API Server Should Enable The EventRateLimit Admission Plugin
More Info:
Verifies that the EventRateLimit admission plugin is enabled to limit the rate of API requests and protect the API server from denial-of-service.
Risk Level
High
Address
Security
Compliance Standards
- CIS Kubernetes
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
Create the EventRateLimit configuration file (every control plane node)
sudo mkdir -p /etc/kubernetes/admissionsudo tee /etc/kubernetes/admission/event-rate-limit.yaml >/dev/null << 'EOF'apiVersion: apiserver.k8s.io/v1alpha1kind: AdmissionConfigurationplugins:- name: EventRateLimitpath: /etc/kubernetes/admission/event-rate-limit-config.yamlEOFsudo tee /etc/kubernetes/admission/event-rate-limit-config.yaml >/dev/null << 'EOF'apiVersion: eventratelimit.admission.k8s.io/v1alpha1kind: Configurationlimits:- type: Namespaceqps: 50burst: 100- type: Userqps: 10burst: 20EOF -
Back up the existing API server static pod manifest (every control plane node)
sudo cp -a /etc/kubernetes/manifests/kube-apiserver.yaml \/etc/kubernetes/manifests/kube-apiserver.yaml.backup.$(date +%F-%H%M%S) -
Edit the API server manifest to enable EventRateLimit (every control plane node)
Open the file:sudo vi /etc/kubernetes/manifests/kube-apiserver.yamlIn the
spec.containers[0].commandlist:- Ensure
--enable-admission-pluginsincludesEventRateLimit(add it to the comma‑separated list, do not remove existing plugins), for example:- --enable-admission-plugins=NodeRestriction,EventRateLimit - Add or update the admission config flag to point to the file you created:
- --admission-control-config-file=/etc/kubernetes/admission/event-rate-limit.yaml
- Ensure
-
Ensure the admission config files are mounted into the API server pod (every control plane node)
In the same manifest, under the containervolumeMounts, add if not present:- mountPath: /etc/kubernetes/admissionname: admission-configreadOnly: trueUnder
volumes, add if not present:- name: admission-confighostPath:path: /etc/kubernetes/admissiontype: DirectoryOrCreate -
Allow the API server to restart and stabilize (every control plane node)
Saving/etc/kubernetes/manifests/kube-apiserver.yamlcauses the kubelet to restart thekube-apiserverstatic pod automatically. Wait and confirm the pod is running:sudo crictl ps | grep kube-apiserver || sudo docker ps | grep kube-apiserver -
Verify EventRateLimit is enabled and configured (every control plane node)
/bin/ps -ef | grep kube-apiserver | grep -v grep \| grep -- '--enable-admission-plugins' \| grep 'EventRateLimit' && \/bin/ps -ef | grep kube-apiserver | grep -v grep \| grep -- '--admission-control-config-file=/etc/kubernetes/admission/event-rate-limit.yaml'Optionally, confirm the flag values inside the container:
kubectl -n kube-system get pod -l component=kube-apiserver -o wide
Using kubectl
kubectl cannot be used to enable the EventRateLimit admission plugin because this setting is defined in the API server’s static pod manifest on each control plane node at /etc/kubernetes/manifests/kube-apiserver.yaml. To remediate this finding, follow the guidance in the Manual Steps section and update the host-level configuration directly on the control plane nodes.
Automation
#!/usr/bin/env bash
#
# Automates enabling the EventRateLimit admission plugin on all control plane nodes.
# - Creates an EventRateLimit config file at /etc/kubernetes/admission-control-eventratelimit.yaml
# - Ensures kube-apiserver manifest has:
# --enable-admission-plugins=...,EventRateLimit,...
# --admission-control-config-file=/etc/kubernetes/admission-control-eventratelimit.yaml
# - Safe to re-run.
#
# RUN ON: each control plane node (with root privileges)
set -euo pipefail
APISERVER_MANIFEST="/etc/kubernetes/manifests/kube-apiserver.yaml"
EVENT_RL_CFG="/etc/kubernetes/admission-control-eventratelimit.yaml"
backup_file() {
local f="$1"
if [ -f "$f" ] && [ ! -f "${f}.pre-eventratelimit.bak" ]; then
cp -p "$f" "${f}.pre-eventratelimit.bak"
fi
}
ensure_eventratelimit_config() {
mkdir -p "$(dirname "$EVENT_RL_CFG")"
backup_file "$EVENT_RL_CFG" || true
cat > "$EVENT_RL_CFG.tmp" <<'EOF'
apiVersion: apiserver.k8s.io/v1alpha1
kind: AdmissionConfiguration
plugins:
- name: EventRateLimit
path: /etc/kubernetes/eventconfig.yaml
---
apiVersion: eventratelimit.admission.k8s.io/v1alpha1
kind: Configuration
limits:
- type: Namespace
qps: 50
burst: 100
- type: User
qps: 20
burst: 50
EOF
# Optional: eventconfig referenced above
cat > /etc/kubernetes/eventconfig.yaml.tmp <<'EOF'
apiVersion: eventratelimit.admission.k8s.io/v1alpha1
kind: Configuration
limits:
- type: Namespace
qps: 50
burst: 100
- type: User
qps: 20
burst: 50
EOF
mv "$EVENT_RL_CFG.tmp" "$EVENT_RL_CFG"
chmod 600 "$EVENT_RL_CFG"
mv /etc/kubernetes/eventconfig.yaml.tmp /etc/kubernetes/eventconfig.yaml
chmod 600 /etc/kubernetes/eventconfig.yaml
}
patch_apiserver_manifest() {
if [ ! -f "$APISERVER_MANIFEST" ]; then
echo "ERROR: $APISERVER_MANIFEST not found; this script is for static pod control planes." >&2
exit 1
fi
backup_file "$APISERVER_MANIFEST"
# 1) Ensure --enable-admission-plugins has EventRateLimit
if grep -q -- '--enable-admission-plugins=' "$APISERVER_MANIFEST"; then
# If EventRateLimit is missing, add it
if ! grep -q -- '--enable-admission-plugins=.*EventRateLimit' "$APISERVER_MANIFEST"; then
sed -i -E \
's/(--enable-admission-plugins=)([^" ]*)/\1\2,EventRateLimit/' \
"$APISERVER_MANIFEST"
fi
else
# Add a new flag line under the kube-apiserver container args
# This assumes a standard kubeadm manifest with "- kube-apiserver" line.
if grep -q '^\s*- kube-apiserver' "$APISERVER_MANIFEST"; then
sed -i \
'/^\s*- kube-apiserver/a\ - --enable-admission-plugins=EventRateLimit' \
"$APISERVER_MANIFEST"
else
echo "WARNING: Could not find '- kube-apiserver' to attach --enable-admission-plugins; please edit $APISERVER_MANIFEST manually." >&2
fi
fi
# 2) Ensure --admission-control-config-file points to our config
if grep -q -- '--admission-control-config-file=' "$APISERVER_MANIFEST"; then
sed -i -E \
"s#--admission-control-config-file=[^\" ]*#--admission-control-config-file=${EVENT_RL_CFG}#g" \
"$APISERVER_MANIFEST"
else
if grep -q '^\s*- kube-apiserver' "$APISERVER_MANIFEST"; then
sed -i \
"/^\s*- kube-apiserver/a\ - --admission-control-config-file=${EVENT_RL_CFG}" \
"$APISERVER_MANIFEST"
else
echo "WARNING: Could not find '- kube-apiserver' to attach --admission-control-config-file; please edit $APISERVER_MANIFEST manually." >&2
fi
fi
echo "NOTE: Editing $APISERVER_MANIFEST will cause the kube-apiserver static pod to restart on this node."
}
verify() {
echo "Waiting 30s for kube-apiserver static pod restart..."
sleep 30
echo "Verifying kube-apiserver process flags..."
if /bin/ps -ef | grep kube-apiserver | grep -v grep | grep -q -- '--enable-admission-plugins=.*EventRateLimit'; then
echo "OK: EventRateLimit is present in --enable-admission-plugins."
else
echo "FAIL: EventRateLimit not found in --enable-admission-plugins." >&2
/bin/ps -ef | grep kube-apiserver | grep -v grep || true
exit 1
fi
if /bin/ps -ef | grep kube-apiserver | grep -v grep | grep -q -- "--admission-control-config-file=${EVENT_RL_CFG}"; then
echo "OK: --admission-control-config-file points to ${EVENT_RL_CFG}."
else
echo "FAIL: --admission-control-config-file not correctly set to ${EVENT_RL_CFG}." >&2
/bin/ps -ef | grep kube-apiserver | grep -v grep || true
exit 1
fi
}
main() {
ensure_eventratelimit_config
patch_apiserver_manifest
verify
}
main "$@"