fix: allow graceful node shutdown to be overridden

The problem is that these values needs to be set to zero if the kubelet
feature gate is disabled, so we can't assume that we can override zero
value with the proper config, so we have to do an extra check on the
supplied configuration.

Also creates KB article on disabling this feature gate.

Signed-off-by: Andrey Smirnov <andrey.smirnov@talos-systems.com>
This commit is contained in:
Andrey Smirnov 2022-04-27 23:15:09 +03:00
parent 867d38f28f
commit 6e7486f099
No known key found for this signature in database
GPG Key ID: 7B26396447AB6DFD
3 changed files with 107 additions and 56 deletions

View File

@ -294,11 +294,11 @@ func NewKubeletConfiguration(clusterDNS []string, dnsDomain string, extraConfig
config.Logging.Format = "json"
}
if config.ShutdownGracePeriod.Duration == 0 {
if _, overridden := extraConfig["shutdownGracePeriod"]; !overridden && config.ShutdownGracePeriod.Duration == 0 {
config.ShutdownGracePeriod = metav1.Duration{Duration: constants.KubeletShutdownGracePeriod}
}
if config.ShutdownGracePeriodCriticalPods.Duration == 0 {
if _, overridden := extraConfig["shutdownGracePeriodCriticalPods"]; !overridden && config.ShutdownGracePeriodCriticalPods.Duration == 0 {
config.ShutdownGracePeriodCriticalPods = metav1.Duration{Duration: constants.KubeletShutdownGracePeriodCriticalPods}
}

View File

@ -322,63 +322,93 @@ func TestNewKubeletConfigurationFail(t *testing.T) {
}
}
func TestNewKubeletConfigurationSuccess(t *testing.T) {
config, err := k8sctrl.NewKubeletConfiguration(
[]string{"10.0.0.5"}, "cluster.local", map[string]interface{}{
"oomScoreAdj": -300,
"enableDebuggingHandlers": true,
func TestNewKubeletConfigurationMerge(t *testing.T) {
defaultKubeletConfig := kubeletconfig.KubeletConfiguration{
TypeMeta: metav1.TypeMeta{
APIVersion: kubeletconfig.SchemeGroupVersion.String(),
Kind: "KubeletConfiguration",
},
)
require.NoError(t, err)
StaticPodPath: constants.ManifestsDirectory,
Port: constants.KubeletPort,
Authentication: kubeletconfig.KubeletAuthentication{
X509: kubeletconfig.KubeletX509Authentication{
ClientCAFile: constants.KubernetesCACert,
},
Webhook: kubeletconfig.KubeletWebhookAuthentication{
Enabled: pointer.ToBool(true),
},
Anonymous: kubeletconfig.KubeletAnonymousAuthentication{
Enabled: pointer.ToBool(false),
},
},
Authorization: kubeletconfig.KubeletAuthorization{
Mode: kubeletconfig.KubeletAuthorizationModeWebhook,
},
CgroupRoot: "/",
SystemCgroups: constants.CgroupSystem,
KubeletCgroups: constants.CgroupKubelet,
RotateCertificates: true,
ProtectKernelDefaults: true,
Address: "0.0.0.0",
OOMScoreAdj: pointer.ToInt32(constants.KubeletOOMScoreAdj),
ClusterDomain: "cluster.local",
ClusterDNS: []string{"10.0.0.5"},
SerializeImagePulls: pointer.ToBool(false),
FailSwapOn: pointer.ToBool(false),
SystemReserved: map[string]string{
"cpu": constants.KubeletSystemReservedCPU,
"memory": constants.KubeletSystemReservedMemory,
"pid": constants.KubeletSystemReservedPid,
"ephemeral-storage": constants.KubeletSystemReservedEphemeralStorage,
},
Logging: v1alpha1.LoggingConfiguration{
Format: "json",
},
ShutdownGracePeriod: metav1.Duration{Duration: constants.KubeletShutdownGracePeriod},
ShutdownGracePeriodCriticalPods: metav1.Duration{Duration: constants.KubeletShutdownGracePeriodCriticalPods},
StreamingConnectionIdleTimeout: metav1.Duration{Duration: 5 * time.Minute},
TLSMinVersion: "VersionTLS13",
}
assert.Equal(
t, &kubeletconfig.KubeletConfiguration{
TypeMeta: metav1.TypeMeta{
APIVersion: kubeletconfig.SchemeGroupVersion.String(),
Kind: "KubeletConfiguration",
for _, tt := range []struct {
name string
extraConfig map[string]interface{}
expectedOverrides func(*kubeletconfig.KubeletConfiguration)
}{
{
name: "override some",
extraConfig: map[string]interface{}{
"oomScoreAdj": -300,
"enableDebuggingHandlers": true,
},
StaticPodPath: constants.ManifestsDirectory,
Port: constants.KubeletPort,
Authentication: kubeletconfig.KubeletAuthentication{
X509: kubeletconfig.KubeletX509Authentication{
ClientCAFile: constants.KubernetesCACert,
},
Webhook: kubeletconfig.KubeletWebhookAuthentication{
Enabled: pointer.ToBool(true),
},
Anonymous: kubeletconfig.KubeletAnonymousAuthentication{
Enabled: pointer.ToBool(false),
},
expectedOverrides: func(kc *kubeletconfig.KubeletConfiguration) {
kc.OOMScoreAdj = pointer.ToInt32(-300)
kc.EnableDebuggingHandlers = pointer.ToBool(true)
},
Authorization: kubeletconfig.KubeletAuthorization{
Mode: kubeletconfig.KubeletAuthorizationModeWebhook,
},
CgroupRoot: "/",
SystemCgroups: constants.CgroupSystem,
KubeletCgroups: constants.CgroupKubelet,
RotateCertificates: true,
ProtectKernelDefaults: true,
Address: "0.0.0.0",
OOMScoreAdj: pointer.ToInt32(-300),
ClusterDomain: "cluster.local",
ClusterDNS: []string{"10.0.0.5"},
SerializeImagePulls: pointer.ToBool(false),
FailSwapOn: pointer.ToBool(false),
SystemReserved: map[string]string{
"cpu": constants.KubeletSystemReservedCPU,
"memory": constants.KubeletSystemReservedMemory,
"pid": constants.KubeletSystemReservedPid,
"ephemeral-storage": constants.KubeletSystemReservedEphemeralStorage,
},
Logging: v1alpha1.LoggingConfiguration{
Format: "json",
},
ShutdownGracePeriod: metav1.Duration{Duration: constants.KubeletShutdownGracePeriod},
ShutdownGracePeriodCriticalPods: metav1.Duration{Duration: constants.KubeletShutdownGracePeriodCriticalPods},
StreamingConnectionIdleTimeout: metav1.Duration{Duration: 5 * time.Minute},
TLSMinVersion: "VersionTLS13",
EnableDebuggingHandlers: pointer.ToBool(true),
},
config,
)
{
name: "disable graceful shutdown",
extraConfig: map[string]interface{}{
"shutdownGracePeriod": "0s",
"shutdownGracePeriodCriticalPods": "0s",
},
expectedOverrides: func(kc *kubeletconfig.KubeletConfiguration) {
kc.ShutdownGracePeriod = metav1.Duration{}
kc.ShutdownGracePeriodCriticalPods = metav1.Duration{}
},
},
} {
tt := tt
t.Run(tt.name, func(t *testing.T) {
expected := defaultKubeletConfig
tt.expectedOverrides(&expected)
config, err := k8sctrl.NewKubeletConfiguration([]string{"10.0.0.5"}, "cluster.local", tt.extraConfig)
require.NoError(t, err)
assert.Equal(t, &expected, config)
})
}
}

View File

@ -0,0 +1,21 @@
---
title: "Knowledge Base"
weight: 1999
description: "Recipes for common configuration tasks with Talos Linux."
---
## Disabling `GracefulNodeShutdown` on a node
Talos Linux enables [Graceful Node Shutdown](https://kubernetes.io/docs/concepts/architecture/nodes/#graceful-node-shutdown) Kubernetes feature by default.
If this feature should be disabled, modify the `kubelet` part of the machine configuration with:
```yaml
machine:
kubelet:
extraArgs:
feature-gates: GracefulNodeShutdown=false
extraConfig:
shutdownGracePeriod: 0s
shutdownGracePeriodCriticalPods: 0s
```