Kubernetes security 101: 10 best practices to secure clusters, workloads, and runtime

Kubernetes security 101: 10 best practices to secure clusters, workloads, and runtime

Santerra Holler October 05, 2026

Kubernetes security 101: 10 best practices to secure clusters, workloads, and runtime

Kubernetes security means protecting clusters, workloads, and runtime activity with layered controls. Those controls include a hardened control plane, least-privilege access, trusted images, restricted pods, segmented networks, protected secrets, and continuous detection of what actually runs. Most incidents trace back to a short list of predictable gaps, such as wildcard RBAC, privileged containers, exposed kubelets, mutable image tags, and clusters with no default-deny network policy. This guide covers the 10 best practices that close those gaps, current as of October 2026. Each practice includes the controls to implement, a YAML or command example where it helps, and a way to check that the control is enforced. It is written for platform engineers, cloud security architects, and SOC teams who need an operational checklist for kubernetes security rather than a list of concepts.

Key takeaways

  • ✓Kubernetes security works in layers: supply chain, cluster configuration, identity and access, workload hardening, network, data, and runtime detection and response.
  • ✓Pod Security Admission with the restricted profile, default-deny NetworkPolicies, and namespace-scoped RBAC block most common attack paths before any workload runs.
  • ✓Secrets need encryption at rest through a KMS provider, an external secret store, rotation, and file mounts instead of environment variables.
  • ✓Audit logs only become useful for investigations when they are correlated with runtime events such as shells spawned inside containers or unexpected outbound connections.
  • ✓Every control needs a validation step, such as kube-bench, kubescape, kubectl auth can-i, or a server-side dry run, because configured and enforced are not the same thing.

What is Kubernetes security?

Kubernetes security is the set of controls that stop attackers from abusing the Kubernetes API, the nodes, the container images, and the running workloads to gain access, move laterally, or steal data. A common mental model is the Four Cs of cloud-native security: Code, Container, Cluster, and Cloud. Each layer depends on the one below it, so a perfectly hardened pod still falls if the cloud account or the API server is exposed.

Typical attack paths into a cluster look like this:

  • A vulnerable or backdoored image runs, and the attacker gets a shell inside a container.
  • The container runs privileged or mounts a hostPath, so the attacker escapes to the node.
  • The auto-mounted service account token has broad RBAC rights, so the attacker reads Secrets or creates new pods.
  • Flat pod networking and reachable cloud metadata endpoints let the attacker pivot to databases and cloud IAM credentials.

The table below maps each layer to its main risk, the native Kubernetes features that address it, and common open-source tools.

Layer Main risk Native Kubernetes controls Common tools
Supply chain Vulnerable, unsigned, or tampered images Admission control, image digests Trivy, Cosign, Kyverno, OPA Gatekeeper
Cluster configuration Exposed API server, kubelet, or etcd API server and kubelet flags, encryption at rest kube-bench, kubescape
Identity and access Wildcard RBAC, overused service account tokens RBAC, bound service account tokens, workload identity kubectl auth can-i, rbac-tool, kubeaudit
Workload Privileged pods, container escape Pod Security Admission, securityContext, seccomp, AppArmor, SELinux kubeaudit, kubescape
Network Lateral movement, data exfiltration NetworkPolicy, namespace isolation Calico, Cilium, service meshes for mTLS
Data Plaintext Secrets, leaked credentials EncryptionConfiguration with KMS, RBAC on Secrets External Secrets Operator, HashiCorp Vault, Secrets Store CSI Driver
Detection and response Attacks that pass every preventive control Audit logging Falco, SIEM, eBPF-based runtime sensors

The 10 best practices below follow these layers in order, starting with the cluster, then the workloads, then runtime.

Securing the cluster: best practices 1 to 3

Start by locking down the control plane, the identities that call the API, and the nodes that run your pods.

1. Harden the control plane and API server

