CKS 無料問題集「Linux Foundation Certified Kubernetes Security Specialist (CKS)」
SIMULATION
Context
For testing purposes, the kubeadm provisioned cluster 's API server
was configured to allow unauthenticated and unauthorized access.
Task
First, secure the cluster 's API server configuring it as follows:
. Forbid anonymous authentication
. Use authorization mode Node,RBAC
. Use admission controller NodeRestriction
The cluster uses the Docker Engine as its container runtime . If needed, use the docker command to troubleshoot running containers.
kubectl is configured to use unauthenticated and unauthorized access. You do not have to change it, but be aware that kubectl will stop working once you have secured the cluster .
You can use the cluster 's original kubectl configuration file located at etc/kubernetes/admin.conf to access the secured cluster.
Next, to clean up, remove the ClusterRoleBinding
system:anonymous.
Context
For testing purposes, the kubeadm provisioned cluster 's API server
was configured to allow unauthenticated and unauthorized access.
Task
First, secure the cluster 's API server configuring it as follows:
. Forbid anonymous authentication
. Use authorization mode Node,RBAC
. Use admission controller NodeRestriction
The cluster uses the Docker Engine as its container runtime . If needed, use the docker command to troubleshoot running containers.
kubectl is configured to use unauthenticated and unauthorized access. You do not have to change it, but be aware that kubectl will stop working once you have secured the cluster .
You can use the cluster 's original kubectl configuration file located at etc/kubernetes/admin.conf to access the secured cluster.
Next, to clean up, remove the ClusterRoleBinding
system:anonymous.
正解:
See the Explanation below for complete solution
Explanation:
1) SSH to control-plane node
ssh cks000002
sudo -i
2) Edit API Server static pod manifest
API server in kubeadm runs as a static pod.
vi /etc/kubernetes/manifests/kube-apiserver.yaml
3) Apply required API Server security settings
3.1 Forbid anonymous authentication
Find command: section and ensure this line exists:
- --anonymous-auth=false
3.2 Use authorization mode Node,RBAC
Ensure exactly this line exists (and no AlwaysAllow):
- --authorization-mode=Node,RBAC
❌ Remove if present:
- --authorization-mode=AlwaysAllow
3.3 Enable admission controller NodeRestriction
Find --enable-admission-plugins and ensure NodeRestriction is included.
Correct example:
- --enable-admission-plugins=NodeRestriction
If other plugins already exist, append NodeRestriction, e.g.:
- --enable-admission-plugins=NamespaceLifecycle,ServiceAccount,NodeRestriction
4) Save file and let kubelet restart API server
Just save and exit (:wq)
Kubelet will automatically restart the API server pod.
5) Switch kubectl to secured config
Current kubectl will stop working after API server hardening.
export KUBECONFIG=/etc/kubernetes/admin.conf
Verify access:
kubectl get nodes
6) Remove insecure ClusterRoleBinding
Delete system:anonymous binding:
kubectl delete clusterrolebinding system:anonymous
Verify removal:
kubectl get clusterrolebinding | grep anonymous
(no output = correct)
7) Quick validation (optional but fast)
API server flags check:
grep -n "anonymous-auth" /etc/kubernetes/manifests/kube-apiserver.yaml
grep -n "authorization-mode" /etc/kubernetes/manifests/kube-apiserver.yaml grep -n "NodeRestriction" /etc/kubernetes/manifests/kube-apiserver.yaml
Explanation:
1) SSH to control-plane node
ssh cks000002
sudo -i
2) Edit API Server static pod manifest
API server in kubeadm runs as a static pod.
vi /etc/kubernetes/manifests/kube-apiserver.yaml
3) Apply required API Server security settings
3.1 Forbid anonymous authentication
Find command: section and ensure this line exists:
- --anonymous-auth=false
3.2 Use authorization mode Node,RBAC
Ensure exactly this line exists (and no AlwaysAllow):
- --authorization-mode=Node,RBAC
❌ Remove if present:
- --authorization-mode=AlwaysAllow
3.3 Enable admission controller NodeRestriction
Find --enable-admission-plugins and ensure NodeRestriction is included.
Correct example:
- --enable-admission-plugins=NodeRestriction
If other plugins already exist, append NodeRestriction, e.g.:
- --enable-admission-plugins=NamespaceLifecycle,ServiceAccount,NodeRestriction
4) Save file and let kubelet restart API server
Just save and exit (:wq)
Kubelet will automatically restart the API server pod.
5) Switch kubectl to secured config
Current kubectl will stop working after API server hardening.
export KUBECONFIG=/etc/kubernetes/admin.conf
Verify access:
kubectl get nodes
6) Remove insecure ClusterRoleBinding
Delete system:anonymous binding:
kubectl delete clusterrolebinding system:anonymous
Verify removal:
kubectl get clusterrolebinding | grep anonymous
(no output = correct)
7) Quick validation (optional but fast)
API server flags check:
grep -n "anonymous-auth" /etc/kubernetes/manifests/kube-apiserver.yaml
grep -n "authorization-mode" /etc/kubernetes/manifests/kube-apiserver.yaml grep -n "NodeRestriction" /etc/kubernetes/manifests/kube-apiserver.yaml
SIMULATION
Documentation Deployments, Pods, bom Command Help bom-help
You must connect to the correct host. Failure to do so may result in a zero score.
[candidate@base] $ ssh cks000035
Task
The alpine Deployment in the alpine namespace has three containers that run different versions of the alpine image.
First, find out which version of the alpine image contains the libcrypto3 package at version 3.1.4-r5.
Next, use the pre-installed bom tool to create an SPDX document for the identified image version at /home/candidate/alpine.spdx.
You can find the bom tool documentation at bom.
Finally, update the alpine Deployment and remove the container that uses the idenfied image version.
The Deployment's manifest file can be found at /home/candidate/alpine-deployment.yaml.
Do not modify any other containers of the Deployment.
Documentation Deployments, Pods, bom Command Help bom-help
You must connect to the correct host. Failure to do so may result in a zero score.
[candidate@base] $ ssh cks000035
Task
The alpine Deployment in the alpine namespace has three containers that run different versions of the alpine image.
First, find out which version of the alpine image contains the libcrypto3 package at version 3.1.4-r5.
Next, use the pre-installed bom tool to create an SPDX document for the identified image version at /home/candidate/alpine.spdx.
You can find the bom tool documentation at bom.
Finally, update the alpine Deployment and remove the container that uses the idenfied image version.
The Deployment's manifest file can be found at /home/candidate/alpine-deployment.yaml.
Do not modify any other containers of the Deployment.
正解:
See the Explanation below for complete solution
Explanation:
1) Connect to the correct host
ssh cks000035
sudo -i
export KUBECONFIG=/etc/kubernetes/admin.conf
2) List the 3 container names + images in the Deployment
kubectl -n alpine get deploy alpine -o jsonpath='{range .spec.template.spec.containers[*]}{.name}{"\t"}{.image}{"\n"}{end}' You'll get 3 lines like:
c1 alpine:3.xx
c2 alpine:3.yy
c3 alpine:3.zz
3) Identify which alpine image has libcrypto3 at 3.1.4-r5
Fastest reliable method (since it's Alpine, just query apk inside each image):
Run these one-by-one for each image you saw in step 2:
docker run --rm <ALPINE_IMAGE_1> sh -c 'apk info -v libcrypto3 2>/dev/null | head -n1' docker run --rm <ALPINE_IMAGE_2> sh -c 'apk info -v libcrypto3 2>/dev/null | head -n1' docker run --rm <ALPINE_IMAGE_3> sh -c 'apk info -v libcrypto3 2>/dev/null | head -n1'
✅ The correct image is the one that prints exactly:
libcrypto3-3.1.4-r5
Note that full image tag, e.g.:
IMG=alpine:3.xx
4) Create SPDX document with bom for that identified image
(Use the identified image from step 3.)
bom generate --image $IMG --format spdx --output /home/candidate/alpine.spdx Verify file exists:
ls -l /home/candidate/alpine.spdx
5) Remove ONLY the container that uses that image version
The manifest to edit is:
vi /home/candidate/alpine-deployment.yaml
In the spec.template.spec.containers: list, find the container entry whose image: equals the identified $IMG, and delete that one container block only (name/image/ports/etc for that container).
Save:
:wq
6) Apply the updated Deployment (do not change other containers)
kubectl apply -f /home/candidate/alpine-deployment.yaml
Wait rollout:
kubectl -n alpine rollout status deployment/alpine
7) Verify only 2 containers remain
kubectl -n alpine get deploy alpine -o jsonpath='{range .spec.template.spec.containers[*]}{.name}{"\t"}{.image}{"\n"}{end}' You should now see 2 lines, and the $IMG line should be gone.
If bom generate ... errors (quick fix)
Check exact syntax on that system:
bom --help
bom generate --help
Then rerun with the flags it expects, keeping:
image = $IMG
output = /home/candidate/alpine.spdx
format = spdx
Explanation:
1) Connect to the correct host
ssh cks000035
sudo -i
export KUBECONFIG=/etc/kubernetes/admin.conf
2) List the 3 container names + images in the Deployment
kubectl -n alpine get deploy alpine -o jsonpath='{range .spec.template.spec.containers[*]}{.name}{"\t"}{.image}{"\n"}{end}' You'll get 3 lines like:
c1 alpine:3.xx
c2 alpine:3.yy
c3 alpine:3.zz
3) Identify which alpine image has libcrypto3 at 3.1.4-r5
Fastest reliable method (since it's Alpine, just query apk inside each image):
Run these one-by-one for each image you saw in step 2:
docker run --rm <ALPINE_IMAGE_1> sh -c 'apk info -v libcrypto3 2>/dev/null | head -n1' docker run --rm <ALPINE_IMAGE_2> sh -c 'apk info -v libcrypto3 2>/dev/null | head -n1' docker run --rm <ALPINE_IMAGE_3> sh -c 'apk info -v libcrypto3 2>/dev/null | head -n1'
✅ The correct image is the one that prints exactly:
libcrypto3-3.1.4-r5
Note that full image tag, e.g.:
IMG=alpine:3.xx
4) Create SPDX document with bom for that identified image
(Use the identified image from step 3.)
bom generate --image $IMG --format spdx --output /home/candidate/alpine.spdx Verify file exists:
ls -l /home/candidate/alpine.spdx
5) Remove ONLY the container that uses that image version
The manifest to edit is:
vi /home/candidate/alpine-deployment.yaml
In the spec.template.spec.containers: list, find the container entry whose image: equals the identified $IMG, and delete that one container block only (name/image/ports/etc for that container).
Save:
:wq
6) Apply the updated Deployment (do not change other containers)
kubectl apply -f /home/candidate/alpine-deployment.yaml
Wait rollout:
kubectl -n alpine rollout status deployment/alpine
7) Verify only 2 containers remain
kubectl -n alpine get deploy alpine -o jsonpath='{range .spec.template.spec.containers[*]}{.name}{"\t"}{.image}{"\n"}{end}' You should now see 2 lines, and the $IMG line should be gone.
If bom generate ... errors (quick fix)
Check exact syntax on that system:
bom --help
bom generate --help
Then rerun with the flags it expects, keeping:
image = $IMG
output = /home/candidate/alpine.spdx
format = spdx
SIMULATION
On the Cluster worker node, enforce the prepared AppArmor profile
#include <tunables/global>
profile nginx-deny flags=(attach_disconnected) {
#include <abstractions/base>
file,
# Deny all file writes.
deny /** w,
}
EOF'
Edit the prepared manifest file to include the AppArmor profile.
apiVersion: v1
kind: Pod
metadata:
name: apparmor-pod
spec:
containers:
- name: apparmor-pod
image: nginx
Finally, apply the manifests files and create the Pod specified on it.
Verify: Try to make a file inside the directory which is restricted.
On the Cluster worker node, enforce the prepared AppArmor profile
#include <tunables/global>
profile nginx-deny flags=(attach_disconnected) {
#include <abstractions/base>
file,
# Deny all file writes.
deny /** w,
}
EOF'
Edit the prepared manifest file to include the AppArmor profile.
apiVersion: v1
kind: Pod
metadata:
name: apparmor-pod
spec:
containers:
- name: apparmor-pod
image: nginx
Finally, apply the manifests files and create the Pod specified on it.
Verify: Try to make a file inside the directory which is restricted.
正解:



SIMULATION


Two tools are pre-installed on the cluster's worker node:
Using the tool of your choice (including any non pre-installed tool), analyze the container's behavior for at least 30 seconds, using filters that detect newly spawning and executing processes.
Store an incident file at /opt/KSRS00101/alerts/details, containing the detected incidents, one per line, in the following format:

The following example shows a properly formatted incident file:





Two tools are pre-installed on the cluster's worker node:
Using the tool of your choice (including any non pre-installed tool), analyze the container's behavior for at least 30 seconds, using filters that detect newly spawning and executing processes.
Store an incident file at /opt/KSRS00101/alerts/details, containing the detected incidents, one per line, in the following format:

The following example shows a properly formatted incident file:



正解:
See explanation below
Explanation:





Explanation:





SIMULATION
Documentation
Installing the Sidecar, PeerAuthentication, Deployments
You must connect to the correct host . Failure to do so may result in a zero score.
[candidate@base] $ ssh cks000041
Context
A microservices-based application using unencrypted Layer 4 (L4) transport must be secured with Istio.
Task
Perform the following tasks to secure an existing application's Layer 4 (L4) transport communication using Istio.
Istio is installed to secure Layer 4 (L4) communications.
You may use your browser to access Istio's documentation.
First, ensure that all Pods in the mtls namespace have the istio-proxy sidecar injected.
Next, configure mutual authentication in strict mode for all workloads in the mtls namespace.
Documentation
Installing the Sidecar, PeerAuthentication, Deployments
You must connect to the correct host . Failure to do so may result in a zero score.
[candidate@base] $ ssh cks000041
Context
A microservices-based application using unencrypted Layer 4 (L4) transport must be secured with Istio.
Task
Perform the following tasks to secure an existing application's Layer 4 (L4) transport communication using Istio.
Istio is installed to secure Layer 4 (L4) communications.
You may use your browser to access Istio's documentation.
First, ensure that all Pods in the mtls namespace have the istio-proxy sidecar injected.
Next, configure mutual authentication in strict mode for all workloads in the mtls namespace.
正解:
See the Explanation below for complete solution
Explanation:
Below is the CKS exam-ready, step-by-step solution for QUESTION 15.
Follow exactly in this order. No extra changes.
QUESTION 15 - Istio mTLS (EXAM MODE)
1) Connect to the correct host
ssh cks000041
sudo -i
export KUBECONFIG=/etc/kubernetes/admin.conf
2) Ensure sidecar injection is enabled for the mtls namespace
2.1 Check current namespace labels
kubectl get ns mtls --show-labels
2.2 Enable automatic Istio sidecar injection
kubectl label namespace mtls istio-injection=enabled --overwrite
Verify:
kubectl get ns mtls --show-labels | grep istio-injection
Expected:
istio-injection=enabled
3) Ensure ALL Pods get the istio-proxy sidecar
Existing Pods will not get sidecars automatically.
You must restart workloads in the namespace.
3.1 Restart all Deployments in mtls
kubectl -n mtls rollout restart deployment
3.2 Verify Pods now have 2 containers (app + istio-proxy)
kubectl -n mtls get pods
Then check one Pod:
kubectl -n mtls get pod <pod-name> -o jsonpath='{.spec.containers[*].name}{"\n"}' Expected output includes:
istio-proxy
4) Configure mutual TLS (mTLS) in STRICT mode
4.1 Create a PeerAuthentication for the mtls namespace
cat <<EOF | kubectl apply -f -
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: mtls-strict
namespace: mtls
spec:
mtls:
mode: STRICT
EOF
5) Verify mTLS policy is applied
kubectl -n mtls get peerauthentication
kubectl -n mtls describe peerauthentication mtls-strict
Expected:
Mode: STRICT
6) Final verification (exam confidence check)
6.1 Confirm all Pods are Running
kubectl -n mtls get pods
6.2 Confirm sidecar injection everywhere
kubectl -n mtls get pods -o jsonpath='{range .items[*]}{.metadata.name}{" -> "}{.spec.containers[*].name}{"\n"}{end}' Each line must include istio-proxy.
Explanation:
Below is the CKS exam-ready, step-by-step solution for QUESTION 15.
Follow exactly in this order. No extra changes.
QUESTION 15 - Istio mTLS (EXAM MODE)
1) Connect to the correct host
ssh cks000041
sudo -i
export KUBECONFIG=/etc/kubernetes/admin.conf
2) Ensure sidecar injection is enabled for the mtls namespace
2.1 Check current namespace labels
kubectl get ns mtls --show-labels
2.2 Enable automatic Istio sidecar injection
kubectl label namespace mtls istio-injection=enabled --overwrite
Verify:
kubectl get ns mtls --show-labels | grep istio-injection
Expected:
istio-injection=enabled
3) Ensure ALL Pods get the istio-proxy sidecar
Existing Pods will not get sidecars automatically.
You must restart workloads in the namespace.
3.1 Restart all Deployments in mtls
kubectl -n mtls rollout restart deployment
3.2 Verify Pods now have 2 containers (app + istio-proxy)
kubectl -n mtls get pods
Then check one Pod:
kubectl -n mtls get pod <pod-name> -o jsonpath='{.spec.containers[*].name}{"\n"}' Expected output includes:
istio-proxy
4) Configure mutual TLS (mTLS) in STRICT mode
4.1 Create a PeerAuthentication for the mtls namespace
cat <<EOF | kubectl apply -f -
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: mtls-strict
namespace: mtls
spec:
mtls:
mode: STRICT
EOF
5) Verify mTLS policy is applied
kubectl -n mtls get peerauthentication
kubectl -n mtls describe peerauthentication mtls-strict
Expected:
Mode: STRICT
6) Final verification (exam confidence check)
6.1 Confirm all Pods are Running
kubectl -n mtls get pods
6.2 Confirm sidecar injection everywhere
kubectl -n mtls get pods -o jsonpath='{range .items[*]}{.metadata.name}{" -> "}{.spec.containers[*].name}{"\n"}{end}' Each line must include istio-proxy.
SIMULATION

Context
A PodSecurityPolicy shall prevent the creation of privileged Pods in a specific namespace.
Task
Create a new PodSecurityPolicy named prevent-psp-policy,which prevents the creation of privileged Pods.
Create a new ClusterRole named restrict-access-role, which uses the newly created PodSecurityPolicy prevent-psp-policy.
Create a new ServiceAccount named psp-restrict-sa in the existing namespace staging.
Finally, create a new ClusterRoleBinding named restrict-access-bind, which binds the newly created ClusterRole restrict-access-role to the newly created ServiceAccount psp-restrict-sa.


Context
A PodSecurityPolicy shall prevent the creation of privileged Pods in a specific namespace.
Task
Create a new PodSecurityPolicy named prevent-psp-policy,which prevents the creation of privileged Pods.
Create a new ClusterRole named restrict-access-role, which uses the newly created PodSecurityPolicy prevent-psp-policy.
Create a new ServiceAccount named psp-restrict-sa in the existing namespace staging.
Finally, create a new ClusterRoleBinding named restrict-access-bind, which binds the newly created ClusterRole restrict-access-role to the newly created ServiceAccount psp-restrict-sa.

正解:
See the Explanation below
Explanation:













Explanation:













SIMULATION

Context
This cluster uses containerd as CRI runtime.
Containerd's default runtime handler is runc. Containerd has been prepared to support an additional runtime handler, runsc (gVisor).
Task
Create a RuntimeClass named sandboxed using the prepared runtime handler named runsc.
Update all Pods in the namespace server to run on gVisor.


Context
This cluster uses containerd as CRI runtime.
Containerd's default runtime handler is runc. Containerd has been prepared to support an additional runtime handler, runsc (gVisor).
Task
Create a RuntimeClass named sandboxed using the prepared runtime handler named runsc.
Update all Pods in the namespace server to run on gVisor.

正解:
See the Explanation below
Explanation:









Explanation:








