Skip to main content
โšก Calmops

Kubernetes Security: Securing Container Orchestration

Introduction

Kubernetes has become the de facto standard for container orchestration, but with its complexity comes significant security challenges. A misconfigured Kubernetes cluster can expose applications to attacks, data breaches, and compliance violations. In 2026, securing Kubernetes requires a defense-in-depth approach spanning multiple layersโ€”from container images to runtime behavior.

This comprehensive guide explores Kubernetes security in depth, covering authentication, authorization, network policies, pod security, secrets management, and runtime protection.

Kubernetes Security Architecture

Defense in Depth

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                  Kubernetes Security Layers                           โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                                      โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”‚
โ”‚  โ”‚  1. Image Security                                          โ”‚   โ”‚
โ”‚  โ”‚     โ€ข Scan for vulnerabilities                               โ”‚   โ”‚
โ”‚  โ”‚     โ€ข Use minimal base images                               โ”‚   โ”‚
โ”‚  โ”‚     โ€ข Sign and verify images                                โ”‚   โ”‚
โ”‚  โ”‚     โ€ข Store images in secure registries                      โ”‚   โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ”‚
โ”‚                              โ”‚                                       โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”‚
โ”‚  โ”‚  2. Cluster Security                                       โ”‚   โ”‚
โ”‚  โ”‚     โ€ข RBAC for access control                              โ”‚   โ”‚
โ”‚  โ”‚     โ€ข etcd encryption                                      โ”‚   โ”‚
โ”‚  โ”‚     โ€ข API server authentication                            โ”‚   โ”‚
โ”‚  โ”‚     โ€ข Network policies                                     โ”‚   โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ”‚
โ”‚                              โ”‚                                       โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”‚
โ”‚  โ”‚  3. Node Security                                         โ”‚   โ”‚
โ”‚  โ”‚     โ€ข OS hardening                                         โ”‚   โ”‚
โ”‚  โ”‚     โ€ข Kernel parameters                                    โ”‚   โ”‚
โ”‚  โ”‚     โ€ข Container runtime security                            โ”‚   โ”‚
โ”‚  โ”‚     โ€ข Node access control                                   โ”‚   โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ”‚
โ”‚                              โ”‚                                       โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”‚
โ”‚  โ”‚  4. Pod Security                                           โ”‚   โ”‚
โ”‚  โ”‚     โ€ข Pod Security Standards                               โ”‚   โ”‚
โ”‚  โ”‚     โ€ข Security contexts                                    โ”‚   โ”‚
โ”‚  โ”‚     โ€ข Resource limits                                      โ”‚   โ”‚
โ”‚  โ”‚     โ€ข Service account management                           โ”‚   โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ”‚
โ”‚                              โ”‚                                       โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”‚
โ”‚  โ”‚  5. Runtime Security                                       โ”‚   โ”‚
โ”‚  โ”‚     โ€ข Falco for behavioral monitoring                       โ”‚   โ”‚
โ”‚  โ”‚     โ€ข Seccomp profiles                                    โ”‚   โ”‚
โ”‚  โ”‚     โ€ข AppArmor/SELinux                                    โ”‚   โ”‚
โ”‚  โ”‚     โ€ข Admission controllers                                 โ”‚   โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ”‚
โ”‚                                                                      โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Security Context

# pod-security-context.yaml
apiVersion: v1
kind: Pod
metadata:
  name: secure-pod
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 10000
    runAsGroup: 10000
    fsGroup: 10000
    seccompProfile:
      type: RuntimeDefault
    sysctls:
      - name: net.ipv4.ping_group_range
        value: "0 0"
  
  containers:
    - name: app
      image: secure-app:latest
      securityContext:
        allowPrivilegeEscalation: false
        readOnlyRootFilesystem: true
        capabilities:
          drop:
            - ALL
        privileged: false
      
      resources:
        limits:
          cpu: "500m"
          memory: "256Mi"
        requests:
          cpu: "100m"
          memory: "64Mi"
      
      volumeMounts:
        - name: tmp
          mountPath: /tmp

Role-Based Access Control (RBAC)

ClusterRoles and Roles

# cluster-role-admin.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: admin-role
rules:
  - apiGroups: ["*"]
    resources: ["*"]
    verbs: ["*"]
  - nonResourceURLs: ["*"]
    verbs: ["*"]

---
# role-developer.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: development
  name: developer-role
