Kubernetes Security Overview

Section 06 Last updated: 2025 ~25 min read

On this page

  1. Kubernetes Threat Model
  2. The 4C Security Model
  3. Attack Surface Map
  4. Defense-in-Depth Layers
  5. Authentication & Authorization
  6. Workload Isolation
  7. Network Security
  8. Secrets & Supply Chain
  9. Runtime Security
  10. Compliance & Audit
  11. Security Hardening Checklist
  12. CIS Benchmark Summary
  13. Best Practices
Coverage checklist
  • Kubernetes threat model and STRIDE analysis
  • 4C security model (Cloud, Cluster, Container, Code)
  • Attack surface: API server, etcd, kubelet, supply chain
  • Defense-in-depth layer diagram
  • AuthN: X.509 / OIDC / ServiceAccount tokens / webhook
  • AuthZ: RBAC, ABAC, Node, Webhook modes
  • Admission control pipeline
  • Pod Security Admission (privileged/baseline/restricted)
  • Network policy default-deny pattern
  • Secrets: etcd encryption, external secret stores
  • Service account token security (bound tokens)
  • Image scanning: Trivy, Grype, Snyk
  • Supply chain: SBOM, Sigstore/cosign, provenance
  • Runtime security: Falco, seccomp, AppArmor, SELinux
  • Audit logging: levels, backend, retention
  • CIS Kubernetes Benchmark top controls
  • Security checklist 30 items
  • Best practices 8 items
  • mTLS between components: kube-apiserver TLS
  • etcd TLS client auth requirement
  • Anonymous auth disable
  • NodeRestriction admission plugin
  • Kubelet authorization mode: Webhook
  • read-only port 10255 disable
  • Privileged container risks
  • hostNetwork/hostPID/hostIPC risks
  • Capability drop ALL + add specific
  • seccompProfile RuntimeDefault
  • runAsNonRoot enforcement
  • readOnlyRootFilesystem
  • Resource limits as security control
  • IRSA / Workload Identity patterns
  • Namespace-based tenancy limitations
  • Links to all detailed sub-pages

Kubernetes Threat Model

Kubernetes clusters are complex distributed systems with a large attack surface. Understanding what can go wrong drives the security architecture. The Kubernetes threat model covers adversaries who are:

STRIDE Analysis

ThreatKubernetes ContextPrimary Mitigations
SpoofingImpersonating a service account, forging kubeconfig credentialsOIDC short-lived tokens, cert rotation, audit logging
TamperingModifying etcd data directly, patching running pods without audit trailetcd TLS+auth, etcd encryption at rest, audit log immutability
RepudiationDenying that a workload made a change; no record of API callsAudit logging with Request/Response levels retained off-cluster
Information DisclosureSecrets in env vars, overly permissive RBAC reads, pod spec dumpsEncryption at rest, external secret stores, RBAC least privilege
Denial of ServiceResource exhaustion via unconstrained workloads, etcd overloadResourceQuota, LimitRange, PriorityClass, rate limiting
Elevation of PrivilegeContainer escape via privileged pod, hostPath write, RBAC cluster-admin grantPod Security Admission (restricted), no privileged pods, RBAC audit

The 4C Security Model

The 4C model (Cloud, Cluster, Container, Code) describes a layered security approach. Each outer layer protects the layers within it, but a vulnerability at any layer can undermine the protections of the layers it contains.

┌────────────────────────────────────────────────────────────────┐
│                           CLOUD                                │
│  IAM roles, VPC network ACLs, node firewall rules,            │
│  cloud provider encryption, managed control plane TLS          │
│                                                                │
│  ┌──────────────────────────────────────────────────────────┐  │
│  │                        CLUSTER                           │  │
│  │  API server auth/authz, RBAC, admission controllers,     │  │
│  │  etcd encryption, network policies, audit logging        │  │
│  │                                                          │  │
│  │  ┌────────────────────────────────────────────────────┐  │  │
│  │  │                    CONTAINER                       │  │  │
│  │  │  Pod Security (seccomp, AppArmor, capabilities),   │  │  │
│  │  │  non-root execution, read-only rootfs, Falco       │  │  │
│  │  │                                                    │  │  │
│  │  │  ┌──────────────────────────────────────────────┐  │  │  │
│  │  │  │                  CODE                        │  │  │  │
│  │  │  │  SAST, dependency scanning, image signing,   │  │  │  │
│  │  │  │  SBOM, Sigstore provenance, secret scanning  │  │  │  │
│  │  │  └──────────────────────────────────────────────┘  │  │  │
│  │  └────────────────────────────────────────────────────┘  │  │
│  └──────────────────────────────────────────────────────────┘  │
└────────────────────────────────────────────────────────────────┘
Outer layers do not compensate for inner layer weaknesses. A privileged container on a locked-down node can still escape to the host. Cloud IAM does not prevent a cluster-admin RBAC binding from being abused. Security must be enforced at every layer independently.

