CKS — CIS Benchmarks & kube-bench Lab

14 minute read

Lab Overview

This hands-on lab covers the complete CIS benchmark workflow: install kube-bench, scan the cluster, identify failures, remediate them, and verify the fixes. By the end of this lab, you’ll have practiced the exact skills tested in the CKS exam for CIS benchmark questions.

Estimated time: 45–60 minutes

Prerequisites

Requirement Details
Kubernetes cluster kubeadm cluster with at least 1 control plane + 1 worker node
SSH access Root/sudo access to both control plane and worker nodes
kubectl Configured and connected to the cluster
Internet access For downloading kube-bench (or pre-download the binary)

Important: This lab requires a kubeadm-based cluster. Managed Kubernetes services (EKS, GKE, AKS) don’t expose control plane configuration files and won’t work for CIS benchmark exercises.

Verify Lab Readiness

# Verify cluster is running
kubectl cluster-info

# Verify you have control plane and worker nodes
kubectl get nodes

# Verify SSH access to control plane
ssh controlplane "hostname"

# Verify SSH access to worker node
ssh node01 "hostname"

Expected output:

NAME           STATUS   ROLES           AGE   VERSION
controlplane   Ready    control-plane   30m   v1.31.0
node01         Ready    <none>          28m   v1.31.0

What You’ll Practice

  • Install kube-bench on cluster nodes
  • Run kube-bench as a Kubernetes Job
  • Scan control plane and identify FAIL results
  • Scan worker node and identify FAIL results
  • Fix top 5 FAIL results on the API server
  • Fix kubelet security configuration
  • Re-run kube-bench and verify all fixes

Exercise 1: Install kube-bench and Run Initial Scan

Objective: Install kube-bench on the control plane node and run an initial baseline scan.

Step 1.1: Install kube-bench Binary

SSH into the control plane node:

ssh controlplane

Download and install kube-bench:

# Download kube-bench
KUBE_BENCH_VERSION=0.8.0
curl -L https://github.com/aquasecurity/kube-bench/releases/download/v${KUBE_BENCH_VERSION}/kube-bench_${KUBE_BENCH_VERSION}_linux_amd64.tar.gz -o kube-bench.tar.gz

# Extract
tar -xvf kube-bench.tar.gz

# Move to PATH
sudo mv kube-bench /usr/local/bin/

# Verify installation
kube-bench version

Expected output:

v0.8.0

Step 1.2: Run Baseline Scan (Control Plane)

# Run the full master scan and save to a file
sudo kube-bench run --targets master 2>&1 | tee /tmp/kube-bench-master-before.txt

# View the summary
tail -5 /tmp/kube-bench-master-before.txt

Expected output (approximately):

== Summary master ==
38 checks PASS
9 checks FAIL
4 checks WARN
0 checks INFO

Step 1.3: List All FAIL Results

# Extract only FAIL lines
grep '^\[FAIL\]' /tmp/kube-bench-master-before.txt

Expected output (your results may vary):

[FAIL] 1.2.1 Ensure that the --anonymous-auth argument is set to false
[FAIL] 1.2.16 Ensure that the --profiling argument is set to false
[FAIL] 1.2.19 Ensure that the --audit-log-path argument is set
[FAIL] 1.2.20 Ensure that the --audit-log-maxage argument is set to 30 or as appropriate
[FAIL] 1.2.21 Ensure that the --audit-log-maxbackup argument is set to 10 or as appropriate
[FAIL] 1.2.22 Ensure that the --audit-log-maxsize argument is set to 100 or as appropriate
[FAIL] 1.3.2 Ensure that the --profiling argument is set to false
[FAIL] 1.4.1 Ensure that the --profiling argument is set to false
[FAIL] 1.4.2 Ensure that the --bind-address argument is set to 127.0.0.1

Record these results — you’ll compare them against the post-remediation scan.

Step 1.4: Install kube-bench on Worker Node

SSH into the worker node and repeat the installation:

ssh node01

KUBE_BENCH_VERSION=0.8.0
curl -L https://github.com/aquasecurity/kube-bench/releases/download/v${KUBE_BENCH_VERSION}/kube-bench_${KUBE_BENCH_VERSION}_linux_amd64.tar.gz -o kube-bench.tar.gz
tar -xvf kube-bench.tar.gz
sudo mv kube-bench /usr/local/bin/
kube-bench version

