I've been living inside Kubernetes security documentation for the past few weeks, and I want to share everything I'm learning as I prepare for the Certified Kubernetes Security Specialist (CKS) exam.
If you're on the same journey, or if you're a DevOps/Platform engineer who just wants to harden your cluster without the exam pressure, this one's for you.
Starting with Benchmarks โ CIS & Kube-bench
Before you can secure anything, you need to know what you're securing and where the gaps are. That's where CIS Benchmarks come in.
I started running the CIS-CAT Lite assessor against my lab environment:
sh /root/Assessor/Assessor-CLI.sh -i -rd /var/www/html/ -nts -rp indexOne thing to keep in mind: CIS-CAT Lite only supports Windows 10, Ubuntu, Google Chrome, and macOS. If you're working with Kubernetes specifically, you need CIS-CAT Pro, which covers Kubernetes v1.6.1+.
For Kubernetes-native scanning, kube-bench is your best friend. It checks your cluster nodes against CIS Kubernetes Benchmark controls and gives you a detailed pass/fail report. Run it early, run it often.
Kubernetes Security Primitives โ The Mental Model
Here's the mental model I keep coming back to: the kube-apiserver is the heart of your security posture.
Every kubectl command, every internal component communication, every service account call โ it all flows through kube-apiserver. So if you're thinking about where to start hardening, start there.
There are two fundamental questions you need to answer:
1. Who can access the cluster?
- Static token files
- X.509 Certificates
- External auth providers (LDAP, OIDC)
- Service Accounts (for workloads)
2. What can they do once they're in?
- RBAC Authorization (most common)
- ABAC Authorization (attribute-based, older approach)
- Node Authorization
- Webhook mode (e.g., Open Policy Agent)
On top of that, all communication between Kubernetes components happens over TLS, and traffic within the cluster is managed by Network Policies.
That's the full picture at a high level. Now let's go deeper.
Authentication โ Who Are You?
Kubernetes handles authentication differently depending on the type of identity:
Admins / Developers : kube-apiserver (certs, tokens)
End Users : Application layer (not Kubernetes' concern)
Bots / Automation: Service Accounts
Service Accounts
Service accounts are for applications โ think Prometheus, Jenkins, your CI/CD pipeline. Every namespace gets a default service account automatically.
Creating and using a token is straightforward:
# Create a time-bound token
kubectl create token my-service-account --duration 2h
# Use it to hit the API directly
curl https://192.162.56.70:6443/api --insecure \
--header "Authorization: Bearer $TOKEN"When a service account is attached to a pod, Kubernetes does three things automatically:
- Creates a token and mounts it as a projected volume
- Rotates the token automatically
- Expires the token when the pod is deleted
This is much cleaner than the old static secret-based tokens. Use it.
TLS Certificates โ The Trust Layer
If there's one concept that shows up everywhere in CKS prep, it's TLS. Kubernetes uses certificates for everything.
A quick terminology anchor:
.crt/.pemโ Public key (the certificate).key/.pemโ Private key (keep this safe)
The three types of certificates in Kubernetes:
- Server certificates โ used by API server, etcd, kubelet
- Client certificates โ used by kubectl, scheduler, controller-manager
- Root certificates (CA) โ the Certificate Authority that signs everything else

The Certificates API
Here's something I didn't fully appreciate before: the CA private key lives on the master node, and whoever controls that file controls your entire cluster's identity system. That's why you protect that node like it's your life.
Kubernetes has a built-in mechanism for managing this โ the Certificates API using CertificateSigningRequest objects:
kubectl get csrAll certificate operations are handled by the controller-manager โ specifically the CSR-APPROVING and CSR-SIGNING controllers.

KubeConfig โ Stop Typing Certs Manually
You could pass your certificates in every curl command. You should not do that.
# Nobody wants to write this every time
curl --cert admin.crt --key admin.key --cacert ca.crt https://...The KubeConfig file (~/.kube/config) organizes this cleanly into three sections:
- clusters โ which cluster, what endpoint
- users โ who you are, what credentials
- contexts โ maps a user to a cluster

Here's how to programmatically extract what you need from kubeconfig:
# Get API server endpoint
APISERVER=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}')
# Extract CA cert if it's embedded
kubectl config view --raw -o jsonpath='{.clusters[0].cluster.certificate-authority-data}' \
| base64 --decode > ca.crt
# Get a service account token (older method)
SECRET_NAME=$(kubectl get serviceaccount my-service-account -o jsonpath='{.secrets[0].name}')
TOKEN=$(kubectl get secret $SECRET_NAME -o jsonpath='{.data.token}' | base64 --decode)
# Make an authenticated API call
curl --cacert ca.crt -H "Authorization: Bearer $TOKEN" \
"$APISERVER/api/v1/namespaces/default/pods"Authorization โ What Can You Do?
Once a request is authenticated, it goes through authorization. The mode is set in kube-apiserver:
--authorization-mode=Node,RBAC,WebhookThe key insight: these are evaluated in order. If Node denies it โ check RBAC โ if RBAC allows it, done. If not โ move to Webhook.
RBAC in Practice
RBAC is the most common and most important to master for CKS:
Role+RoleBindingโ namespace-scopedClusterRole+ClusterRoleBindingโ cluster-wide
The --authorization-mode chain looks like this in practice:
User Request โ Node Authorizer โ RBAC โ Webhook (OPA)Kubelet Security
The kubelet exposes two ports that are worth knowing:
Port Description 10250 Full API access (authenticated) 10255 Unauthenticated read-only access

