fix(kubelet): handle parsing of imageMaximumGCAge and imageMinimumGCAge in kubelet config

- add unit tests for image GC duration
- change the string type of the image GC field to metav1.Duration
- remove unnecessary comments
This commit is contained in:
huhouhua 2025-06-30 01:03:22 +08:00
parent adb6d81a9f
commit c41bf2c2ff
8 changed files with 52 additions and 12 deletions

View File

@ -248,6 +248,12 @@ func buildKubeletComponentConfig(kubeletConfig *kops.KubeletConfigSpec, provider
if kubeletConfig.ShutdownGracePeriodCriticalPods != nil { if kubeletConfig.ShutdownGracePeriodCriticalPods != nil {
componentConfig.ShutdownGracePeriodCriticalPods = *kubeletConfig.ShutdownGracePeriodCriticalPods componentConfig.ShutdownGracePeriodCriticalPods = *kubeletConfig.ShutdownGracePeriodCriticalPods
} }
if kubeletConfig.ImageMaximumGCAge != nil {
componentConfig.ImageMaximumGCAge = *kubeletConfig.ImageMaximumGCAge
}
if kubeletConfig.ImageMinimumGCAge != nil {
componentConfig.ImageMinimumGCAge = *kubeletConfig.ImageMinimumGCAge
}
componentConfig.MemorySwap.SwapBehavior = kubeletConfig.MemorySwapBehavior componentConfig.MemorySwap.SwapBehavior = kubeletConfig.MemorySwapBehavior
s := runtime.NewScheme() s := runtime.NewScheme()

View File

@ -31,6 +31,7 @@ import (
"k8s.io/kops/pkg/apis/nodeup" "k8s.io/kops/pkg/apis/nodeup"
"k8s.io/kops/pkg/assets" "k8s.io/kops/pkg/assets"
"k8s.io/kops/pkg/client/simple/vfsclientset" "k8s.io/kops/pkg/client/simple/vfsclientset"
"k8s.io/kops/pkg/flagbuilder"
"k8s.io/kops/pkg/pki" "k8s.io/kops/pkg/pki"
"k8s.io/kops/pkg/testutils" "k8s.io/kops/pkg/testutils"
"k8s.io/kops/upup/pkg/fi" "k8s.io/kops/upup/pkg/fi"
@ -399,6 +400,8 @@ func Test_BuildComponentConfigFile(t *testing.T) {
componentConfig := kops.KubeletConfigSpec{ componentConfig := kops.KubeletConfigSpec{
ShutdownGracePeriod: &metav1.Duration{Duration: 30 * time.Second}, ShutdownGracePeriod: &metav1.Duration{Duration: 30 * time.Second},
ShutdownGracePeriodCriticalPods: &metav1.Duration{Duration: 10 * time.Second}, ShutdownGracePeriodCriticalPods: &metav1.Duration{Duration: 10 * time.Second},
ImageMaximumGCAge: &metav1.Duration{Duration: 30 * time.Hour},
ImageMinimumGCAge: &metav1.Duration{Duration: 30 * time.Minute},
} }
_, err := buildKubeletComponentConfig(&componentConfig, "") _, err := buildKubeletComponentConfig(&componentConfig, "")
@ -406,3 +409,34 @@ func Test_BuildComponentConfigFile(t *testing.T) {
t.Errorf("Failed to build component config file: %v", err) t.Errorf("Failed to build component config file: %v", err)
} }
} }
func Test_Kubelet_BuildFlags(t *testing.T) {
grid := []struct {
config kops.KubeletConfigSpec
expected string
}{
{
kops.KubeletConfigSpec{
ImageMaximumGCAge: &metav1.Duration{Duration: 30 * time.Hour},
},
"",
},
{
kops.KubeletConfigSpec{
ImageMinimumGCAge: &metav1.Duration{Duration: 30 * time.Minute},
},
"",
},
}
for _, g := range grid {
actual, err := flagbuilder.BuildFlags(&g.config)
if err != nil {
t.Errorf("error building flags for %v: %v", g.config, err)
continue
}
if actual != g.expected {
t.Errorf("flags did not match. actual=%q expected=%q", actual, g.expected)
}
}
}

View File

