CKS sample questions with answers
10 free CKS sample questions across the exam's domains, each with its answer and an explanation. No account needed.
CKS sample questions
Certified Kubernetes Security Specialist (CKS), CNCF / The Linux Foundation.
Question 1
Domain: Cluster Setup
Which NetworkPolicy blocks all incoming traffic to every Pod in the namespace it is created in, while leaving outgoing traffic unaffected?
- spec: {podSelector: {}, policyTypes: [Egress]} with no egress rules
- spec: {podSelector: {}, policyTypes: [Ingress]} with no ingress rules
- spec: {podSelector: {}, ingress: [{}]} with policyTypes: [Ingress]
- spec: {podSelector: {matchLabels: {deny: all}}, policyTypes: [Ingress, Egress]}
Show the answer
Answer: B. spec: {podSelector: {}, policyTypes: [Ingress]} with no ingress rules
An empty podSelector selects every Pod in the namespace, and listing Ingress in policyTypes with no ingress rules means no inbound connection is allowed. The variant with ingress: [{}] is the trap: a single empty rule matches all sources, so it explicitly allows all ingress instead of denying it.
Checked against: https://kubernetes.io/docs/concepts/services-networking/network-policies/#default-deny-all-ingress-traffic
Question 2
Domain: Cluster Setup
kube-bench on a kubeadm control plane node reports: [FAIL] 1.2.x Ensure that the --profiling argument is set to false (kube-apiserver).
How should this finding be remediated?
- Add --profiling=false to /etc/kubernetes/manifests/kube-apiserver.yaml; the kubelet then recreates the static Pod
- Run kubectl edit pod kube-apiserver-cp1 -n kube-system and add --profiling=false to the kube-apiserver container's command list
- Add profiling: false to /var/lib/kubelet/config.yaml on the control plane node and restart the kubelet
- Create a ConfigMap named kube-apiserver in kube-system containing profiling=false
Show the answer
Answer: A. Add --profiling=false to /etc/kubernetes/manifests/kube-apiserver.yaml; the kubelet then recreates the static Pod
In a kubeadm cluster the API server is a static Pod defined by a manifest on the node; the kubelet watches that directory and restarts the Pod when the file changes. Editing the mirror Pod through the API looks convenient but does not persist, because mirror Pods cannot change the static Pod definition.
Checked against: https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/
Question 3
Domain: Cluster Hardening
A user holds a ClusterRole allowing create on clusterrolebindings but has no other permissions and no bind or escalate verbs.
What happens when the user runs kubectl create clusterrolebinding x --clusterrole=cluster-admin --user=jane?
- The binding is created, because permission to create ClusterRoleBindings is by itself sufficient to bind any ClusterRole
- It is rejected: RBAC blocks binding a role with permissions the user lacks, unless the user has bind on that role
- The binding is created but stays inactive until a cluster administrator approves it
- The binding is created with its rules reduced to the permissions the requesting user already holds
Show the answer
Answer: B. It is rejected: RBAC blocks binding a role with permissions the user lacks, unless the user has bind on that role
RBAC's privilege escalation prevention only lets a user create a binding if they already hold all permissions in the referenced role, or have the bind verb on that role. Because it looks like create on ClusterRoleBindings should be enough, that is the tempting answer, but it would make creating bindings equivalent to cluster-admin.
Checked against: https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update
Question 4
Domain: System Hardening
A worker node image was built from a general-purpose server template. You suspect it runs daemons that Kubernetes does not need, such as a web server and a print service.
Which command gives the best starting inventory of services to review for removal?
- journalctl --list-boots
- systemctl list-timers --all
- systemctl daemon-reload
- systemctl list-units --type=service --state=running
Show the answer
Answer: D. systemctl list-units --type=service --state=running
Listing running service units shows every daemon currently active on the host, which is the attack surface to review and disable where not needed. Timers are only one way units get triggered and do not show long-running daemons such as an unused web server.
Checked against: https://www.freedesktop.org/software/systemd/man/latest/systemctl.html
Question 5
Domain: Minimize Microservice Vulnerabilities
You plan to label namespace prod with pod-security.kubernetes.io/enforce=restricted and want to avoid surprises.
Which command shows which existing Pods would violate the policy before the label is actually applied?
- kubectl label --dry-run=client --overwrite ns prod pod-security.kubernetes.io/enforce=restricted
- kubectl auth can-i create pods -n prod --as=system:serviceaccount:prod:default
- kubectl label --dry-run=server --overwrite ns prod pod-security.kubernetes.io/enforce=restricted
- kubectl get pods -n prod -l pod-security.kubernetes.io/enforce=restricted
Show the answer
Answer: C. kubectl label --dry-run=server --overwrite ns prod pod-security.kubernetes.io/enforce=restricted
A server-side dry run sends the request to the API server, where Pod Security Admission evaluates existing Pods against the new level and returns warnings, without saving the change. A client-side dry run never reaches the API server, so no admission evaluation takes place and no warnings are produced.
Checked against: https://kubernetes.io/docs/tasks/configure-pod-container/enforce-standards-namespace-labels/
Question 6
Domain: Minimize Microservice Vulnerabilities
Namespace payments has a PeerAuthentication with mtls.mode: STRICT. A client Pod in namespace legacy, which has no Istio sidecar injected, now gets connection resets when calling the payments service.
Why did the legacy client stop working?
- STRICT mode blocks all traffic from outside the namespace, regardless of whether TLS is used
- STRICT mode rejects plaintext connections, and a client without a sidecar cannot present an Istio mTLS certificate
- STRICT mode requires the client to be listed in an AuthorizationPolicy before it can connect
- STRICT mode switches the server to HTTP/2 only, which the legacy client does not support
Show the answer
Answer: B. STRICT mode rejects plaintext connections, and a client without a sidecar cannot present an Istio mTLS certificate
Under STRICT, the server-side sidecar accepts only mutual TLS, so plaintext traffic from a workload without a sidecar is refused; PERMISSIVE is intended for exactly this migration period. STRICT does not add namespace or identity restrictions by itself, as those come from AuthorizationPolicy.
Checked against: https://istio.io/latest/docs/tasks/security/authentication/mtls-migration/
Question 7
Domain: Supply Chain Security
The CI pipeline signs images with cosign sign --key cosign.key. Before a release you want to verify the image registry.example.com/api@sha256:<digest> by hand.
Which command verifies the image signature with the team's public key?
- cosign sign --key cosign.pub registry.example.com/api@sha256:<digest>
- cosign verify-blob --key cosign.key registry.example.com/api@sha256:<digest>
- cosign attest --key cosign.pub registry.example.com/api@sha256:<digest>
- cosign verify --key cosign.pub registry.example.com/api@sha256:<digest>
Show the answer
Answer: D. cosign verify --key cosign.pub registry.example.com/api@sha256:<digest>
cosign verify checks the signature stored in the registry for an image against the supplied public key. cosign sign creates a signature and needs the private key, so running it with the public key is the easy mistake; verify-blob is for files, not images in a registry.
Checked against: https://docs.sigstore.dev/cosign/verifying/verify/
Question 8
Domain: Supply Chain Security
A Dockerfile has COPY id_rsa /root/.ssh/id_rsa, then RUN git clone ..., then RUN rm /root/.ssh/id_rsa. A scanner still finds the private key in the pushed image.
Why is the key still recoverable from the image?
- Each instruction creates a layer, so the file remains in the COPY layer even though a later layer hides it
- A rm in a RUN instruction only takes effect when a container starts from the image, not while the image is built
- Docker keeps a copy of every COPY source in the image's config JSON
- The key is cached in the builder's DNS cache, which is exported with the image
Show the answer
Answer: A. Each instruction creates a layer, so the file remains in the COPY layer even though a later layer hides it
Image layers are additive: deleting a file in a later RUN adds a whiteout that hides it, but the earlier layer with the file is still in the image and can be extracted. Build secrets should be mounted with RUN --mount=type=secret or kept out of the build context, rather than copied and deleted.
Checked against: https://docs.docker.com/build/building/secrets/
Question 9
Domain: Monitoring, Logging and Runtime Security
An audit log shows a user creating a Pod with a hostPath volume for / mounted at /host. Falco then reports 'chroot /host' followed by a shell in that container.
Which tactic does this activity represent?
- Initial access through a public-facing application
- Defence evasion by clearing container logs
- Discovery of cluster network services
- Privilege escalation through escape from the container to the host
Show the answer
Answer: D. Privilege escalation through escape from the container to the host
Mounting the host filesystem and chrooting into it gives the attacker the node's root filesystem as root, moving from container to host, which is privilege escalation by escaping to host. The Pod is created by a user who already has access, so Initial Access does not describe this step.
Checked against: https://attack.mitre.org/techniques/T1611/
Question 10
Domain: Monitoring, Logging and Runtime Security
You are designing an audit policy that must show who read or changed Secrets, without creating a new place where credentials can leak.
Why do the Kubernetes docs' example policies log Secrets and ConfigMaps at the Metadata level rather than Request or RequestResponse?
- Metadata is the only audit level that records the username and groups of whoever made the request
- Request and RequestResponse are not permitted for resources in the core API group
- Request and RequestResponse would write sensitive payloads, such as Secret data, into the log
- Metadata events are delivered faster to the log backend because they skip the RequestReceived stage
Show the answer
Answer: C. Request and RequestResponse would write sensitive payloads, such as Secret data, into the log
At Request level and above, request and response bodies are logged, so Secret values would end up in log files and log pipelines with much weaker access controls. All levels except None record the user, which is why the 'only level with the user' option is wrong.
Checked against: https://kubernetes.io/docs/tasks/debug/debug-cluster/audit/#audit-policy
More practice
A 20-question practice sampler is free with an account; Pro adds the full question bank and timed mock exams.
CKS course and practice exam: Certified Kubernetes Security Specialist: the exam guide, with the format, cost, pass mark and domains from the vendor.