Port 10255 being open and unauthenticated is a serious misconfiguration in production. Lock it down. Kubelet authentication supports certificates and API bearer tokens; authorization defaults to AlwaysAllow but should be set to Webhook in hardened environments.
Network Policies โ Zero Trust Inside the Cluster
By default, Kubernetes allows all pod-to-pod communication. That's fine for development. That's terrifying for production.
Network Policies let you define ingress and egress rules at the pod level. Think of them as firewall rules for your cluster.
One important caveat: not all CNI plugins support NetworkPolicy.
Plugin NetworkPolicy Support
Calico โ Yes
Kube-router โ Yes
Romana โ Yes
Flannel โ No
If you're using Flannel and relying on Network Policies, your policies are being silently ignored. Switch to Calico.
Ingress โ Layer 7 Routing Done Right
Ingress is essentially a Layer 7 load balancer that you configure using native Kubernetes primitives. You still need to expose it externally, but once you do, a single Ingress controller can handle routing, TLS termination, and more.
Popular Ingress controllers:
- Nginx (most common)
- GCE (Google Cloud native)
- Traefik, HAProxy, Contour, Istio
Setting up Nginx as an Ingress controller involves:
- A Deployment with Nginx config (error log path, keep-alive, SSL protocols)
- A ConfigMap for those configs
- A Service to expose it externally
- A ServiceAccount for RBAC
Securing Node Metadata
Node metadata exposure is an attack surface that often gets overlooked. Here's why it matters:
- Unauthorized access โ attacker identifies kubelet version โ targets known CVEs
- Misconfiguration โ removing a taint accidentally โ non-production workloads schedule on production nodes
- Privacy breach โ attacker maps internal IP addresses โ enables targeted DDoS
- Compliance failure โ kernel versions exposed โ violates GDPR, HIPAA, PCI-DSS
Protection Strategies
- Node Isolation โ reserve nodes for specific workloads using taints/tolerations
- Network Policies โ restrict which services can talk to which nodes
- Audit Logging โ track every access to node metadata
- Regular Patching โ keep node OS and Kubernetes components updated
Auditing โ The Forensic Trail
Kubernetes audit logging answers four questions:
- Who made the request?
- When did it happen?
- What was the action?
- How was it performed?
This matters for more than debugging โ it's required for GDPR, HIPAA, and PCI-DSS compliance. When an incident happens (and eventually it will), your audit log is the difference between "we know exactly what happened" and guessing.
Audit policy levels go from least to most verbose:
Noneโ don't logMetadataโ log request metadata onlyRequestโ log metadata + request bodyRequestResponseโ log everything including response body
Cluster Upgrades โ The One Minor Version at a Time Rule
A quick note on upgrades since it's part of CKS scope: Kubernetes only supports the 3 most recent minor versions at any given time.
Upgrade path: always one minor version at a time.

v1.11 โ v1.12 โ v1.13 โ
v1.11 โ v1.13 โThe upgrade workflow per node:
kubectl drain <node> # Evict workloads
# ... upgrade kubelet, kubeadm
kubectl uncordon <node> # Bring node backVerifying Platform Binaries
One thing I hadn't thought about before CKS prep: verifying the integrity of Kubernetes binaries before deploying them.
Generate the SHA checksum and compare it against what's published on the Kubernetes release page:
sha512sum kubectl
# Compare output with official checksum on kubernetes.io/releasesIf they don't match, don't deploy. Simple, but often skipped.
API Groups โ The Structure of the Kubernetes API
Understanding the API group hierarchy helps you write precise RBAC rules:
/api(core group) โv1: pods, namespaces, services, configmaps/apis(named groups):appsโ deployments, replicasetsnetworking.k8s.ioโ ingress, network policiescertificates.k8s.ioโ CSRsauthentication.k8s.ioโ token reviews- Utility endpoints:
/healthz,/metrics,/version,/logs
When writing RBAC roles, you reference these groups directly. Know the structure and writing policies becomes intuitive.
Wrapping Up
CKS prep is genuinely humbling. You think you know Kubernetes security until you sit down and try to explain why TLS bootstrapping works the way it does, or what happens when your audit policy is set to RequestResponse in a high-traffic cluster.
The content I've covered here spans:
- Benchmark scanning (CIS-CAT, kube-bench)
- Authentication mechanisms (certs, service accounts, tokens)
- TLS architecture and the Certificates API
- RBAC and authorization chains
- Kubelet hardening
- Network Policies and CNI compatibility
- Ingress controller setup
- Node metadata protection
- Audit logging for compliance
- Safe upgrade procedures