Exercise 2: Run kube-bench as a Kubernetes Job

Objective: Deploy kube-bench as a Kubernetes Job to scan the control plane — the most common exam approach.

Step 2.1: Create the Job Manifest

Back on your workstation (or control plane node with kubectl):

cat <<'EOF' > kube-bench-master-job.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: kube-bench-master
  namespace: default
spec:
  template:
    metadata:
      labels:
        app: kube-bench
    spec:
      hostPID: true
      nodeSelector:
        node-role.kubernetes.io/control-plane: ""
      tolerations:
        - key: node-role.kubernetes.io/control-plane
          operator: Exists
          effect: NoSchedule
        - key: node-role.kubernetes.io/master
          operator: Exists
          effect: NoSchedule
      containers:
        - name: kube-bench
          image: aquasec/kube-bench:v0.8.0
          command: ["kube-bench", "run", "--targets", "master"]
          volumeMounts:
            - name: var-lib-etcd
              mountPath: /var/lib/etcd
              readOnly: true
            - name: var-lib-kubelet
              mountPath: /var/lib/kubelet
              readOnly: true
            - name: var-lib-kube-scheduler
              mountPath: /var/lib/kube-scheduler
              readOnly: true
            - name: var-lib-kube-controller-manager
              mountPath: /var/lib/kube-controller-manager
              readOnly: true
            - name: etc-systemd
              mountPath: /etc/systemd
              readOnly: true
            - name: lib-systemd
              mountPath: /lib/systemd/
              readOnly: true
            - name: srv-kubernetes
              mountPath: /srv/kubernetes/
              readOnly: true
            - name: etc-kubernetes
              mountPath: /etc/kubernetes
              readOnly: true
            - name: usr-bin
              mountPath: /usr/local/mount-from-host/bin
              readOnly: true
            - name: etc-cni-netd
              mountPath: /etc/cni/net.d/
              readOnly: true
            - name: opt-cni-bin
              mountPath: /opt/cni/bin/
              readOnly: true
      restartPolicy: Never
      volumes:
        - name: var-lib-etcd
          hostPath:
            path: /var/lib/etcd
        - name: var-lib-kubelet
          hostPath:
            path: /var/lib/kubelet
        - name: var-lib-kube-scheduler
          hostPath:
            path: /var/lib/kube-scheduler
        - name: var-lib-kube-controller-manager
          hostPath:
            path: /var/lib/kube-controller-manager
        - name: etc-systemd
          hostPath:
            path: /etc/systemd
        - name: lib-systemd
          hostPath:
            path: /lib/systemd
        - name: srv-kubernetes
          hostPath:
            path: /srv/kubernetes
        - name: etc-kubernetes
          hostPath:
            path: /etc/kubernetes
        - name: usr-bin
          hostPath:
            path: /usr/bin
        - name: etc-cni-netd
          hostPath:
            path: /etc/cni/net.d/
        - name: opt-cni-bin
          hostPath:
            path: /opt/cni/bin/
  backoffLimit: 0
EOF

Step 2.2: Deploy and View Results

# Apply the Job
kubectl apply -f kube-bench-master-job.yaml

# Wait for Job to complete
kubectl wait --for=condition=complete job/kube-bench-master --timeout=120s

# View full results
kubectl logs job/kube-bench-master

# View only FAIL results
kubectl logs job/kube-bench-master | grep '^\[FAIL\]'

# View summary
kubectl logs job/kube-bench-master | tail -5

Step 2.3: Compare Results

The Job results should match what you saw from the direct binary run. This confirms the Job is working correctly.

Step 2.4: Cleanup

kubectl delete job kube-bench-master

Exercise 3: Scan Master Node and Identify FAIL Results

Objective: Analyze the control plane scan results and categorize failures by priority.

Step 3.1: Run Targeted Scans

SSH into the control plane node:

ssh controlplane

Run scans per section:

# API Server checks
sudo kube-bench run --group 1.2 2>&1 | grep -E '^\[(FAIL|WARN)\]'

# Controller Manager checks
sudo kube-bench run --group 1.3 2>&1 | grep -E '^\[(FAIL|WARN)\]'

# Scheduler checks
sudo kube-bench run --group 1.4 2>&1 | grep -E '^\[(FAIL|WARN)\]'

# etcd checks
sudo kube-bench run --targets etcd 2>&1 | grep -E '^\[(FAIL|WARN)\]'