The API server is the front door to everything in the cluster, and etcd holds every object, including Secrets. Responsibility depends on the deployment model. On EKS, GKE, and AKS the provider runs the control plane, which is one of the main reasons the Cloud Security Alliance outlines for choosing a managed Kubernetes service. You still own endpoint exposure, authentication, RBAC, nodes, and workloads.

  • ✓Use a private API endpoint or restrict it to authorized networks; never leave port 6443 open to the internet.
  • ✓Set , anonymous-auth=false and enable the NodeRestriction admission plugin on self-managed clusters.
  • ✓Enforce TLS everywhere, rotate certificates before expiry, and require client certificates for etcd.
  • ✓Encrypt and access-control etcd backups, because a backup is a full copy of every Secret.
  • ✓Stay within supported Kubernetes versions; the project maintains the three most recent minor releases.

Validate: run curl --insecure https://<api-endpoint>:6443/api from outside your network. It should time out or return 401/403, never a resource list.

2. Enforce least-privilege RBAC and workload identity

RBAC decides what every user and service account can do. The most common mistakes are cluster-admin bindings for CI pipelines, wildcard verbs or resources ("*"), and granting list on Secrets, which exposes their contents just like get does. Scope roles to a namespace and to specific verbs:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: deploy-reader
  namespace: payments
rules:
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: deploy-reader-ci
  namespace: payments
subjects:
- kind: ServiceAccount
  name: ci-bot
  namespace: payments
roleRef:
  kind: Role
  name: deploy-reader
  apiGroup: rbac.authorization.k8s.io
  • ✓Set automountServiceAccountToken: false on pods and service accounts that never call the API.
  • ✓Rely on short-lived, bound service account tokens instead of long-lived token Secrets.
  • ✓Use cloud workload identity (EKS Pod Identity or IRSA, GKE Workload Identity, Azure Workload Identity) instead of static cloud keys in pods.
  • ✓Block or audit the escalate, bind, and impersonate verbs, which allow privilege escalation.

Validate: kubectl auth can-i --list --as=system:serviceaccount:payments:ci-bot -n payments should show only what the role grants.

3. Lock down nodes and kubelets

An attacker who reaches a node reaches every pod on it. An exposed kubelet on port 10250 with anonymous access lets anyone list pods and run commands in them.

  • ✓Set kubelet , anonymous-auth=false, , authorization-mode=Webhook, and , read-only-port=0.
  • ✓Enable kubelet certificate rotation with , rotate-certificates.
  • ✓Use minimal, container-optimized node operating systems such as Bottlerocket, Flatcar, or Container-Optimized OS.
  • ✓Patch node images on a fixed schedule and replace nodes instead of patching them in place.
  • ✓Block pod access to the cloud metadata endpoint, or require IMDSv2 with a hop limit of 1 on AWS.

Validate: curl --silent --insecure https://<node-ip>:10250/pods should return 401 or 403.

Securing workloads: best practices 4 to 8

Workload controls decide what images enter the cluster, what those containers are allowed to do, who they can talk to, and how they receive credentials.

4. Secure the software supply chain

Admission control is your last chance to stop a bad image before it runs. Mutable tags like latest mean the image you scanned may not be the image you deploy.

  • ✓Scan images in CI and in the registry with tools such as Trivy, and generate an SBOM for every build.
  • ✓Sign images with Cosign and attach build provenance attestations (SLSA format).
  • ✓Pin images by digest (@sha256:...) and enable tag immutability in the registry.
  • ✓Allow images only from approved registries.

A Kyverno policy that rejects unsigned images from your registry looks like this:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-signed-images
spec:
  validationFailureAction: Enforce
  rules:
    - name: verify-signature
      match:
        any:
          - resources:
              kinds: ["Pod"]
      verifyImages:
        - imageReferences: ["registry.example.com/*"]
          attestors:
            - entries:
                - keys:
                    publicKeys: |-
                      -----BEGIN PUBLIC KEY-----
                      ...
                      -----END PUBLIC KEY-----

Validate: deploy an unsigned test image into a non-production namespace and confirm the API server rejects it.

Scanning produces far more CVEs than any team can patch. Rank findings by whether the vulnerable package is actually loaded in a running container and reachable from the network. This approach to vulnerability prioritization with runtime context shrinks the backlog to what attackers can actually use.

5. Apply Pod Security Standards and harden pod specs

