Verify Read Only Port Argument Is Set 0
More Info:
Disable the read-only port.
Risk Level
Medium
Address
Security
Compliance Standards
- CIS Kubernetes
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
On every worker node, check how kubelet is configured (file vs flags):
ps -fC kubeletInspect the command line: if you see
--config=/var/lib/kubelet/config.yamlit is using the config file; if you see--read-only-port=it is using flags. -
If using the kubelet config file, edit it to disable the read-only port:
sudo sed -i 's/^[[:space:]]*readOnlyPort:.*/readOnlyPort: 0/' /var/lib/kubelet/config.yamlIf there is no
readOnlyPortline, add it under the top-levelkubeletConfigurationblock, for example:sudo sh -c 'printf "\nreadOnlyPort: 0\n" >> /var/lib/kubelet/config.yaml' -
If using command-line arguments, edit the kubelet systemd drop-in on each worker node:
sudo sed -i 's/--read-only-port=[0-9]\+/--read-only-port=0/' /etc/systemd/system/kubelet.service.d/10-kubeadm.confIf
--read-only-portis missing, add it to theKUBELET_SYSTEM_PODS_ARGS(or the line with other--flags), for example:sudo sed -i 's#^\(.*KUBELET_SYSTEM_PODS_ARGS=.*\)"#\1 --read-only-port=0"#' /etc/systemd/system/kubelet.service.d/10-kubeadm.conf -
On every worker node, reload systemd and restart kubelet (this will restart the kubelet and may briefly impact pod scheduling/health reporting on that node):
sudo systemctl daemon-reloadsudo systemctl restart kubelet.service -
Verify on every worker node that kubelet is running with the read-only port disabled:
ps -fC kubeletConfirm either that:
- the kubelet command line contains
--read-only-port=0, or - kubelet is using
/var/lib/kubelet/config.yamland that file containsreadOnlyPort: 0.
- the kubelet command line contains
Using kubectl
kubectl cannot modify kubelet process flags or its config file on worker nodes; this setting must be changed directly on each node’s /var/lib/kubelet/config.yaml or in the kubelet systemd unit. Refer to the Manual Steps section for the exact on-node configuration and restart instructions.
Automation
#!/usr/bin/env bash
#
# Fix: Ensure kubelet read-only port is disabled (readOnlyPort: 0)
# Scope: every worker node
#
# Usage:
# Run as root on each worker node:
# bash ./fix-kubelet-readonlyport.sh
#
# Idempotent: safe to re-run.
set -euo pipefail
KUBELET_CONFIG="/var/lib/kubelet/config.yaml"
SYSTEMD_DROPIN="/etc/systemd/system/kubelet.service.d/10-kubeadm.conf"
BACKUP_SUFFIX=".$(date +%Y%m%d%H%M%S).bak"
log() { printf '[%s] %s\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "$*"; }
require_root() {
if [ "$(id -u)" -ne 0 ]; then
log "ERROR: This script must be run as root."
exit 1
fi
}
backup_file() {
local f="$1"
if [ -f "$f" ]; then
cp -p "$f" "$f$BACKUP_SUFFIX"
log "Backup created: $f$BACKUP_SUFFIX"
fi
}
ensure_readonlyport_in_config() {
if [ ! -f "$KUBELET_CONFIG" ]; then
log "Kubelet config file not found at $KUBELET_CONFIG, skipping file-based config."
return 1
fi
backup_file "$KUBELET_CONFIG"
if grep -qE '^\s*readOnlyPort:' "$KUBELET_CONFIG"; then
# Replace existing key
sed -i 's/^\(\s*readOnlyPort:\).*/\1 0/' "$KUBELET_CONFIG"
log "Updated existing readOnlyPort entry to 0 in $KUBELET_CONFIG"
else
# Append key at top-level (2 space indent is acceptable for this scalar)
printf '\nreadOnlyPort: 0\n' >> "$KUBELET_CONFIG"
log "Appended readOnlyPort: 0 to $KUBELET_CONFIG"
fi
return 0
}
ensure_readonlyport_in_systemd() {
if [ ! -f "$SYSTEMD_DROPIN" ]; then
log "Systemd drop-in not found at $SYSTEMD_DROPIN, skipping CLI-arg config."
return 1
fi
backup_file "$SYSTEMD_DROPIN"
# Ensure KUBELET_SYSTEM_PODS_ARGS exists in Environment line
if grep -q 'KUBELET_SYSTEM_PODS_ARGS' "$SYSTEMD_DROPIN"; then
:
else
# Add an Environment line if missing
echo 'Environment="KUBELET_SYSTEM_PODS_ARGS="' >> "$SYSTEMD_DROPIN"
log "Added KUBELET_SYSTEM_PODS_ARGS environment definition to $SYSTEMD_DROPIN"
fi
# Remove any existing --read-only-port flag
sed -i 's/--read-only-port=[^" ]*//g' "$SYSTEMD_DROPIN"
# Add --read-only-port=0 into KUBELET_SYSTEM_PODS_ARGS
# If the var is empty, just set this flag; otherwise append.
perl -0777 -pi -e '
s/(Environment="[^"]*KUBELET_SYSTEM_PODS_ARGS=)([^"]*)"/
my $prefix = $1; my $val = $2;
$val =~ s/\s+$//;
if ($val =~ /--read-only-port=0\b/) { $prefix.$val."\"" }
elsif ($val eq "") { $prefix."--read-only-port=0\"" }
else { $prefix.$val." --read-only-port=0\"" }
/eg
' "$SYSTEMD_DROPIN"
log "Ensured --read-only-port=0 is present in KUBELET_SYSTEM_PODS_ARGS in $SYSTEMD_DROPIN"
return 0
}
restart_kubelet() {
log "Reloading systemd and restarting kubelet (this will restart the kubelet process)..."
systemctl daemon-reload
systemctl restart kubelet.service
log "kubelet restarted."
}
verify() {
log "Verifying kubelet read-only port is disabled..."
# Check via ps flags
if /bin/ps -fC kubelet 2>/dev/null | grep -q -- '--read-only-port=0'; then
log "Verification: kubelet process has --read-only-port=0 flag."
else
log "WARNING: kubelet process does not show --read-only-port=0 flag in ps output."
fi
# If config file exists, also verify its content
if [ -f "$KUBELET_CONFIG" ]; then
if grep -qE '^\s*readOnlyPort:\s*0\b' "$KUBELET_CONFIG"; then
log "Verification: $KUBELET_CONFIG contains readOnlyPort: 0"
else
log "WARNING: $KUBELET_CONFIG does not contain readOnlyPort: 0"
fi
fi
# Final display of kubelet command line for manual confirmation
log "Current kubelet command line:"
/bin/ps -fC kubelet || true
}
main() {
require_root
local cfg_ok=1
local sysd_ok=1
if ensure_readonlyport_in_config; then
cfg_ok=0
fi
if ensure_readonlyport_in_systemd; then
sysd_ok=0
fi
if [ "$cfg_ok" -ne 0 ] && [ "$sysd_ok" -ne 0 ]; then
log "ERROR: Neither $KUBELET_CONFIG nor $SYSTEMD_DROPIN could be updated. Please review manually."
exit 1
fi
restart_kubelet
verify
}
main "$@"