Attack Surface Map

EXTERNAL                          CLUSTER INTERNAL
─────────                         ──────────────────
kubectl / CI/CD ──► API Server ──► etcd (CRITICAL — encrypt + TLS client auth)
                        │
                        ├──► Controller Manager (in-cluster RBAC)
                        ├──► Scheduler (in-cluster RBAC)
                        └──► Kubelet API (port 10250)
                                    │
                             ┌──────┴──────┐
                             │  Node OS    │
                             │  Container  │
                             │  Runtime    │
                             └─────────────┘
                                    │
                             ┌──────▼──────┐
                             │   Pods      │
                             │ ServiceAcct │──► cloud IAM via IRSA/Workload Identity
                             └─────────────┘

High-Value Targets

TargetWhy CriticalKey Hardening
etcdAll cluster state including secrets; direct write bypasses all admissionTLS client cert auth, encryption at rest, firewall to API server only
API serverSingle entry point for all cluster operationsDisable anonymous auth, enable audit, RBAC, admission plugins
KubeletPort 10250 allows exec/logs for all pods on nodeWebhook authorization, disable read-only port 10255, NodeRestriction
Service account tokensAuto-mounted; long-lived tokens give persistent API accessBound tokens (expiry), automountServiceAccountToken: false default
Container imagesBackdoored images run attacker code at cluster scaleImage signing (cosign), admission policy (image policy webhook)

Defense-in-Depth Layers

🔐

Authentication

Who can talk to the API server? X.509 client certs, OIDC tokens (Dex, Okta), ServiceAccount bound tokens, webhook token authenticators.

🛡️

Authorization (RBAC)

What are they allowed to do? Role, ClusterRole, RoleBinding, ClusterRoleBinding — least-privilege per workload. Covered in 01-rbac.html.

🚦

Admission Control

Mutating and validating webhooks, OPA/Gatekeeper, Kyverno, Pod Security Admission. Final gate before objects are persisted. Covered in 06-admission-controllers.html.

🌐

Network Policies

Default-deny east-west traffic; explicit allow rules per service. Requires a CNI that enforces policies (Cilium, Calico, Weave). Covered in 03-network-policies.html.

🔒

Pod Security

seccomp, AppArmor, Linux capabilities, non-root, read-only rootfs, no privilege escalation. Covered in 02-pod-security.html.

🗝️

Secrets Management

etcd encryption at rest, external secret stores (Vault, AWS SSM, CSI driver), short rotation windows. Covered in 04-secrets-management.html.

📦

Image & Supply Chain

Vulnerability scanning (Trivy), image signing (cosign/Sigstore), SBOM generation, admission policy enforcement. Covered in 07-image-security.html and 10-supply-chain-security.html.

🔍

Runtime Security

Falco behavioral detection, eBPF-based syscall monitoring, anomaly alerting. Covered in runtime section.

📋

Audit Logging

All API server requests recorded at configurable levels; shipped off-cluster for immutability. Covered in 08-audit-logging.html.

Authentication & Authorization

Authentication Methods

MethodUse CaseToken LifetimeNotes
X.509 client certsAdmin users, control-plane componentsUp to cert expiryRevocation requires CRL or cert rotation; hard to revoke individual users
OIDC tokensHuman users via Dex, Okta, Auth0, Azure ADTypically 1h (JWT exp)Short-lived; requires --oidc-issuer-url API server flag
ServiceAccount tokens (bound)In-cluster workloads (1.20+ projected volumes)Configurable (default 1h)Audience + expiry + pod binding; replaces legacy static tokens
Bootstrap tokensNode join (kubeadm)24h defaultsystem:bootstrappers group; deleted after join
Webhook token authenticatorExternal identity providersProvider-definedAPI server calls webhook; flexible but adds latency
Static token fileTesting onlyPermanent until restartNever use in production

Authorization Modes