The Pod Security Standards define three cumulative policies: Privileged (unrestricted), Baseline (blocks known privilege escalations such as hostNetwork, hostPID, and privileged containers), and Restricted (enforces current hardening best practices). Pod Security Admission enforces them per namespace with labels:

kubectl label ns payments pod-security.kubernetes.io/enforce=restricted

A pod that passes the restricted profile sets a securityContext like this:

spec:
  automountServiceAccountToken: false
  securityContext:
    runAsNonRoot: true
    runAsUser: 10001
    seccompProfile:
      type: RuntimeDefault
  containers:
    - name: api
      image: registry.example.com/api@sha256:<digest>
      securityContext:
        allowPrivilegeEscalation: false
        readOnlyRootFilesystem: true
        capabilities:
          drop: ["ALL"]
  • ✓Drop all Linux capabilities and add back only what the app needs, such as NET_BIND_SERVICE.
  • ✓Add AppArmor or SELinux profiles for workloads that handle sensitive data.
  • ✓Ban hostPath mounts, hostNetwork, and hostPID outside system namespaces.

Validate: before enforcing, run kubectl label --dry-run=server --overwrite ns payments pod-security.kubernetes.io/enforce=restricted. The API server lists every existing pod that would violate the profile.

6. Segment the network with default-deny policies

By default, every pod can talk to every other pod in the cluster. NetworkPolicies only take effect if your CNI enforces them (Calico, Cilium, and most managed CNIs do). Start each namespace with a default deny for ingress and egress, allowing only DNS:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny
  namespace: payments
spec:
  podSelector: {}
  policyTypes: ["Ingress", "Egress"]
  egress:
  - to:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: kube-system
      podSelector:
        matchLabels:
          k8s-app: kube-dns
    ports:
    - protocol: UDP
      port: 53
    - protocol: TCP
      port: 53
  • ✓Add explicit allow policies per service, selecting on pod labels rather than IP ranges.
  • ✓Restrict egress to known destinations to limit exfiltration and command-and-control traffic.
  • ✓Use a service mesh such as Istio or Linkerd for mTLS on east-west traffic where compliance requires encryption in transit.

Validate: kubectl run nettest --rm -it --image=busybox -n payments -- wget -T 2 http://orders.shop.svc.cluster.local should time out.

7. Manage secrets beyond etcd

Kubernetes Secrets are only base64-encoded unless you turn on encryption at rest. Anyone with get or list on Secrets, or with access to etcd or its backups, can read them.

  • ✓Configure an EncryptionConfiguration with a KMS provider (AWS KMS, Google Cloud KMS, Azure Key Vault) so etcd stores only ciphertext.
  • ✓Keep the source of truth in an external store such as HashiCorp Vault or AWS Secrets Manager, synced with External Secrets Operator or mounted with the Secrets Store CSI Driver.
  • ✓Rotate credentials automatically and prefer short-lived dynamic credentials for databases.
  • ✓Mount secrets as files instead of environment variables, which leak through crash dumps, debug logs, and /proc.
  • ✓Never commit Secret manifests to Git; use Sealed Secrets or an external store instead.

Validate: on a self-managed cluster, read a Secret directly from etcd with etcdctl get /registry/secrets/payments/db-creds. The value should start with a k8s:enc: prefix, not readable text.

8. Isolate tenants with namespaces, quotas, and node pools

Namespaces group resources and scope RBAC, but on their own they are not a security boundary. Pods in different namespaces share the node kernel, and ClusterRoleBindings cross every namespace.

  • ✓Apply a ResourceQuota and LimitRange to every namespace so one tenant cannot starve the cluster.
  • ✓Pair each namespace with its own PSA label, default-deny NetworkPolicy, and RoleBindings.
  • ✓Run sensitive or untrusted workloads on dedicated node pools using taints, tolerations, and node affinity.
  • ✓Use sandboxed runtimes such as gVisor or Kata Containers for untrusted code.

The tradeoff is cost and complexity. Dedicated node pools reduce bin-packing efficiency, and separate clusters are still the only hard boundary for hostile tenants.

Securing runtime: best practices 9 and 10

