How to pass CKS — Kubernetes Security Specialist exam. Part 1
CKS certification is a performance-based, hands-on exam that tests knowledge of K8s security in a simulated, real-world environment. I had 15 different tasks and 120 min to complete them. 68 % required to pass.

CKS requires CKA (Certified Kubernetes Administrator) passed first. It is a mandatory pre-request. I shared my tips in a different post on how to pass CKA and CKAD. If you received CKA, know how to use kubectl and Kubernetes documentation in an efficient way, you can start study for CKS. CKS is harder than the other two K8s exams. Good preparation requires deep study of native and external Kubernetes security tools, best security practices, and also requires a good knowledge of Kubernetes architecture, especially about API server, etcd, and kubelet. The exam covers the following areas: gVisor, AppArmor, RBAC, Network Policies, Auditing, Falco,Trivy, Admission Controllers, CIS Benchmark, Pod Security Policies, writing secure Dockerfiles, Secrets, Privileged Pods.
In the next episodes, I will share my experience of how to solve the exam tasks. I keep tips in the GitHub repo
- Episode — Network Policies
- Episode — gVisor
- Episode — Trivy
- Episode — AppArmor
- Episode — PodSecurityPolicies
- Episode — RBAC
- Dockerfile & SecurityContext
Network Policies
Configure bash auto-completion on Linux before you start the exam:
source <(kubectl completion bash)
alias k=kubectl
complete -F __start_kubectl k
Network Policies are an important topic on the exam. If you want to control traffic flow at the IP address or port level (OSI layer 3 or 4), then you should use K8s Network Policies. By default, all pods in a cluster can communicate with any other pod on the same cluster, including pods from different namespaces, and this includes the main kube-system namespace where the control plane is hosted. Unless changed, this is the network policy that is configured when you install Kubernetes and deploy your cluster. Network policies specify how groups of pods are allowed to communicate with each other and other network endpoints. You can think of them as the Kubernetes equivalent of a firewall.
“default-deny-all” network policy. It is a good practice to create default deny all Ingress traffic first and later Egress traffic in the namespace and just open necessary communication between pods or namespaces
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: test
spec:
podSelector: {}
policyTypes:
- Ingress
Ingress
(above) and Egress
(below) default deny
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: test
spec:
podSelector: {}
policyTypes:
- Egress
If we want to allow some traffic to or from Pods or namespaces, there are four kinds of selectors that can be specified in an ingress
from
section or egress
to
section:
podSelector — selects particular Pods in the same namespace as the NetworkPolicy which should be allowed as ingress sources or egress destinations,
namespaceSelector -selects particular namespaces for which all Pods should be allowed as ingress sources or egress destinations,
namespaceSelector and podSelector - both selectors must match
namespaceSelector or podSelector - one selector in an array must match
problem 1 — allow traffic to Pod with a label pod=ingress
in namespace test
from pods in the namespace default
or from pods in the local Namespace with the label demo=pod
solution — you need to explicitly set the label for namespace default
, the label is not added automatically during namespace creation
k label ns default ns=default
k get ns --show-labels
and apply the following YAML file (k apply -f file.yaml)
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: example-ingress
namespace: test
spec:
podSelector:
matchLabels:
pod: ingress
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
ns: default
- podSelector:
matchLabels:
demo: pod
problem 2 — allow traffic from Pod with a label pod=egress
in namespace test
to pods in the namespace default
and with the label demo=pod
.
solution — let's create required label:
k label ns default ns=default
k get ns --show-labels
and apply the following YAML file (k apply -f file.yaml)
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: example-egress
namespace: test
spec:
podSelector:
matchLabels:
pod: egress
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
ns: default
podSelector:
matchLabels:
demo: pod
problem 3 — allow traffic to all Pods in a namespace test
from pods in the namespace default
solution:
k label ns default ns=default
k get ns --show-labels
and create the following network policy
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: example-ingress
namespace: test
spec:
podSelector:{}
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
ns: default
if you need to display already existing labels
k get pods --show-labels
k get ns --show-labels
Examples from this post are available on GitHub. Thank you and see you soon in the next episode! The next post will be about gVisor.