@ -132,11 +132,11 @@ type KubeletConfigSpec struct {
// computed (such as IPSEC). // computed (such as IPSEC).
NetworkPluginMTU *int32 `json:"networkPluginMTU,omitempty" flag:"network-plugin-mtu"` NetworkPluginMTU *int32 `json:"networkPluginMTU,omitempty" flag:"network-plugin-mtu"`
// imageMinimumGCAge is the minimum age for an unused image before it is garbage collected. Default: "2m" // imageMinimumGCAge is the minimum age for an unused image before it is garbage collected. Default: "2m"
ImageMinimumGCAge *string `json:"imageMinimumGCAge,omitempty" flag:"image-minimum-gc-age"` ImageMinimumGCAge *metav1.Duration `json:"imageMinimumGCAge,omitempty"`
// imageMaximumGCAge is the maximum age an image can be unused before it is garbage collected. // imageMaximumGCAge is the maximum age an image can be unused before it is garbage collected.
// The default of this field is "0s", which disables this field--meaning images won't be garbage // The default of this field is "0s", which disables this field--meaning images won't be garbage
// collected based on being unused for too long. Default: "0s" (disabled) // collected based on being unused for too long. Default: "0s" (disabled)
ImageMaximumGCAge *string `json:"imageMaximumGCAge,omitempty" flag:"image-maximum-gc-age"` ImageMaximumGCAge *metav1.Duration `json:"imageMaximumGCAge,omitempty"`
// ImageGCHighThresholdPercent is the percent of disk usage after which // ImageGCHighThresholdPercent is the percent of disk usage after which
// image garbage collection is always run. // image garbage collection is always run.
ImageGCHighThresholdPercent *int32 `json:"imageGCHighThresholdPercent,omitempty" flag:"image-gc-high-threshold"` ImageGCHighThresholdPercent *int32 `json:"imageGCHighThresholdPercent,omitempty" flag:"image-gc-high-threshold"`

View File

@ -132,11 +132,11 @@ type KubeletConfigSpec struct {
// computed (such as IPSEC). // computed (such as IPSEC).
NetworkPluginMTU *int32 `json:"networkPluginMTU,omitempty" flag:"network-plugin-mtu"` NetworkPluginMTU *int32 `json:"networkPluginMTU,omitempty" flag:"network-plugin-mtu"`
// imageMinimumGCAge is the minimum age for an unused image before it is garbage collected. Default: "2m" // imageMinimumGCAge is the minimum age for an unused image before it is garbage collected. Default: "2m"
ImageMinimumGCAge *string `json:"imageMinimumGCAge,omitempty" flag:"image-minimum-gc-age"` ImageMinimumGCAge *metav1.Duration `json:"imageMinimumGCAge,omitempty"`
// imageMaximumGCAge is the maximum age an image can be unused before it is garbage collected. // imageMaximumGCAge is the maximum age an image can be unused before it is garbage collected.
// The default of this field is "0s", which disables this field--meaning images won't be garbage // The default of this field is "0s", which disables this field--meaning images won't be garbage
// collected based on being unused for too long. Default: "0s" (disabled) // collected based on being unused for too long. Default: "0s" (disabled)
ImageMaximumGCAge *string `json:"imageMaximumGCAge,omitempty" flag:"image-maximum-gc-age"` ImageMaximumGCAge *metav1.Duration `json:"imageMaximumGCAge,omitempty"`
// ImageGCHighThresholdPercent is the percent of disk usage after which // ImageGCHighThresholdPercent is the percent of disk usage after which
// image garbage collection is always run. // image garbage collection is always run.
ImageGCHighThresholdPercent *int32 `json:"imageGCHighThresholdPercent,omitempty" flag:"image-gc-high-threshold"` ImageGCHighThresholdPercent *int32 `json:"imageGCHighThresholdPercent,omitempty" flag:"image-gc-high-threshold"`

View File

@ -4197,12 +4197,12 @@ func (in *KubeletConfigSpec) DeepCopyInto(out *KubeletConfigSpec) {
} }
if in.ImageMinimumGCAge != nil { if in.ImageMinimumGCAge != nil {
in, out := &in.ImageMinimumGCAge, &out.ImageMinimumGCAge in, out := &in.ImageMinimumGCAge, &out.ImageMinimumGCAge
*out = new(string) *out = new(v1.Duration)
**out = **in **out = **in
} }
if in.ImageMaximumGCAge != nil { if in.ImageMaximumGCAge != nil {
in, out := &in.ImageMaximumGCAge, &out.ImageMaximumGCAge in, out := &in.ImageMaximumGCAge, &out.ImageMaximumGCAge
*out = new(string) *out = new(v1.Duration)
**out = **in **out = **in
} }
if in.ImageGCHighThresholdPercent != nil { if in.ImageGCHighThresholdPercent != nil {

View File

@ -131,11 +131,11 @@ type KubeletConfigSpec struct {
// computed (such as IPSEC). // computed (such as IPSEC).
NetworkPluginMTU *int32 `json:"networkPluginMTU,omitempty" flag:"network-plugin-mtu"` NetworkPluginMTU *int32 `json:"networkPluginMTU,omitempty" flag:"network-plugin-mtu"`
// imageMinimumGCAge is the minimum age for an unused image before it is garbage collected. Default: "2m" // imageMinimumGCAge is the minimum age for an unused image before it is garbage collected. Default: "2m"
ImageMinimumGCAge *string `json:"imageMinimumGCAge,omitempty" flag:"image-minimum-gc-age"` ImageMinimumGCAge *metav1.Duration `json:"imageMinimumGCAge,omitempty"`
// imageMaximumGCAge is the maximum age an image can be unused before it is garbage collected. // imageMaximumGCAge is the maximum age an image can be unused before it is garbage collected.
// The default of this field is "0s", which disables this field--meaning images won't be garbage // The default of this field is "0s", which disables this field--meaning images won't be garbage
// collected based on being unused for too long. Default: "0s" (disabled) // collected based on being unused for too long. Default: "0s" (disabled)
ImageMaximumGCAge *string `json:"imageMaximumGCAge,omitempty" flag:"image-maximum-gc-age"` ImageMaximumGCAge *metav1.Duration `json:"imageMaximumGCAge,omitempty"`
// ImageGCHighThresholdPercent is the percent of disk usage after which // ImageGCHighThresholdPercent is the percent of disk usage after which
// image garbage collection is always run. // image garbage collection is always run.
ImageGCHighThresholdPercent *int32 `json:"imageGCHighThresholdPercent,omitempty" flag:"image-gc-high-threshold"` ImageGCHighThresholdPercent *int32 `json:"imageGCHighThresholdPercent,omitempty" flag:"image-gc-high-threshold"`

View File

@ -4176,12 +4176,12 @@ func (in *KubeletConfigSpec) DeepCopyInto(out *KubeletConfigSpec) {
} }
if in.ImageMinimumGCAge != nil { if in.ImageMinimumGCAge != nil {
in, out := &in.ImageMinimumGCAge, &out.ImageMinimumGCAge in, out := &in.ImageMinimumGCAge, &out.ImageMinimumGCAge
*out = new(string) *out = new(v1.Duration)
**out = **in **out = **in
} }
if in.ImageMaximumGCAge != nil { if in.ImageMaximumGCAge != nil {
in, out := &in.ImageMaximumGCAge, &out.ImageMaximumGCAge in, out := &in.ImageMaximumGCAge, &out.ImageMaximumGCAge
*out = new(string) *out = new(v1.Duration)
**out = **in **out = **in
} }
if in.ImageGCHighThresholdPercent != nil { if in.ImageGCHighThresholdPercent != nil {

View File

@ -4279,12 +4279,12 @@ func (in *KubeletConfigSpec) DeepCopyInto(out *KubeletConfigSpec) {
} }
if in.ImageMinimumGCAge != nil { if in.ImageMinimumGCAge != nil {
in, out := &in.ImageMinimumGCAge, &out.ImageMinimumGCAge in, out := &in.ImageMinimumGCAge, &out.ImageMinimumGCAge
*out = new(string) *out = new(v1.Duration)
**out = **in **out = **in
} }
if in.ImageMaximumGCAge != nil { if in.ImageMaximumGCAge != nil {
in, out := &in.ImageMaximumGCAge, &out.ImageMaximumGCAge in, out := &in.ImageMaximumGCAge, &out.ImageMaximumGCAge
*out = new(string) *out = new(v1.Duration)
**out = **in **out = **in
} }
if in.ImageGCHighThresholdPercent != nil { if in.ImageGCHighThresholdPercent != nil {