Runtime controls record what happens in the cluster and detect attacks that slip past every preventive control.

9. Enable audit logging and correlate it with runtime events

Kubernetes audit logs record who called the API, what they did, and when. They are off by default on self-managed clusters and often need to be enabled explicitly on managed services. Rules match in order, so put specific rules first:

apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata
  resources:
  - group: ""
    resources: ["secrets", "configmaps"]
- level: Request
  resources:
  - group: ""
    resources: ["pods/exec", "pods/attach"]
- level: RequestResponse
  verbs: ["create", "update", "patch", "delete"]
  resources:
  - group: "rbac.authorization.k8s.io"
- level: Metadata
  omitStages: ["RequestReceived"]

Logging Secrets at Metadata level avoids writing secret values into your logs. Ship audit logs to your SIEM, and join them with container runtime events. A pods/exec call in the audit log means much more when the same pod then opens an outbound connection to an unknown IP.

10. Run runtime detection and response

Runtime detection watches system calls, processes, file access, and network activity inside containers, typically using eBPF. Falco is the best-known open-source option. Useful indicators of compromise include:

  • A shell (sh, bash) spawned in a container that never runs one.
  • Writes to /etc, /usr/bin, or other binary directories in a running container.
  • Connections to the cloud metadata endpoint from application pods.
  • New privileged pods or ClusterRoleBindings created outside the CI pipeline.
  • Crypto-mining processes or connections to known mining pools.

A basic triage workflow:

  1. Confirm the alert with the audit log entry and the process tree from the runtime sensor.
  2. Scope the blast radius by checking the pod’s service account permissions, mounted secrets, and reachable services.
  3. Contain by applying a deny-all NetworkPolicy to the pod’s labels and cordoning the node.
  4. Preserve evidence (container filesystem, logs) before deleting the pod.
  5. Rotate exposed credentials and fix the root cause in the image, manifest, or RBAC.

Top Kubernetes misconfigurations and how to validate your controls

The most damaging Kubernetes misconfigurations are a small, well-known set, and automated tools can find nearly all of them. Check for these first:

  • Containers running privileged or as root.
  • Wildcard RBAC rules and cluster-admin bound to service accounts.
  • Kubernetes Dashboard exposed publicly or running with an admin service account.
  • No default-deny NetworkPolicy in application namespaces.
  • Mutable image tags such as latest.
  • hostPath mounts, hostNetwork, or hostPID in application pods.
  • Kubelets reachable with anonymous authentication.

If you need the Dashboard at all, deploy it without cluster-wide rights, keep it off public ingress, and require per-user tokens or SSO through kubectl proxy or an authenticating proxy.

Tool What it checks Example command
kube-bench Node and control plane settings against the CIS Kubernetes Benchmark kube-bench run --targets node
kubescape Manifests and live clusters against NSA/CISA and other frameworks kubescape scan framework nsa
kubeaudit Pod specs for root users, capabilities, and privileged settings kubeaudit all
Trivy Image CVEs, IaC misconfigurations, and cluster resources trivy k8s --report summary
Kyverno / OPA Gatekeeper Policy-as-code enforcement at admission, plus background audits kubectl get policyreport -A
Falco Runtime behavior against detection rules Trigger kubectl exec into a test pod and confirm an alert fires

Map these checks to the frameworks your auditors use: the CIS Kubernetes Benchmark, the NSA/CISA Kubernetes Hardening Guide, NIST SP 800-190, and the OWASP Kubernetes Top 10. Our overview of cloud security compliance frameworks explains how these fit into broader programs. Cloud-provider posture tools such as Amazon GuardDuty EKS Protection, Microsoft Defender for Containers, and GKE Security Posture add provider-specific checks, and a wider comparison of container security tools from scanning to runtime helps when you outgrow single-purpose utilities.

Configured or enforced? A policy in Git proves nothing. Every control above should have a test that tries to break it, run in CI or on a schedule against live clusters.

How Upwind secures Kubernetes at runtime