Step 3.2: Create a Prioritized Fix List

Based on the results, create your fix list (example):

Priority: CRITICAL
  [ ] 1.2.1  - API server anonymous auth → --anonymous-auth=false

Priority: HIGH
  [ ] 1.2.19 - Audit log path → --audit-log-path=/var/log/kubernetes/audit/audit.log
  [ ] 1.2.20 - Audit log maxage → --audit-log-maxage=30
  [ ] 1.2.21 - Audit log maxbackup → --audit-log-maxbackup=10
  [ ] 1.2.22 - Audit log maxsize → --audit-log-maxsize=100

Priority: MEDIUM
  [ ] 1.2.16 - API server profiling → --profiling=false
  [ ] 1.3.2  - Controller manager profiling → --profiling=false
  [ ] 1.4.1  - Scheduler profiling → --profiling=false
  [ ] 1.4.2  - Scheduler bind address → --bind-address=127.0.0.1

Exercise 4: Scan Worker Node and Identify FAIL Results

Objective: Run kube-bench on the worker node and identify kubelet failures.

Step 4.1: Run Worker Node Scan

SSH into the worker node:

ssh node01
# Run full worker node scan
sudo kube-bench run --targets node 2>&1 | tee /tmp/kube-bench-node-before.txt

# View FAIL results
grep '^\[FAIL\]' /tmp/kube-bench-node-before.txt

Expected output (approximately):

[FAIL] 4.2.1 Ensure that the --anonymous-auth argument is set to false
[FAIL] 4.2.4 Ensure that the --read-only-port argument is set to 0
[FAIL] 4.2.6 Ensure that the --protect-kernel-defaults argument is set to true

Step 4.2: View Summary

tail -5 /tmp/kube-bench-node-before.txt

Expected output:

== Summary node ==
18 checks PASS
3 checks FAIL
1 checks WARN
0 checks INFO

Exercise 5: Fix Top 5 FAIL Results on the API Server

Objective: Remediate the most critical API server failures.

Step 5.1: Back Up the Current Manifest

SSH into the control plane node:

ssh controlplane
# Always back up before editing
sudo cp /etc/kubernetes/manifests/kube-apiserver.yaml /tmp/kube-apiserver.yaml.bak

Step 5.2: Fix Anonymous Auth (Critical)

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

Add in the command section (after existing flags):

    - --anonymous-auth=false

Do NOT save yet — we’ll apply multiple fixes at once to minimize restarts.

Step 5.3: Fix Profiling (Medium)

In the same file, add:

    - --profiling=false

Step 5.4: Fix Audit Logging (High)

First, create the audit policy and directories:

# Create directories
sudo mkdir -p /var/log/kubernetes/audit
sudo mkdir -p /etc/kubernetes/audit

# Create audit policy
cat <<'EOF' | sudo tee /etc/kubernetes/audit/audit-policy.yaml
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
  - level: Metadata
    resources:
    - group: ""
      resources: ["secrets", "configmaps"]
  - level: RequestResponse
    resources:
    - group: ""
      resources: ["pods"]
    verbs: ["create", "delete", "patch"]
  - level: RequestResponse
    resources:
    - group: "rbac.authorization.k8s.io"
  - level: Metadata
    stages:
    - ResponseComplete
EOF

Now add the audit flags to the API server manifest:

    - --audit-policy-file=/etc/kubernetes/audit/audit-policy.yaml
    - --audit-log-path=/var/log/kubernetes/audit/audit.log
    - --audit-log-maxage=30
    - --audit-log-maxbackup=10
    - --audit-log-maxsize=100

Add volume mounts (inside the existing volumeMounts array):

    - name: audit-log
      mountPath: /var/log/kubernetes/audit
    - name: audit-policy
      mountPath: /etc/kubernetes/audit
      readOnly: true

Add volumes (inside the existing volumes array):

  - name: audit-log
    hostPath:
      path: /var/log/kubernetes/audit
      type: DirectoryOrCreate
  - name: audit-policy
    hostPath:
      path: /etc/kubernetes/audit
      type: DirectoryOrCreate

Step 5.5: Save and Verify API Server Restart

Save the file. The kubelet detects the change and restarts the API server.

# Watch the API server Pod restart
kubectl get pods -n kube-system -l component=kube-apiserver -w

