Skip to main content

Ensure Admission Control Plugin EventRateLimit Is Set

More Info:​

Limit the rate at which the API server accepts requests.

Risk Level​

Low

Address​

Security

Compliance Standards​

  • CIS Kubernetes

Triage and Remediation​

Remediation​

Manual Steps
  1. Create an EventRateLimit configuration file (on every control plane node)

    sudo mkdir -p /etc/kubernetes/admission
    sudo tee /etc/kubernetes/admission/event-rate-limit.yaml >/dev/null << 'EOF'
    apiVersion: apiserver.config.k8s.io/v1
    kind: AdmissionConfiguration
    plugins:
    - name: EventRateLimit
    path: /etc/kubernetes/admission/event-rate-limit-config.yaml
    EOF

    sudo tee /etc/kubernetes/admission/event-rate-limit-config.yaml >/dev/null << 'EOF'
    apiVersion: apiserver.config.k8s.io/v1alpha1
    kind: EventRateLimitConfig
    limits:
    - type: Namespace
    qps: 50
    burst: 100
    - type: User
    qps: 10
    burst: 20
    EOF
  2. Back up the existing API server manifest (on every control plane node)

    sudo cp -a /etc/kubernetes/manifests/kube-apiserver.yaml /etc/kubernetes/manifests/kube-apiserver.yaml.bak.$(date +%s)
  3. Edit the API server manifest to enable EventRateLimit and reference the config file (on every control plane node)
    Open the file:

    sudo sed -n '1,160p' /etc/kubernetes/manifests/kube-apiserver.yaml

    Then edit it with a text editor (for example):

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

    In the spec.containers[0].command (the list of - --flag=value lines), ensure:

    • The --enable-admission-plugins flag includes EventRateLimit in the comma‑separated list, for example:
      - --enable-admission-plugins=NamespaceLifecycle,NodeRestriction,EventRateLimit
    • Add or update the admission config file flag to point to the file you created:
      - --admission-control-config-file=/etc/kubernetes/admission/event-rate-limit.yaml
  4. Allow the API server static pod to restart automatically
    Saving the manifest under /etc/kubernetes/manifests/ will cause the kubelet on the control plane node to restart the kube-apiserver pod. No additional command is required, but expect a brief control‑plane disruption during restart.

  5. Verify the API server process flags include EventRateLimit and the config file (on every control plane node)

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

    Confirm the output contains:

    • --enable-admission-plugins=...EventRateLimit...
    • --admission-control-config-file=/etc/kubernetes/admission/event-rate-limit.yaml
Using kubectl

kubectl cannot modify kube-apiserver process flags or the static pod manifest at /etc/kubernetes/manifests/kube-apiserver.yaml, so this finding cannot be remediated through Kubernetes API objects. To address it, you must edit the manifest and related configuration directly on every control plane node; see the Manual Steps section for the required host-level changes.

Automation
#!/usr/bin/env bash
#
# Automation: Ensure kube-apiserver has EventRateLimit admission plugin enabled
# and uses an admission-control-config-file on every control plane node.
#
# Run on: every control plane node (as root).
# Safe to re-run (idempotent).
#
# Operational impact: Editing /etc/kubernetes/manifests/kube-apiserver.yaml
# will cause the kubelet to restart the kube-apiserver static pod.

set -euo pipefail

API_MANIFEST="/etc/kubernetes/manifests/kube-apiserver.yaml"
ADMISSION_CONFIG_DIR="/etc/kubernetes"
ADMISSION_CONFIG_FILE="${ADMISSION_CONFIG_DIR}/admission-control-config.yaml"

backup_manifest() {
local ts
ts="$(date +%Y%m%d%H%M%S)"
if [ -f "${API_MANIFEST}" ] && [ ! -f "${API_MANIFEST}.pre-eventratelimit.bak" ]; then
cp "${API_MANIFEST}" "${API_MANIFEST}.pre-eventratelimit.bak"
elif [ -f "${API_MANIFEST}" ]; then
cp "${API_MANIFEST}" "${API_MANIFEST}.bak.${ts}"
fi
}

