Before you can secure Kubernetes, you must understand how it works — specifically, how requests flow through the API server, how authentication and authorization decisions are made, and where the attack surface lies.
Kubernetes Architecture Through a Security Lens
Every Kubernetes interaction goes through the API Server. The API Server authenticates the request (who are you?), authorizes it via RBAC (are you allowed?), runs admission controllers (should this be modified or rejected?), and then writes to etcd (the cluster state store). Each step is a security boundary. Each step can be misconfigured.
RBAC Deep Dive
Role-Based Access Control is Kubernetes' primary authorization mechanism. It consists of Roles (what permissions exist), RoleBindings (who gets those permissions), ClusterRoles (cluster-wide permissions), and ClusterRoleBindings (cluster-wide assignments).
# Least-privilege Role: read pods in one namespace only
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: production
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
---
# Bind to a specific service account
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
namespace: production
name: read-pods
subjects:
- kind: ServiceAccount
name: monitoring-agent
namespace: production
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
Kubernetes Admission Flow
Admission controllers run AFTER authentication and authorization but BEFORE the object is persisted. They can mutate requests (MutatingAdmissionWebhook) or reject them (ValidatingAdmissionWebhook). This is where policy engines like OPA Gatekeeper and Kyverno plug in.
The Kubernetes Attack Surface
- API Server: Exposed without auth? Anonymous access enabled? Insecure port open?
- etcd: Unencrypted? Accessible without mTLS? Secrets stored in plaintext?
- Kubelet: Anonymous auth enabled? Read-only port exposed?
- Service Accounts: Default SA with auto-mounted tokens? Overly broad ClusterRoleBindings?
- Pods: Running as root? hostPID? hostNetwork? Privileged containers?