rules:
  - apiGroups: [""]
    resources: ["pods", "services", "configmaps", "secrets"]
    verbs: ["get", "list", "watch", "create", "update", "patch"]
  - apiGroups: [""]
    resources: ["pods/log"]
    verbs: ["get", "list"]
  - apiGroups: ["apps"]
    resources: ["deployments", "replicasets", "statefulsets"]
    verbs: ["get", "list", "watch", "create", "update", "patch"]
  - apiGroups: ["batch"]
    resources: ["jobs", "cronjobs"]
    verbs: ["get", "list", "watch", "create", "update", "patch"]

---
# role-binding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: developer-role-binding
  namespace: development
subjects:
  - kind: User
    name: john.doe
    apiGroup: rbac.authorization.k8s.io
  - kind: Group
    name: developers
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: developer-role
  apiGroup: rbac.authorization.k8s.io

Service Account Best Practices

# service-account.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: app-service-account
  namespace: production
  annotations:
    description: "Service account for payment service"

---
# role-service-account.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: production
  name: service-account-role
rules:
  - apiGroups: [""]
    resources: ["secrets"]
    resourceNames: ["payment-db-credentials"]
    verbs: ["get"]
  - apiGroups: [""]
    resources: ["configmaps"]
    resourceNames: ["payment-config"]
    verbs: ["get", "watch"]

---
# role-binding-service-account.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: service-account-binding
  namespace: production
subjects:
  - kind: ServiceAccount
    name: app-service-account
    namespace: production
roleRef:
  kind: Role
  name: service-account-role
  apiGroup: rbac.authorization.k8s.io

Pod Security Standards

PSS Policies

class PodSecurityStandards:
    @staticmethod
    def restricted():
        return {
            "policy": {
                "name": "restricted",
                "description": "Most restrictive policy",
                "enforce": "Restricted",
                "enforce_version": "latest",
                "warn": "Restricted",
                "warn_version": "latest",
                "audit": "Restricted",
                "audit_version": "latest"
            },
            "restrictions": [
                "Cannot run as root",
                "Cannot use privileged containers",
                "Must drop all capabilities",
                "Cannot mount hostPath volumes",
                "Must use seccomp profile or RuntimeDefault"
            ]
        }
    
    @staticmethod
    def baseline():
        return {
            "policy": {
                "name": "baseline",
                "description": "Baseline policy with minimal restrictions",
                "enforce": "Baseline",
                "enforce_version": "latest"
            },
            "allowed": [
                "Running as non-root user",
                "Specific capabilities allowed",
                "HostPath with restrictions"
            ],
            "forbidden": [
                "Privileged containers",
                "Host network access",
                "Host PID namespace"
            ]
        }

Applying PSS

# pss-namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: production
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/enforce-version: latest
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/audit-version: latest
    pod-security.kubernetes.io/warn: restricted
    pod-security.kubernetes.io/warn-version: latest

---
# pss-exception.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: privileged
  labels:
    pod-security.kubernetes.io/enforce: baseline
    pod-security.kubernetes.io/enforce-version: latest

Network Policies

Basic Network Policies

# default-deny-all.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: production
spec:
  podSelector: {}
  policyTypes:
    - Ingress
    - Egress

---
# allow-dns-egress.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-dns-egress
  namespace: production
spec:
  podSelector: {}
  policyTypes:
    - 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

---
# allow-app-communication.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-api-to-db
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: database
  policyTypes:
    - Ingress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: api
      ports:
        - protocol: TCP
          port: 5432

Advanced Network Policies

# complex-network-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: complex-app-policy
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: payment-service
  policyTypes:
    - Ingress
    - Egress
  
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: api-gateway
        - podSelector:
            matchLabels:
              app: admin-panel
      ports:
        - protocol: TCP
          port: 8080
    - from:
        - namespaceSelector:
            matchLabels:
              name: monitoring
          podSelector:
            matchLabels:
              app: prometheus
      ports:
        - protocol: TCP
          port: 9090
  
  egress:
    - to:
        - podSelector:
            matchLabels:
              app: postgres
      ports:
        - protocol: TCP
          port: 5432
    - to:
        - podSelector:
            matchLabels:
              app: redis
      ports:
        - protocol: TCP
          port: 6379
    - to:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: kube-system
          podSelector:
            matchLabels:
              k8s-app: kube-dns
      ports:
        - protocol: UDP
          port: 53

Secrets Management

Kubernetes Secrets

# secret-generic.yaml
apiVersion: v1
kind: Secret
metadata:
  name: app-secrets
  namespace: production
type: Opaque
stringData:
  database-url: postgres://user:password@db:5432/mydb
  api-key: sk_live_xxxxxxxxxxxxx
  jwt-secret: verylongsecretkey
