1
16
17 package e2enode
18
19 import (
20 "context"
21 "os"
22 "path/filepath"
23 "time"
24
25 "github.com/onsi/ginkgo/v2"
26 "github.com/onsi/gomega"
27 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
28 kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config"
29 "k8s.io/kubernetes/test/e2e/framework"
30 "k8s.io/kubernetes/test/e2e/nodefeature"
31 )
32
33 var _ = SIGDescribe("Kubelet Config", framework.WithSlow(), framework.WithSerial(), framework.WithDisruptive(), nodefeature.KubeletConfigDropInDir, func() {
34 f := framework.NewDefaultFramework("kubelet-config-drop-in-dir-test")
35 ginkgo.Context("when merging drop-in configs", func() {
36 var oldcfg *kubeletconfig.KubeletConfiguration
37 ginkgo.BeforeEach(func(ctx context.Context) {
38 var err error
39 oldcfg, err = getCurrentKubeletConfig(ctx)
40 framework.ExpectNoError(err)
41 })
42 ginkgo.AfterEach(func(ctx context.Context) {
43 files, err := filepath.Glob(filepath.Join(framework.TestContext.KubeletConfigDropinDir, "*"+".conf"))
44 framework.ExpectNoError(err)
45 for _, file := range files {
46 err := os.Remove(file)
47 framework.ExpectNoError(err)
48 }
49 updateKubeletConfig(ctx, f, oldcfg, true)
50 })
51 ginkgo.It("should merge kubelet configs correctly", func(ctx context.Context) {
52
53 initialConfig, err := getCurrentKubeletConfig(ctx)
54 framework.ExpectNoError(err)
55
56 ginkgo.By("Stopping the kubelet")
57 restartKubelet := stopKubelet()
58
59
60 gomega.Eventually(ctx, func() bool {
61 return kubeletHealthCheck(kubeletHealthCheckURL)
62 }, f.Timeouts.PodStart, f.Timeouts.Poll).Should(gomega.BeFalse())
63
64 configDir := framework.TestContext.KubeletConfigDropinDir
65
66 contents := []byte(`apiVersion: kubelet.config.k8s.io/v1beta1
67 kind: KubeletConfiguration
68 port: 10255
69 readOnlyPort: 10257
70 clusterDNS:
71 - 192.168.1.10
72 systemReserved:
73 memory: 1Gi
74 authorization:
75 mode: Webhook
76 webhook:
77 cacheAuthorizedTTL: "5m"
78 cacheUnauthorizedTTL: "30s"
79 staticPodURLHeader:
80 kubelet-api-support:
81 - "Authorization: 234APSDFA"
82 - "X-Custom-Header: 123"
83 custom-static-pod:
84 - "Authorization: 223EWRWER"
85 - "X-Custom-Header: 456"
86 shutdownGracePeriodByPodPriority:
87 - priority: 1
88 shutdownGracePeriodSeconds: 60
89 - priority: 2
90 shutdownGracePeriodSeconds: 45
91 - priority: 3
92 shutdownGracePeriodSeconds: 30
93 featureGates:
94 DisableKubeletCloudCredentialProviders: true
95 PodAndContainerStatsFromCRI: true`)
96 framework.ExpectNoError(os.WriteFile(filepath.Join(configDir, "10-kubelet.conf"), contents, 0755))
97 contents = []byte(`apiVersion: kubelet.config.k8s.io/v1beta1
98 kind: KubeletConfiguration
99 clusterDNS:
100 - 192.168.1.1
101 - 192.168.1.5
102 - 192.168.1.8
103 port: 8080
104 cpuManagerReconcilePeriod: 0s
105 systemReserved:
106 memory: 2Gi
107 authorization:
108 mode: Webhook
109 webhook:
110 cacheAuthorizedTTL: "6m"
111 cacheUnauthorizedTTL: "40s"
112 staticPodURLHeader:
113 kubelet-api-support:
114 - "Authorization: 8945AFSG1"
115 - "X-Custom-Header: 987"
116 custom-static-pod:
117 - "Authorization: 223EWRWER"
118 - "X-Custom-Header: 345"
119 shutdownGracePeriodByPodPriority:
120 - priority: 1
121 shutdownGracePeriodSeconds: 19
122 - priority: 2
123 shutdownGracePeriodSeconds: 41
124 - priority: 6
125 shutdownGracePeriodSeconds: 30
126 featureGates:
127 PodAndContainerStatsFromCRI: false
128 DynamicResourceAllocation: true`)
129 framework.ExpectNoError(os.WriteFile(filepath.Join(configDir, "20-kubelet.conf"), contents, 0755))
130 ginkgo.By("Restarting the kubelet")
131 restartKubelet()
132
133 gomega.Eventually(ctx, func() bool {
134 return kubeletHealthCheck(kubeletHealthCheckURL)
135 }, f.Timeouts.PodStart, f.Timeouts.Poll).Should(gomega.BeTrue())
136
137 mergedConfig, err := getCurrentKubeletConfig(ctx)
138 framework.ExpectNoError(err)
139
140
141 initialConfig.Port = int32(8080)
142 initialConfig.ReadOnlyPort = int32(10257)
143 initialConfig.SystemReserved = map[string]string{
144 "memory": "2Gi",
145 }
146 initialConfig.ClusterDNS = []string{"192.168.1.1", "192.168.1.5", "192.168.1.8"}
147
148 initialConfig.CPUManagerReconcilePeriod = metav1.Duration{Duration: time.Duration(0)}
149
150
151 initialConfig.CPUCFSQuotaPeriod = metav1.Duration{Duration: time.Duration(100000000)}
152
153 initialConfig.StaticPodURLHeader = map[string][]string{
154 "kubelet-api-support": {"Authorization: 8945AFSG1", "X-Custom-Header: 987"},
155 "custom-static-pod": {"Authorization: 223EWRWER", "X-Custom-Header: 345"},
156 }
157
158 initialConfig.ShutdownGracePeriodByPodPriority = []kubeletconfig.ShutdownGracePeriodByPodPriority{
159 {Priority: 1, ShutdownGracePeriodSeconds: 19},
160 {Priority: 2, ShutdownGracePeriodSeconds: 41},
161 {Priority: 6, ShutdownGracePeriodSeconds: 30},
162 }
163
164 initialConfig.Authorization = kubeletconfig.KubeletAuthorization{
165 Mode: "Webhook",
166 Webhook: kubeletconfig.KubeletWebhookAuthorization{
167 CacheAuthorizedTTL: metav1.Duration{Duration: time.Duration(6 * time.Minute)},
168 CacheUnauthorizedTTL: metav1.Duration{Duration: time.Duration(40 * time.Second)},
169 },
170 }
171
172 initialConfig.FeatureGates = map[string]bool{"DisableKubeletCloudCredentialProviders": true, "PodAndContainerStatsFromCRI": false, "DynamicResourceAllocation": true}
173
174 gomega.Expect(initialConfig).To(gomega.BeComparableTo(mergedConfig), "Merged kubelet config does not match the expected configuration.")
175 })
176 })
177
178 })
179
View as plain text