Wait until the Pod shows Running and READY 1/1:

NAME                            READY   STATUS    RESTARTS   AGE
kube-apiserver-controlplane     1/1     Running   0          15s

If the API server doesn’t come back: Check for YAML syntax errors:

# Check kubelet logs
sudo journalctl -u kubelet -f | grep apiserver

# Restore from backup if needed
sudo cp /tmp/kube-apiserver.yaml.bak /etc/kubernetes/manifests/kube-apiserver.yaml

Step 5.6: Verify API Server Fixes

# Check all the checks we fixed
sudo kube-bench run --check 1.2.1
sudo kube-bench run --check 1.2.16
sudo kube-bench run --check 1.2.19
sudo kube-bench run --check 1.2.20
sudo kube-bench run --check 1.2.21
sudo kube-bench run --check 1.2.22

Expected output for each:

[PASS] 1.2.1 Ensure that the --anonymous-auth argument is set to false
[PASS] 1.2.16 Ensure that the --profiling argument is set to false
[PASS] 1.2.19 Ensure that the --audit-log-path argument is set
[PASS] 1.2.20 Ensure that the --audit-log-maxage argument is set to 30 or as appropriate
[PASS] 1.2.21 Ensure that the --audit-log-maxbackup argument is set to 10 or as appropriate
[PASS] 1.2.22 Ensure that the --audit-log-maxsize argument is set to 100 or as appropriate

Step 5.7: Fix Controller Manager and Scheduler

# Back up
sudo cp /etc/kubernetes/manifests/kube-controller-manager.yaml /tmp/kube-controller-manager.yaml.bak
sudo cp /etc/kubernetes/manifests/kube-scheduler.yaml /tmp/kube-scheduler.yaml.bak

# Fix controller manager
sudo vi /etc/kubernetes/manifests/kube-controller-manager.yaml

Add:

    - --profiling=false
# Fix scheduler
sudo vi /etc/kubernetes/manifests/kube-scheduler.yaml

Add:

    - --profiling=false
    - --bind-address=127.0.0.1

Wait for both Pods to restart:

kubectl get pods -n kube-system -l 'component in (kube-controller-manager,kube-scheduler)' -w

Verify:

sudo kube-bench run --check 1.3.2
sudo kube-bench run --check 1.4.1
sudo kube-bench run --check 1.4.2

Expected — all PASS.


Exercise 6: Fix Kubelet Security Configuration

Objective: Remediate kubelet FAIL results on the worker node.

Step 6.1: Back Up Current Configuration

SSH into the worker node:

ssh node01
# Back up
sudo cp /var/lib/kubelet/config.yaml /tmp/kubelet-config.yaml.bak

Step 6.2: Review Current kubelet Config

cat /var/lib/kubelet/config.yaml

Note the current values for authentication, authorization, readOnlyPort, and protectKernelDefaults.

Step 6.3: Apply Security Fixes

sudo vi /var/lib/kubelet/config.yaml

Add or modify these sections:

# Fix 4.2.1: Disable anonymous authentication
authentication:
  anonymous:
    enabled: false
  webhook:
    enabled: true
    cacheTTL: 0s
  x509:
    clientCAFile: /etc/kubernetes/pki/ca.crt

# Fix 4.2.2: Use Webhook authorization
authorization:
  mode: Webhook
  webhook:
    cacheAuthorizedTTL: 0s
    cacheUnauthorizedTTL: 0s

# Fix 4.2.4: Disable read-only port
readOnlyPort: 0

Step 6.4: Fix Kernel Defaults (if 4.2.6 failed)

Before enabling protectKernelDefaults, set the required kernel parameters:

# Set required kernel parameters
sudo sysctl -w vm.overcommit_memory=1
sudo sysctl -w vm.panic_on_oom=0
sudo sysctl -w kernel.panic=10
sudo sysctl -w kernel.panic_on_oops=1

# Make persistent
cat <<EOF | sudo tee /etc/sysctl.d/90-kubelet.conf
vm.overcommit_memory=1
vm.panic_on_oom=0
kernel.panic=10
kernel.panic_on_oops=1
EOF

sudo sysctl --system

Now add to kubelet config:

protectKernelDefaults: true

Step 6.5: Restart kubelet

sudo systemctl restart kubelet

# Verify kubelet is running
sudo systemctl status kubelet