data:
  # base64 encoded values
  username: YWRtaW4=
  password: cGFzc3dvcmQ=

---
# secret-tls.yaml
apiVersion: v1
kind: Secret
metadata:
  name: tls-secret
  namespace: production
type: kubernetes.io/tls
data:
  # base64 encoded
  tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0t...
  tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0t...

External Secrets Operator

# external-secret.yaml
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: aws-secrets-manager
  namespace: production
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: aws-secrets-manager
    kind: SecretStore
  target:
    name: app-secrets-from-aws
    creationPolicy: Owner
  data:
    - secretKey: database-password
      remoteRef:
        key: prod/database
        property: password
    - secretKey: api-key
      remoteRef:
        key: prod/api-keys
        property: payment-api

---
# secret-store.yaml
apiVersion: external-secrets.io/v1beta1
kind: ClusterSecretStore
metadata:
  name: aws-secrets-manager
spec:
  provider:
    aws:
      service: SecretsManager
      region: us-east-1
      auth:
        jwt:
          serviceAccountRef:
            name: external-secrets-sa
            namespace: external-secrets

Admission Controllers

Validating Webhooks

# validating-webhook.yaml
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
  name: pod-security-validation
webhooks:
  - name: pods.security.example.com
    clientConfig:
      service:
        name: security-webhook
        namespace: kube-system
        path: "/validate-pod"
      caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0t...
    rules:
      - operations: ["CREATE", "UPDATE"]
        apiGroups: [""]
        apiVersions: ["v1"]
        resources: ["pods"]
    admissionReviewVersions: ["v1", "v1beta1"]
    sideEffects: None
    failurePolicy: Fail
    timeoutSeconds: 10

OPA Gatekeeper

# gatekeeper-constraint-template.yaml
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: k8srequiredlabels
spec:
  crd:
    spec:
      names:
        kind: K8sRequiredLabels
      validation:
        openAPIV3Schema:
          type: object
          properties:
            labels:
              type: array
              items:
                type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8srequiredlabels
        
        violation[{"msg": msg, "details": required_labels}] {
          provided := input.review.object.metadata.labels
          required := input.parameters.labels
          missing := required - provided
          count(missing) > 0
          msg := sprintf("Missing required labels: %v", [missing])
        }

---
# gatekeeper-constraint.yaml
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
  name: require-app-label
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod", "Deployment", "StatefulSet"]
  parameters:
    labels:
      - app
      - environment

Runtime Security

Falco Configuration

# falco-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: falco-config
  namespace: falco
data:
  falco.yaml: |
    json_output: true
    program_priority: "INFO"
    log_level: info
    
    rules_file:
      - /etc/falco/falco_rules.yaml
      - /etc/falco/falco_rules.local.yaml
      - /etc/falco/k8s_audit_rules.yaml
    
    plugins:
      - name: k8saudit
        library_path: libk8saudit.so
        init_config:
         .
          .
    
    default_rules_for_emitter: false
    
    syscall_event_drops:
      threshold: .1
      actions:
        - log
        - alert
      priority: warning

  # Custom rules
  falco_rules.local.yaml: |
    - rule: Detect shell in container
      desc: A shell was spawned inside a container
      condition: >
        evt.type = execve and
        container.id != host and
        (proc.name in (sh, bash, zsh, dash) or
         proc.name = "sh" or
         proc.aname in (sh, bash, zsh, dash))
      output: "Shell detected in container (user=%user.name container_id=%container.id shell=%proc.name)"
      priority: WARNING
      tags: [container, shell]

    - rule: Detect privilege escalation
      desc: Privilege escalation detected
      condition: >
        evt.type = setuid or evt.type = setgid or
        evt.type = setxid or evt.type = setresuid or
        evt.type = setfsuid or evt.type = setreuid
      output: "Privilege escalation detected (user=%user.name uid=%user.uid)"
      priority: CRITICAL
      tags: [container, privilege]

Seccomp Profiles

# seccomp-profile.yaml
apiVersion: v1
kind: Pod
metadata:
  name: workload-with-seccomp
spec:
  securityContext:
    seccompProfile:
      type: Localhost
      localhostProfile: profiles/custom-seccomp.json

---
# custom-seccomp.json
{
  "defaultAction": "SCMP_ACT_LOG",
  "syscalls": [
    {
      "names": [
        "read",
        "write",
        "close",
        "exit_group"
      ],
      "action": "SCMP_ACT_ALLOW"
    },
    {
      "names": [
        "connect",
        "accept",
        "listen",
        "sendto",
        "recvfrom"
      ],
      "action": "SCMP_ACT_ALLOW"
    }
  ]
}

