Skip to main content

Ensure Kubelet Https Argument Is Enabled

More Info:

Use https for kubelet connections.

Risk Level

High

Address

Security

Compliance Standards

  • CIS Kubernetes

Triage and Remediation

Remediation

Manual Steps
  1. SSH to each control plane node

    ssh root@<control-plane-node-ip>
  2. Backup the API server static pod manifest

    cp -p /etc/kubernetes/manifests/kube-apiserver.yaml \
    /etc/kubernetes/manifests/kube-apiserver.yaml.bak
  3. Edit the manifest to remove the --kubelet-https argument
    Open the file in an editor on the control plane node:

    vi /etc/kubernetes/manifests/kube-apiserver.yaml

    In the command: or args: list for kube-apiserver, delete the entire line containing:

    --kubelet-https=false

    or

    --kubelet-https=true

    (Remove the flag completely, do not re-add it with another value.)
    Save and exit the editor.

    Note: Editing this file will cause the kube-apiserver static pod to be restarted by kubelet.

  4. Wait for the kube-apiserver pod to restart and become Running
    From any machine with kubectl access:

    kubectl get pods -n kube-system -o wide | grep kube-apiserver

    Repeat until the kube-apiserver-<node-name> pod is in Running and READY status.

  5. Verify the kube-apiserver is no longer started with --kubelet-https
    On the same control plane node:

    /bin/ps -ef | grep kube-apiserver | grep -v grep

    Confirm that in the printed command line there is no --kubelet-https= argument present.

Using kubectl

kubectl cannot change the kube-apiserver static pod manifest or its process flags, so this finding cannot be remediated via the Kubernetes API. To fix it, you must edit /etc/kubernetes/manifests/kube-apiserver.yaml directly on every control plane node as described in the Manual Steps section.

Automation
#!/usr/bin/env bash
#
# Automation: Ensure kube-apiserver does not use deprecated --kubelet-https flag
#
# Scope: run on every control plane node (with root or sudo privileges)
# Effect: editing /etc/kubernetes/manifests/kube-apiserver.yaml causes the
# kube-apiserver static pod to be recreated automatically by kubelet.

set -euo pipefail

API_MANIFEST="/etc/kubernetes/manifests/kube-apiserver.yaml"
BACKUP_DIR="/etc/kubernetes/manifests/backup-$(date +%Y%m%d)"
CHANGED=0

if [ ! -f "$API_MANIFEST" ]; then
echo "ERROR: $API_MANIFEST not found on this node; is this a control plane node?"
exit 1
fi

mkdir -p "$BACKUP_DIR"

backup_file="${BACKUP_DIR}/kube-apiserver.yaml.$(date +%H%M%S)"
cp -p "$API_MANIFEST" "$backup_file"
echo "Backup of $API_MANIFEST created at $backup_file"

# Remove any occurrence of the --kubelet-https argument line
if grep -q -- '--kubelet-https' "$API_MANIFEST"; then
# This sed deletes any line containing --kubelet-https (with or without value)
# while preserving all other content.
sed '/--kubelet-https/d' "$API_MANIFEST" > "${API_MANIFEST}.tmp"
mv "${API_MANIFEST}.tmp" "$API_MANIFEST"
CHANGED=1
echo "Removed --kubelet-https from $API_MANIFEST"
else
echo "--kubelet-https argument not present in $API_MANIFEST; no changes made."
fi

# If we changed the manifest, kubelet will automatically restart the apiserver pod.
if [ "$CHANGED" -eq 1 ]; then
echo "Waiting up to 120 seconds for kube-apiserver pod to be recreated..."
# Optional wait loop (does not fail script if unavailable)
end=$((SECONDS+120))
while [ $SECONDS -lt $end ]; do
if /bin/ps -ef | grep '[k]ube-apiserver' >/dev/null 2>&1; then
break
fi
sleep 5
done
fi

echo "Verification: ensuring kube-apiserver is not started with --kubelet-https"

if /bin/ps -ef | grep '[k]ube-apiserver' | grep -- '--kubelet-https' >/dev/null 2>&1; then
echo "FAIL: kube-apiserver still running with --kubelet-https argument:"
/bin/ps -ef | grep kube-apiserver | grep -v grep
exit 2
fi

echo "PASS: kube-apiserver is running without --kubelet-https argument."
/bin/ps -ef | grep kube-apiserver | grep -v grep || true

Additional Reading: