Cart

    Sorry, we could not find any results for your search querry.

    Securing Kubernetes: nodes, containers, gateways, and persistent volumes

    Kubernetes lets you deploy workloads quickly, but it also increases your attack surface: more services, more dependencies, and more paths for traffic and data. This guide explains how to secure your own workloads, from containers and gateways to storage.

    The control plane is outside the scope of this guide because TransIP manages it. You therefore focus on your namespaces, RBAC, pods, images, network access, and volumes.

    • Follow the principle of least privilege: grant only the access a workload actually needs.
       
    • Publish traffic through a central gateway with TLS, not directly from every service.
       
    • Use only trusted images and update them promptly when CVEs or dependency updates become available.
       
    • Treat storage, Secrets, and network rules as part of your security, not as separate aftercare.
     

     

    Logically separate workloads

     

    Security starts with separation. A test application, production application, and CI workload should not automatically share the same permissions, network reachability, and storage.

    • Namespace: give each application, environment, or tenant its own namespace so that policies, quotas, and access remain predictable.
    • Label and selector: use a consistent label and selector strategy to ensure that policies, Deployments, and Services apply only to the correct workloads.
    • Taints and tolerations: reserve sensitive nodes for specific workloads using taints and a targeted toleration.
    • RBAC: use Roles and ClusterRoles only when necessary, and bind them through RoleBindings or ClusterRoleBindings to separate ServiceAccounts. Avoid `cluster-admin` for applications.
    • ServiceAccounts: use a dedicated ServiceAccount for each application. This keeps audit logging clear and lets you restrict permissions per workload.

    Establishing these boundaries early prevents a vulnerable workload from automatically gaining access to other workloads, configuration, or storage.


     

    Harden pods and containers 

     

    A workload that runs as root, has a writable root file system, and receives all Linux capabilities is unnecessarily risky. Make hardening part of your standard manifests.

    • Container image: use a small, maintained container image, pin versions, and retrieve images only from trusted registries or your own registry.
    • Non-root: run containers as non-root by default with fixed `runAsUser` and `runAsGroup` values.
    • Capabilities: drop all capabilities by default and add back only those that are demonstrably required.
    • File system: enable `readOnlyRootFilesystem: true` where possible. Use a separate volume such as `emptyDir` for temporary writable data.
    • Privilege escalation: set `allowPrivilegeEscalation: false` and avoid privileged containers unless a component genuinely requires them.
    • Seccomp and additional policies: use `RuntimeDefault` for seccomp and supplement it with AppArmor of SELinux.
    • ServiceAccount token: set `automountServiceAccountToken: false` if a workload does not need to use the Kubernetes API.
    • Probes: configure readiness-, liveness and startup-probes so that faulty pods do not continue processing traffic or jobs.

     

    Example hardening profile

    apiVersion: v1
    kind: Pod
    metadata:
      name: hardened
    spec:
      automountServiceAccountToken: false
      containers:
        - name: app
          image: busybox:1.36
          command: ["sh", "-c", "sleep 3600"]
          securityContext:
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
            runAsNonRoot: true
            runAsUser: 65532
            runAsGroup: 65532
            capabilities:
              drop:
                - ALL
            seccompProfile:
              type: RuntimeDefault

    Adapt this profile to the application, but make exceptions explicit. When deviating from this baseline, clearly document why it is necessary.


     

    Restrict traffic between pods and publish only through the gateway

     

    By default, traffic in many clusters can flow more broadly than necessary. Explicitly define which workloads may communicate and route public traffic through a single controlled entry point.

    • Gateway or ingress: publish HTTP(S) traffic through a central gateway of ingress, for example using Traefik.
    • TLS: use TLS on your public listeners and automate certificates with Cert-manager.
    • NetworkPolicies: use deny-by-default and open only the ports and namespaces that a workload actually needs.
    • East-west encryption: traffic between pods is not encrypted by default. To enforce TLS or mTLS internally, use a service mesh or CNI solution that supports it.
    • Public services: avoid `NodePort` and separate `LoadBalancer` Services for internal components. Fewer direct entry points mean a smaller attack surface.

     

    Example of a restrictive NetworkPolicy

    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: allow-only-same-namespace
      namespace: example
    spec:
      podSelector:
        matchLabels:
          app: echo
      policyTypes:
        - Ingress
      ingress:
        - from:
            - namespaceSelector:
                matchLabels:
                  kubernetes.io/metadata.name: example
          ports:
            - protocol: TCP
              port: 5678

    With this policy, the selected workload accepts traffic only from its own namespace on port `5678`. This prevents arbitrary other workloads in the cluster from connecting.


     

    Protect Secrets and storage as production data

     

    Sensitive data does not belong in images, Git repositories, or general configuration files. The same applies to storage: an incorrectly shared volume can be as serious a security issue as an open port.

    • Secrets: store passwords, tokens, and keys in Kubernetes Secrets or an external secret manager. Do not use ConfigMaps or environment variables in example files when the values are sensitive.
    • Volume access: mount volumes as read-write only when necessary. Many configuration or certificate volumes can be mounted as read-only.
    • Persistent storage: give each application its own volume where possible. Use shared file storage only when the application supports concurrent access and file locking.
    • Persistent volume claim: create a separate persistent volume claim for each datastore used by a stateful workload, so that permissions and lifecycle remain manageable per workload.
    • Backups and snapshots: do not rely on replication alone. Create backups or snapshots to protect against human error, corrupted data, or ransomware within the workload itself.

    Storage security therefore covers not only encryption, but also separation, lifecycle, access permissions, and recovery options.


     

    Continue scanning, logging, and updating

     

    A cluster is never 'finished'. New CVEs, container versions, and Helm Charts make periodic checks necessary.

    • Image and manifestscans: periodically scan images and manifests with tools such as Trivy, kubeaudit, kube-bench, or kube-hunter, depending on what you need to check.
    • Third-party software: install Helm Charts, operators, and YAML only from sources you trust and maintain. Review changelogs and permissions before applying them.
    • Monitoring: collect metrics and logs with Prometheus and Grafana, and use Lens or similar tools to identify anomalies quickly.
    • Updates: houd base images, dependencies and cluster-add-ons bij. Old versions of images, charts, or controllers remain one of the main causes of avoidable incidents.
    • Review permissions regularly: periodically check which ServiceAccounts, Roles, and bindings are still necessary. Otherwise, old permissions remain in place unnoticed.

    Making scanning, logging, and updates routine reduces the chance that a known vulnerability remains in your cluster for weeks or months.


     

    Clear separation between workloads, strict pod hardening, restricted network access, and deliberate use of storage make your Kubernetes workloads significantly more secure. Combine this with active patch management and monitoring to keep your cluster manageable and defensible in the long term.

    Need help?

    Receive personal support from our supporters

    Contact us