Image Security

Image Scanning Pipeline

class ImageSecurityScanner:
    def __init__(self):
        self.scanner = "trivy"
    
    def scan_image(self, image: str) -> dict:
        return {
            "image": image,
            "vulnerabilities": {
                "critical": 0,
                "high": 2,
                "medium": 5,
                "low": 10
            },
            "scanned_at": "2026-03-12T10:00:00Z",
            "scan_result": "FAILED"
        }
    
    def enforce_scan_policy(self, image: str) -> bool:
        result = self.scan_image(image)
        
        critical_threshold = 0
        high_threshold = 5
        
        if result["vulnerabilities"]["critical"] > critical_threshold:
            return False
        
        if result["vulnerabilities"]["high"] > high_threshold:
            return False
        
        return True

Image Policy Enforcement

# image-policy-webhook.yaml
apiVersion: imagepolicy.k8s.io/v1alpha1
kind: ImagePolicy
metadata:
  name: image-policy
spec:
  repositories:
    - name: "registry.example.com/*"
      policy:
        requirement:
          oneOf:
            - namespaceLabel: trusted
        template:
          metadata:
            annotations:
              imagetag: ".*"
      injectAnnotations:
        - name: image.approved

---
# kubewarden-policy.yaml
apiVersion: policies.kubewarden.io/v1
kind: ClusterAdmissionPolicy
metadata:
  name: require-readonly-rootfs
spec:
  module: registry://ghcr.io/kubewarden/policies/readonly-rootfs-psp:v0.1.5
  settings:
    runAsNonRoot: true
  rules:
    - apiGroups: [""]
      apiVersions: ["v1"]
      resources: ["pods"]
      operations: ["CREATE", "UPDATE"]

Best Practices

Security Checklist

KUBERNETES_SECURITY_CHECKLIST = {
    "cluster_setup": [
        "Enable RBAC and restrict permissions",
        "Enable etcd encryption at rest",
        "Use dedicated service accounts",
        "Configure API server authentication",
        "Enable audit logging",
        "Secure etcd with TLS and authentication",
        "Use network policies to isolate namespaces"
    ],
    
    "container_security": [
        "Use minimal base images",
        "Scan images for vulnerabilities",
        "Run containers as non-root user",
        "Use read-only root filesystem",
        "Drop all capabilities",
        "Enable seccomp profiles",
        "Set appropriate resource limits"
    ],
    
    "runtime_security": [
        "Enable runtime protection (Falco)",
        "Implement admission controllers",
        "Use Pod Security Standards",
        "Enable image signing verification",
        "Implement secrets encryption",
        "Monitor for suspicious activity"
    ],
    
    "network_security": [
        "Implement NetworkPolicies",
        "Use mTLS between services",
        "Restrict egress traffic",
        "Enable DNS policies",
        "Use service mesh for traffic encryption"
    ],
    
    "monitoring": [
        "Enable audit logging",
        "Set up Falco alerts",
        "Monitor API server requests",
        "Track pod security events",
        "Implement alerting for anomalies"
    ]
}

Hardening Guide

HARDENING_GUIDE = {
    "api_server": [
        "--anonymous-auth=false",
        "--authorization-mode=Node,RBAC",
        "--enable-admission-plugins=NodeRestriction",
        "--encryption-provider-config=encryption-config",
        "--audit-log-path=/var/log/kubernetes/audit.log",
        "--audit-log-maxsize=100",
        "--audit-log-maxbackup=10",
        "--request-timeout=60s"
    ],
    
    "kubelet": [
        "--anonymous-auth=false",
        "--authorization-mode=Webhook",
        "--client-ca-file=/etc/kubernetes/pki/ca.crt",
        "--read-only-port=0",
        "--protect-kernel-defaults=true",
        "--make-iptables-util-chains=true"
    ],
    
    "containerd": [
        "Enable selinux",
        "Disable live restore",
        "Use user namespace remapping",
        "Configure container defaults"
    ]
}

Resources

Conclusion

Kubernetes security requires a comprehensive, defense-in-depth approach spanning the entire container lifecycle. From securing container images to implementing runtime protection, every layer must be carefully configured and continuously monitored.

This guide covered authentication and authorization with RBAC, Pod Security Standards, network policies, secrets management, admission controllers, runtime security with Falco and seccomp, and image security best practices. By implementing these security measures, you can significantly reduce the attack surface of your Kubernetes clusters and protect your applications from common threats.

Comments