Upwind is a runtime-first CNAPP that uses lightweight eBPF sensors to see what is actually running in your clusters, then prioritizes Kubernetes risk by real runtime exposure instead of static configuration alone. That runtime context links posture findings, vulnerabilities, identities, and threats so teams fix the issues attackers can actually reach. One caveat is that teams running a single small cluster that only need an admission controller and a CIS scan may find a full platform more than they need.

  • ✓Vulnerability management shows which CVEs are loaded and reachable in running containers.
  • ✓Identity risk is based on which permissions are actually used.
  • ✓One sensor and one platform cover Kubernetes posture and workload protection.
  • ✓Cloud detection and response covers threats unfolding in clusters.
  • ✓AI agents (the Agentic Pack) investigate threats, validate exposure, and generate fixes.

A prioritized Kubernetes security roadmap

Block the most common attack paths first, then add isolation and detection as teams and clusters grow. Use these three stages:

  1. Foundational (new clusters): private API endpoint, anonymous auth disabled on the API server and kubelets, namespace-scoped RBAC with no wildcards, PSA Baseline enforced everywhere, image scanning in CI, audit logging on, and a monthly kube-bench run.
  2. Intermediate (scaling teams): PSA Restricted for application namespaces, default-deny NetworkPolicies, KMS encryption for Secrets plus External Secrets Operator, digest-pinned images, policy-as-code with Kyverno or Gatekeeper, workload identity, and runtime detection with alert routing to the SOC.
  3. Advanced (regulated or multi-tenant): signed images with provenance enforced at admission, SBOMs per release, dedicated node pools or sandboxed runtimes for untrusted tenants, mTLS for east-west traffic, correlated audit and runtime investigations, and continuous mapping to CIS, NIST, and NSA/CISA controls.

Adjust the roadmap to your deployment model. On managed services, the provider patches the control plane and etcd, so your effort shifts to endpoint access, node image updates, RBAC, and workloads. On self-managed clusters, every API server flag, certificate, etcd backup, and version upgrade is yours.

Start with the cluster, harden the workloads, and finish with runtime detection that tells you when prevention fails. Validate each control with a test that tries to break it, and kubernetes security becomes a measurable, repeatable practice instead of a one-time hardening project.

FAQ

What is Kubernetes security?

Kubernetes security is the practice of protecting clusters, workloads, and runtime activity with layered controls across the control plane, identities, images, pods, network, secrets, and detection. Its goal is to stop attackers from abusing the API, nodes, container images, and running workloads to gain access, move laterally, or steal data.

What are the most common Kubernetes security gaps?

The article highlights a short list of recurring issues: wildcard RBAC, privileged containers, exposed kubelets, mutable image tags such as latest, no default-deny NetworkPolicy, hostPath mounts, hostNetwork or hostPID in application pods, and broad access to Secrets. These misconfigurations are behind many real cluster incidents.

Which Kubernetes security controls should teams prioritize first?

The guide recommends starting with a private API endpoint, disabling anonymous auth on the API server and kubelets, namespace-scoped least-privilege RBAC, Pod Security Admission, image scanning in CI, audit logging, and a regular kube-bench run. As teams mature, they should add restricted pod policies, default-deny NetworkPolicies, KMS-backed secret encryption, workload identity, policy-as-code, and runtime detection.

How should Kubernetes Secrets be protected?

Secrets should be encrypted at rest with an EncryptionConfiguration backed by a KMS provider, managed from an external secret store when possible, rotated automatically, and mounted as files instead of environment variables. The article also warns that anyone with get or list access to Secrets, or access to etcd or its backups, can read them.

How do you verify Kubernetes security controls are actually enforced?

The article stresses testing every control, because configured and enforced are not the same. Examples include using kubectl auth can-i for RBAC, server-side dry runs for Pod Security Admission, kube-bench for control plane and node settings, kubescape and kubeaudit for misconfigurations, Trivy for images and cluster resources, and Falco or similar tools to confirm runtime alerts fire during safe test activity.

Contents
Add the Upwind RSS Feed to Slack
Connect the Upwind RSS Feed to your Slack.
Follow the how-to here.
Threat RSS
Add the Upwind RSS Feed to Slack
Connect the Upwind RSS Feed to your Slack.
Follow the how-to here.
Main RSS