The API server evaluates authorization modes in the order specified by --authorization-mode. A request is allowed if any mode permits it (short-circuit on first Allow).

ModeDescriptionProduction Use
RBACRole-based; fine-grained verb+resource rules✅ Always enable
NodeRestricts kubelet to only read/write resources belonging to its own node✅ Always enable (with NodeRestriction admission)
WebhookDelegates to external HTTP endpoint (OPA, custom systems)Optional; for complex policies
ABACFile-based attribute policies; requires restart to update❌ Legacy; superseded by RBAC
AlwaysAllowNo authorization check❌ Testing only
AlwaysDenyAll requests denied❌ Testing only
Required authorization mode for production. Always run --authorization-mode=Node,RBAC at minimum. Node mode + NodeRestriction admission prevents a compromised kubelet from reading secrets for pods not running on its node.

Admission Control Pipeline

After a request passes authentication and authorization, it passes through the admission control pipeline before being persisted to etcd:

Request → AuthN → AuthZ → Mutating Admission → Object Schema Validation → Validating Admission → etcd
                              │                                                      │
                     MutatingWebhookConfigurations                   ValidatingWebhookConfigurations
                     Pod Security Admission (mutate)                 Pod Security Admission (validate)
                     LimitRanger                                      OPA/Gatekeeper
                     ServiceAccount token injection                   Kyverno
                     NamespaceLifecycle                               ResourceQuota

Key built-in admission plugins (enabled by default or recommended):

PluginPurpose
NamespaceLifecyclePrevents creating objects in terminating namespaces
LimitRangerEnforces LimitRange defaults and constraints
ServiceAccountInjects default service account token
NodeRestrictionLimits kubelet to mutate only its own Node/Pod objects
PodSecurityEnforces Pod Security Standards (privileged/baseline/restricted)
ResourceQuotaEnforces namespace resource quotas
MutatingAdmissionWebhookCalls registered mutating webhooks
ValidatingAdmissionWebhookCalls registered validating webhooks

Workload Isolation

Pod Security Standards

Pod Security Admission (PSA) enforces three built-in policy levels per namespace, applied via the label pod-security.kubernetes.io/enforce. See 02-pod-security.html for the full field-by-field breakdown.

LevelWho Should Use ItWhat It Allows
privilegedSystem namespaces (kube-system, node agents)No restrictions — full host access possible
baselineGeneral workloads needing some elevated permissionsNo privileged containers; no host namespaces; restricted capabilities
restrictedUntrusted or hardened production workloadsEnforces seccomp RuntimeDefault, non-root, no privilege escalation, drop ALL caps

Namespace Tenancy Model

Namespaces provide a soft isolation boundary — they scope RBAC, ResourceQuota, NetworkPolicy, and PSA. They do not provide hard multi-tenancy; a privileged workload in any namespace can reach the host. For stronger isolation, use separate clusters or hierarchical namespace controllers (HNC).

Namespace security labels — apply to all tenant namespaces.
kubectl label namespace my-app \
  pod-security.kubernetes.io/enforce=restricted \
  pod-security.kubernetes.io/audit=restricted \
  pod-security.kubernetes.io/warn=restricted
Use enforce to block, audit to log violations, warn to surface warnings without blocking.

Key Pod-Level Security Fields

securityContext:                      # Pod-level
  runAsNonRoot: true
  runAsUser: 1000
  runAsGroup: 3000
  fsGroup: 2000
  seccompProfile:
    type: RuntimeDefault               # or Localhost with custom profile
  sysctls: []                          # avoid privileged sysctls

containers:
  - securityContext:                   # Container-level (overrides pod-level)
      allowPrivilegeEscalation: false  # prevent setuid/sudo escalation
      readOnlyRootFilesystem: true
      capabilities:
        drop: ["ALL"]
        add: ["NET_BIND_SERVICE"]      # only if port < 1024 needed
      seccompProfile:
        type: RuntimeDefault

Network Security

Default-Deny Pattern

Without Network Policies, all pods can communicate freely within a cluster. The correct default is to deny all ingress and egress, then explicitly allow required flows. See 03-network-policies.html for full examples.

# Apply to every tenant namespace
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
spec:
  podSelector: {}          # matches all pods
  policyTypes:
  - Ingress
  - Egress
  # no ingress/egress rules = deny all