ensure_admission_config_file() {
mkdir -p "${ADMISSION_CONFIG_DIR}"
if [ ! -f "${ADMISSION_CONFIG_FILE}" ]; then
cat > "${ADMISSION_CONFIG_FILE}" <<'EOF'
apiVersion: apiserver.config.k8s.io/v1alpha1
kind: AdmissionConfiguration
plugins:
- name: EventRateLimit
configuration:
apiVersion: eventratelimit.admission.k8s.io/v1alpha1
kind: Configuration
limits:
- type: Server
qps: 50
burst: 100
EOF
fi
}

ensure_manifest_arg() {
local arg_name="$1"
local desired_value="$2"

# If arg not present, append new - --arg=value line under existing args.
if ! grep -qE "[[:space:]]- ${arg_name}=" "${API_MANIFEST}"; then
# Append under the first occurrence of a container args block.
# This assumes standard kubeadm-style manifest with "args:" followed by "- --..."
awk -v ARG_NAME="${arg_name}" -v ARG_VAL="${desired_value}" '
$0 ~ /^[[:space:]]*args:/ && inserted == 0 {
print $0
print " - " ARG_NAME "=" ARG_VAL
inserted = 1
next
}
{ print $0 }
' "${API_MANIFEST}" > "${API_MANIFEST}.tmp"
mv "${API_MANIFEST}.tmp" "${API_MANIFEST}"
else
# Arg present; update in-place while preserving other flags.
# For --enable-admission-plugins we must ensure EventRateLimit is included.
if [ "${arg_name}" = "--enable-admission-plugins" ]; then
# Add ",EventRateLimit" if missing
if ! grep -qE "[[:space:]]- --enable-admission-plugins=.*EventRateLimit" "${API_MANIFEST}"; then
sed -E -i 's/(^[[:space:]]*- --enable-admission-plugins=.*)/\1,EventRateLimit/' "${API_MANIFEST}"
fi
else
# Generic replacement for other args
sed -E -i "s|(^[[:space:]]*- ${arg_name}=).*|\1${desired_value}|" "${API_MANIFEST}"
fi
fi
}

main() {
if [ ! -f "${API_MANIFEST}" ]; then
echo "ERROR: ${API_MANIFEST} not found on this node. Are you on a control plane node?" >&2
exit 1
fi

backup_manifest
ensure_admission_config_file

# Ensure --enable-admission-plugins includes EventRateLimit
ensure_manifest_arg "--enable-admission-plugins" "EventRateLimit"

# Ensure --admission-control-config-file is set to our config file path
ensure_manifest_arg "--admission-control-config-file" "${ADMISSION_CONFIG_FILE}"

echo "Waiting for kube-apiserver to be restarted by kubelet (up to 60s)..."
sleep 10

# Verification: show kube-apiserver process with required flags
echo "Verification: checking kube-apiserver process flags"
/bin/ps -ef | grep kube-apiserver | grep -v grep || {
echo "ERROR: kube-apiserver process not found. Check pod status." >&2
exit 1
}

if /bin/ps -ef | grep kube-apiserver | grep -v grep | grep -q -- "--enable-admission-plugins=.*EventRateLimit"; then
echo "OK: --enable-admission-plugins includes EventRateLimit"
else
echo "ERROR: --enable-admission-plugins does not include EventRateLimit" >&2
exit 1
fi

if /bin/ps -ef | grep kube-apiserver | grep -v grep | grep -q -- "--admission-control-config-file=${ADMISSION_CONFIG_FILE}"; then
echo "OK: --admission-control-config-file is set to ${ADMISSION_CONFIG_FILE}"
else
echo "ERROR: --admission-control-config-file not set correctly" >&2
exit 1
fi

echo "EventRateLimit admission plugin is configured on this control plane node."
}

main "$@"

Additional Reading:​