Kubelet RotateKubeletServerCertificate Set To True
More Info:
The RotateKubeletServerCertificate feature gate should be true so the kubelet automatically rotates its serving certificates, preventing expiry-related failures.
Risk Level
High
Address
Security
Compliance Standards
- CIS AKS
Triage and Remediation
- Remediation
Remediation
Manual Steps
- On every worker node, open the kubelet systemd drop-in file for editing (create it if it does not exist yet):
sudo mkdir -p /etc/systemd/system/kubelet.service.d
sudo vi /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
- In that file, ensure there is an Environment line that includes the RotateKubeletServerCertificate feature gate. For example, add or update:
[Service]
Environment="KUBELET_CERTIFICATE_ARGS=--feature-gates=RotateKubeletServerCertificate=true"
If other Environment="KUBELET_... lines already exist, keep them and only add or adjust the KUBELET_CERTIFICATE_ARGS line.
- If the kubelet is also configured via
/etc/default/kubeletor/var/lib/kubelet/kubeadm-flags.env, check those files to ensure they do not override the feature gate. On every worker node:
sudo grep -n "feature-gates" /etc/default/kubelet /var/lib/kubelet/kubeadm-flags.env 2>/dev/null || true
If you see RotateKubeletServerCertificate=false anywhere, edit the file and remove that part or change it to true.
- Reload systemd configuration and restart kubelet on every worker node:
sudo systemctl daemon-reload
sudo systemctl restart kubelet.service
- Confirm kubelet is healthy on every worker node:
sudo systemctl status kubelet.service --no-pager
- Verify the kubelet process is running with
RotateKubeletServerCertificate=trueon every worker node:
/bin/ps -fC kubelet | grep -o 'RotateKubeletServerCertificate=[^,"]*' || echo "feature gate not found in args"
Using kubectl
kubectl cannot modify kubelet process flags or host-level configuration files, so this finding cannot be fixed via Kubernetes API changes. Configure RotateKubeletServerCertificate in /etc/systemd/system/kubelet.service.d/10-kubeadm.conf on every worker node as described, and follow the steps in the Manual Steps section.
Automation
#!/usr/bin/env bash
# Automation: enable RotateKubeletServerCertificate feature gate for kubelet
# Run on: every worker node (as root)
set -euo pipefail
KUBELET_DROPIN="/etc/systemd/system/kubelet.service.d/10-kubeadm.conf"
BACKUP_SUFFIX="$(date +%Y%m%d%H%M%S)"
if [[ ! -f "$KUBELET_DROPIN" ]]; then
echo "ERROR: $KUBELET_DROPIN not found on this node. Aborting."
exit 1
fi
echo "Backing up $KUBELET_DROPIN to ${KUBELET_DROPIN}.${BACKUP_SUFFIX}.bak"
cp -p "$KUBELET_DROPIN" "${KUBELET_DROPIN}.${BACKUP_SUFFIX}.bak"
# Ensure KUBELET_CERTIFICATE_ARGS line exists
if ! grep -qE '^\s*Environment=.*KUBELET_CERTIFICATE_ARGS=' "$KUBELET_DROPIN"; then
echo "Adding KUBELET_CERTIFICATE_ARGS environment line to $KUBELET_DROPIN"
cat <<'EOF' >>"$KUBELET_DROPIN"
Environment="KUBELET_CERTIFICATE_ARGS="
EOF
fi
# Idempotently ensure RotateKubeletServerCertificate=true is in feature-gates
tmpfile="$(mktemp)"
trap 'rm -f "$tmpfile"' EXIT
awk '
BEGIN {
target="RotateKubeletServerCertificate=true"
}
# Process lines containing KUBELET_CERTIFICATE_ARGS
/KUBELET_CERTIFICATE_ARGS=/ {
# Remove any existing RotateKubeletServerCertificate entry
gsub(/RotateKubeletServerCertificate=[^,"]*/, "", $0)
# Clean up any duplicate commas in feature-gates list
gsub(/,,+/, ",", $0)
gsub(/feature-gates=,/, "feature-gates=", $0)
gsub(/, *"/, "\"", $0)
if ($0 ~ /--feature-gates=/) {
# Append our gate to existing feature-gates
sub(/--feature-gates=([^" ]*)/, "&," target, $0)
# Fix potential leading/trailing commas
gsub(/--feature-gates=,/, "--feature-gates=", $0)
gsub(/,--feature-gates=/, "--feature-gates=", $0)
gsub(/,+"/, "\"", $0)
} else {
# No feature-gates yet; add one
# Insert before closing quote if present
if ($0 ~ /"$/) {
sub(/"$/, " --feature-gates=" target "\"", $0)
} else {
$0 = $0 " --feature-gates=" target
}
}
}
{ print }
' "$KUBELET_DROPIN" >"$tmpfile"
mv "$tmpfile" "$KUBELET_DROPIN"
echo "Reloading systemd and restarting kubelet (this will restart kubelet on this node)..."
systemctl daemon-reload
systemctl restart kubelet.service
echo "Verifying kubelet process has RotateKubeletServerCertificate=true enabled..."
/bin/ps -fC kubelet || {
echo "ERROR: kubelet process not found after restart."
exit 1
}
if /bin/ps -fC kubelet | grep -q -- '--feature-gates=.*RotateKubeletServerCertificate=true'; then
echo "SUCCESS: kubelet is running with RotateKubeletServerCertificate=true on this node."
exit 0
else
echo "ERROR: kubelet is not running with RotateKubeletServerCertificate=true."
echo "Current kubelet command line:"
/bin/ps -fC kubelet
exit 1
fi