Network Policies require a CNI that enforces them. The default kubenet CNI does not enforce NetworkPolicy. Use Cilium, Calico, Weave Net, or another policy-capable CNI. Pods are unprotected if you create NetworkPolicy objects but the CNI doesn't implement them — no error is raised.

mTLS for Service-to-Service

NetworkPolicy operates at L3/L4 (IP + port). For L7 identity-based traffic control and end-to-end encryption, use a service mesh (Istio, Linkerd, Cilium's mesh mode). mTLS provides:

Secrets & Supply Chain

Secret Storage Risk Hierarchy

Storage MethodRisk LevelNotes
Plain text in source code / ConfigMapCriticalNever do this
Kubernetes Secret (base64, no etcd encryption)HighReadable by anyone with etcd access or broad RBAC
Kubernetes Secret + etcd encryption at restMediumProtects stolen etcd backup; API server still decrypts on read
External Secret Operator (Vault / AWS SSM)LowSecrets never reside in etcd; centralized rotation; audit trail
CSI secrets store driver (SSCD)LowMounted as files, not env vars; ephemeral, rotated by provider

Supply Chain Attack Vectors

See 10-supply-chain-security.html for Sigstore/cosign signing workflow, SBOM generation with Syft, and admission policy enforcement with Kyverno image verification.

Runtime Security

Linux Kernel Security Mechanisms

MechanismWhat It DoesKubernetes Integration
seccompRestricts allowed syscalls; blocks dangerous calls like ptrace, mount, unsharesecurityContext.seccompProfile; RuntimeDefault or custom JSON profile
AppArmorFile/capability access profiles per processcontainer.apparmor.security.beta.kubernetes.io/<container> annotation (GA in 1.30)
SELinuxMandatory access control; label-based policy enforcementsecurityContext.seLinuxOptions; typically set by runtime on RHEL/CoreOS
Linux capabilitiesSplit root privileges into fine-grained tokenscapabilities.drop: ["ALL"] + explicit add of needed caps
NamespacesIsolate process view: PID, net, IPC, UTS, mountContainer runtime manages; hostPID/hostNetwork/hostIPC: false

Falco — Behavioral Runtime Detection

Falco (CNCF) monitors kernel syscalls via eBPF/kernel module and alerts on policy violations at runtime. Key default rules:

Falco does not prevent — it detects. Falco alerts on violations after the syscall occurs. It is a detection control, not a prevention control. Pair it with admission policies (Kyverno/OPA) for prevention, and Falco for detection of what admission policies miss (runtime behavior, zero-days).

Compliance & Audit

Kubernetes audit logging records every API server request at configurable verbosity levels. Logs should be shipped to immutable storage (S3, Elasticsearch, Splunk) off-cluster immediately. See 08-audit-logging.html for audit policy examples.

Compliance Frameworks

FrameworkKubernetes RelevanceKey Controls
CIS Kubernetes BenchmarkPrescriptive hardening for control plane, nodes, RBACAPI server flags, etcd TLS, RBAC audit, node config
NSA/CISA Kubernetes Hardening GuideGovernment/defense-grade guidancePod security, network policies, audit, image provenance
SOC 2 Type IIAudit trail completeness, access controlAudit logging, RBAC reviews, secret management, MFA for API access
PCI DSSCardholder data environment isolationNetwork segmentation (policies), encryption at rest+transit, audit, vulnerability scanning
HIPAAPHI in containersEncryption at rest, audit, BAA with cloud provider, access control
FedRAMPUS federal cloud authorizationFIPS 140-2 crypto, STIG compliance, continuous monitoring

See 11-compliance.html for compliance automation tools (kube-bench, Polaris, Kubescape).

Security Hardening Checklist

Control Plane

CheckCommand / VerificationPriority
Disable anonymous auth--anonymous-auth=false on kube-apiserverCritical
Enable Node+RBAC authorization--authorization-mode=Node,RBACCritical
Enable audit logging--audit-log-path + --audit-policy-fileCritical
etcd TLS + client cert auth--etcd-cafile --etcd-certfile --etcd-keyfileCritical
etcd encryption at rest--encryption-provider-config with aescbc or KMSCritical
Enable NodeRestriction admission--enable-admission-plugins=...,NodeRestrictionCritical
Disable insecure HTTP port--insecure-port=0 (default disabled since 1.20)Critical
TLS cipher restriction--tls-min-version=VersionTLS13High
Enable PodSecurity admission--enable-admission-plugins=...,PodSecurityHigh
Rotate certificates regularlykubeadm certs renew all; automate via cert-managerHigh

Nodes

CheckVerificationPriority
Kubelet authorization mode: Webhook--authorization-mode=Webhook in kubelet configCritical
Disable read-only port--read-only-port=0 in kubelet configCritical
Disable anonymous kubelet authauthentication.anonymous.enabled: falseCritical
Enable kubelet TLS--tls-cert-file --tls-private-key-fileCritical
Restrict hostPath mountsAdmission policy: deny hostPath.path: / or /etcHigh
CIS-hardened node imageUse CIS-hardened AMI/image; run kube-bench to verifyHigh

Workloads

CheckImplementationPriority
No privileged containersPSA restricted or Kyverno deny privileged: trueCritical
No hostNetwork / hostPID / hostIPCPSA baseline+ or admission policyCritical
Drop ALL capabilitiescapabilities.drop: ["ALL"]High
seccomp RuntimeDefaultseccompProfile.type: RuntimeDefaultHigh
runAsNonRootrunAsNonRoot: true + runAsUser: 1000High
readOnlyRootFilesystemreadOnlyRootFilesystem: trueHigh
No allowPrivilegeEscalationallowPrivilegeEscalation: falseHigh
automount SA token only when neededautomountServiceAccountToken: false on SA or PodHigh
Resource limits set on all containersLimitRange defaults + explicit limitsMedium
Network policies: default denyApply default-deny NetworkPolicy to all tenant namespacesHigh

CIS Benchmark Key Controls Summary

The CIS Kubernetes Benchmark (Center for Internet Security) is the most widely adopted prescriptive hardening guide. Run kube-bench to automatically check your cluster against the benchmark. Key sections:

SectionFocus AreaExample Checks
1 — Control Plane Componentskube-apiserver, etcd, scheduler, controller-manager flags--anonymous-auth=false, --audit-log-path, etcd TLS
2 — Etcdetcd security configurationPeer TLS, client cert auth, encryption at rest
3 — Control Plane Configkubeconfig file permissions, certificatesadmin.conf permissions 600, cert expiry monitoring
4 — Worker Node SecurityKubelet configurationWebhook authn/authz, read-only port disabled
5 — Kubernetes PoliciesRBAC, Pod Security, Network Policies, SecretsNo cluster-admin bindings for SA, PSA enabled, secrets encrypted
# Run kube-bench in-cluster
kubectl apply -f https://raw.githubusercontent.com/aquasecurity/kube-bench/main/job.yaml
kubectl logs job/kube-bench

# Or run as a pod targeting specific benchmark
kubectl run kube-bench --image=aquasec/kube-bench:latest \
  --restart=Never -- node --benchmark cis-1.8

Best Practices

  1. Apply the 4C model systematically. Don't rely on cluster security alone. Harden the cloud layer (IAM, VPC), the container layer (seccomp, capabilities), and the code layer (SAST, image scanning) independently.
  2. Enforce Pod Security Standards at the restricted level for all non-system namespaces. Use enforce mode (not just warn) on all workload namespaces. Reserve privileged level for kube-system and node agent namespaces only.
  3. Use short-lived, bound service account tokens. Disable legacy auto-mounted tokens (automountServiceAccountToken: false on default ServiceAccount per namespace). Inject tokens only for pods that need API server access, using projected volumes with a 1h audience-bound expiry.
  4. Encrypt secrets at rest and prefer external secret stores. etcd encryption at rest protects stolen backups; an external store (Vault, AWS SSM) additionally prevents secrets from residing in etcd at all. Use IRSA/Workload Identity for cloud-native secret retrieval without static credentials.
  5. Implement default-deny NetworkPolicy in every tenant namespace. Then explicitly allow required ingress/egress. This prevents east-west lateral movement after a container compromise.
  6. Sign all images with cosign and enforce policy in admission. A Kyverno ClusterPolicy or OPA Gatekeeper constraint should reject pods using unsigned images from unauthorized registries. This blocks most supply chain attacks.
  7. Ship audit logs off-cluster immediately to immutable storage. A compromised cluster admin can delete on-cluster audit logs. Ship to an external SIEM (Splunk, Elasticsearch, CloudWatch) with a write-once policy.
  8. Run CIS kube-bench and address all Level 1 failures before production. Automate kube-bench as part of cluster provisioning CI. Re-run after every control plane upgrade. Track benchmark drift in a dedicated Grafana dashboard.