# Check for errors
sudo journalctl -u kubelet --no-pager | tail -20

Step 6.6: Verify Kubelet Fixes

sudo kube-bench run --check 4.2.1
sudo kube-bench run --check 4.2.2
sudo kube-bench run --check 4.2.4
sudo kube-bench run --check 4.2.6

Expected:

[PASS] 4.2.1 Ensure that the --anonymous-auth argument is set to false
[PASS] 4.2.2 Ensure that the --authorization-mode argument is not set to AlwaysAllow
[PASS] 4.2.4 Ensure that the --read-only-port argument is set to 0
[PASS] 4.2.6 Ensure that the --protect-kernel-defaults argument is set to true

Exercise 7: Re-Run kube-bench and Verify Improvements

Objective: Run a complete post-remediation scan and compare with the baseline.

Step 7.1: Full Master Rescan

SSH into the control plane node:

ssh controlplane
# Run post-remediation master scan
sudo kube-bench run --targets master 2>&1 | tee /tmp/kube-bench-master-after.txt

# View new summary
echo "=== BEFORE ==="
tail -5 /tmp/kube-bench-master-before.txt
echo ""
echo "=== AFTER ==="
tail -5 /tmp/kube-bench-master-after.txt

Expected output:

=== BEFORE ===
== Summary master ==
38 checks PASS
9 checks FAIL
4 checks WARN
0 checks INFO

=== AFTER ===
== Summary master ==
47 checks PASS
0 checks FAIL
4 checks WARN
0 checks INFO

Step 7.2: Full Worker Rescan

SSH into the worker node:

ssh node01
# Run post-remediation worker scan
sudo kube-bench run --targets node 2>&1 | tee /tmp/kube-bench-node-after.txt

# Compare
echo "=== BEFORE ==="
tail -5 /tmp/kube-bench-node-before.txt
echo ""
echo "=== AFTER ==="
tail -5 /tmp/kube-bench-node-after.txt

Expected output:

=== BEFORE ===
== Summary node ==
18 checks PASS
3 checks FAIL
1 checks WARN
0 checks INFO

=== AFTER ===
== Summary node ==
21 checks PASS
0 checks FAIL
1 checks WARN
0 checks INFO

Step 7.3: Verify No Remaining FAILs

# Master
grep '^\[FAIL\]' /tmp/kube-bench-master-after.txt
# Should return empty

# Worker
grep '^\[FAIL\]' /tmp/kube-bench-node-after.txt
# Should return empty

Step 7.4: Review Remaining WARNs

# Master WARNs
grep '^\[WARN\]' /tmp/kube-bench-master-after.txt

Example remaining WARNs:

[WARN] 1.2.10 Ensure that the admission control plugin EventRateLimit is set
[WARN] 1.2.12 Ensure that the admission control plugin AlwaysPullImages is set

These are Level 2 checks that require organizational decisions — acceptable to leave as WARN with documented justification.


Lab Cleanup

# On control plane — delete kube-bench Job if still running
kubectl delete job kube-bench-master --ignore-not-found

# Optionally remove kube-bench binary
ssh controlplane "sudo rm /usr/local/bin/kube-bench"
ssh node01 "sudo rm /usr/local/bin/kube-bench"

# Keep the security fixes in place — don't revert!

Important: Do NOT revert the security fixes. The hardened configuration is the desired state.

Lab Summary

Exercise What You Did Key Skill
1 Installed kube-bench, ran baseline scan Tool installation, scan execution
2 Deployed kube-bench as Kubernetes Job Job YAML creation (exam skill)
3 Analyzed control plane failures Result interpretation, prioritization
4 Analyzed worker node failures kubelet-specific checks
5 Fixed API server, controller-manager, scheduler Static Pod manifest editing
6 Fixed kubelet configuration kubelet config.yaml editing, systemctl
7 Verified all fixes with re-scan Complete workflow validation

Practice Questions

Q1: On the CKS exam, you need to run kube-bench but it’s not installed. What’s the fastest method?

Show Answer

Run kube-bench as a Kubernetes Job. This doesn’t require installing anything on the node:

kubectl apply -f kube-bench-job.yaml
kubectl wait --for=condition=complete job/kube-bench-master --timeout=120s
kubectl logs job/kube-bench-master

If the exam provides kube-bench pre-installed on nodes, use the binary directly:

sudo kube-bench run --targets master

The Job approach is preferred because it doesn’t require SSH access to the node, which may be faster in the exam environment.


Q2: After editing the API server manifest, kubectl stops working. What happened and how do you fix it?

Show Answer

The API server failed to restart due to a YAML syntax error or invalid flag value in /etc/kubernetes/manifests/kube-apiserver.yaml.

Diagnosis:

# kubectl won't work — use crictl or check kubelet logs directly
sudo crictl ps -a | grep apiserver
sudo journalctl -u kubelet --no-pager | tail -50 | grep -i error

Fix:

# Option 1: Fix the YAML error
sudo vi /etc/kubernetes/manifests/kube-apiserver.yaml

# Option 2: Restore from backup
sudo cp /tmp/kube-apiserver.yaml.bak /etc/kubernetes/manifests/kube-apiserver.yaml

The kubelet will automatically detect the corrected file and restart the API server. Wait 30-60 seconds, then verify with kubectl get pods -n kube-system.

Prevention: Always back up the manifest before editing: sudo cp /etc/kubernetes/manifests/kube-apiserver.yaml /tmp/kube-apiserver.yaml.bak


Q3: A kube-bench scan shows that kubelet protectKernelDefaults is failing. After setting it to true, kubelet won’t start. Why?

Show Answer

When protectKernelDefaults: true, the kubelet checks that required kernel parameters are already set correctly before starting. If they’re not, kubelet refuses to start.

Fix: Set the required kernel parameters first:

sudo sysctl -w vm.overcommit_memory=1
sudo sysctl -w vm.panic_on_oom=0
sudo sysctl -w kernel.panic=10
sudo sysctl -w kernel.panic_on_oops=1

# Make persistent
cat <<EOF | sudo tee /etc/sysctl.d/90-kubelet.conf
vm.overcommit_memory=1
vm.panic_on_oom=0
kernel.panic=10
kernel.panic_on_oops=1
EOF

sudo sysctl --system

Then restart kubelet:

sudo systemctl restart kubelet

Q4: Write a complete kube-bench Job YAML that scans a worker node. Include the critical spec fields.

Show Answer
apiVersion: batch/v1
kind: Job
metadata:
  name: kube-bench-node
  namespace: default
spec:
  template:
    spec:
      hostPID: true
      nodeSelector:
        node-role.kubernetes.io/worker: ""
      containers:
        - name: kube-bench
          image: aquasec/kube-bench:v0.8.0
          command: ["kube-bench", "run", "--targets", "node"]
          volumeMounts:
            - name: var-lib-kubelet
              mountPath: /var/lib/kubelet
              readOnly: true
            - name: etc-systemd
              mountPath: /etc/systemd
              readOnly: true
            - name: etc-kubernetes
              mountPath: /etc/kubernetes
              readOnly: true
            - name: lib-systemd
              mountPath: /lib/systemd
              readOnly: true
      restartPolicy: Never
      volumes:
        - name: var-lib-kubelet
          hostPath:
            path: /var/lib/kubelet
        - name: etc-systemd
          hostPath:
            path: /etc/systemd
        - name: etc-kubernetes
          hostPath:
            path: /etc/kubernetes
        - name: lib-systemd
          hostPath:
            path: /lib/systemd
  backoffLimit: 0

Key differences from master Job: different nodeSelector (worker node), no control-plane tolerations, --targets node instead of --targets master, fewer volume mounts (no etcd directories).


Q5: After all remediation, your scan shows 0 FAIL but still 4 WARN. The exam asks you to “ensure the cluster passes CIS benchmarks.” Is your work done?

Show Answer

Yes — for the CKS exam, 0 FAIL is the target. WARN results mean kube-bench couldn’t automatically verify the check, not that it failed. Common WARNs like EventRateLimit and AlwaysPullImages are Level 2 advisory checks.

On the exam:

  • Fix all FAIL results — this is what’s being scored
  • WARN results don’t need to be fixed unless the exam specifically asks for them
  • Focus your time on FAILs and move on once they’re all PASS

In production, you’d review each WARN and document a justification for accepting or fixing it. But on the exam, time is limited — don’t chase WARNs.


Congratulations! You’ve completed the CIS Benchmarks & kube-bench chapter. You can now scan clusters, interpret results, and fix the most common security misconfigurations — the exact skills tested on the CKS exam.


← Remediation Strategies Next Chapter →

Updated: