Kubernetes Security Hardening: Pod Security, Network Policies, and RBAC
A comprehensive guide to securing Kubernetes clusters with Pod Security Standards, network segmentation, RBAC best practices, and runtime security monitoring.
Executive Summary
Kubernetes default configurations prioritize flexibility over security. This guide provides actionable hardening steps for production clusters, from pod security standards to network isolation and secrets management.
1. Pod Security Standards
Kubernetes Pod Security Standards (PSS) replaced Pod Security Policies in v1.25:
Three Security Levels:
- Privileged: Unrestricted (default). Allows privilege escalation, host namespace access, privileged containers.
- Baseline: Minimally restrictive. Prevents privilege escalation, host access, and dangerous volume types.
- Restricted: Heavily restricted best practices. Enforces non-root users, read-only root filesystems, and drops all capabilities.
Example: Namespace-Level Pod Security
# Apply Pod Security Standards at namespace level
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted
---
# Secure Pod Configuration
apiVersion: v1
kind: Pod
metadata:
name: secure-app
namespace: production
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 1000
seccompProfile:
type: RuntimeDefault
containers:
- name: app
image: myapp:v1.2.3
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
volumeMounts:
- name: tmp
mountPath: /tmp
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 250m
memory: 256Mi
volumes:
- name: tmp
emptyDir: {}2. Network Policies for Microsegmentation
By default, all pods can communicate with each other. Network policies provide zero-trust segmentation:
# Default deny all ingress traffic
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
---
# Allow frontend to backend on port 8080
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-backend
namespace: production
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
---
# Allow backend to database
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-backend-to-db
namespace: production
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Egress
egress:
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 5432
# Allow DNS
- to:
- namespaceSelector:
matchLabels:
name: kube-system
ports:
- protocol: UDP
port: 533. RBAC (Role-Based Access Control)
Implement least privilege access using RBAC:
# Read-only developer role apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: developer-readonly namespace: production rules: - apiGroups: ["", "apps", "batch"] resources: ["pods", "deployments", "jobs", "services"] verbs: ["get", "list", "watch"] - apiGroups: [""] resources: ["pods/log"] verbs: ["get"] --- # Deploy role (CI/CD) apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: deployer namespace: production rules: - apiGroups: ["apps"] resources: ["deployments", "replicasets"] verbs: ["get", "list", "create", "update", "patch"] - apiGroups: [""] resources: ["services", "configmaps"] verbs: ["get", "list", "create", "update"] - apiGroups: [""] resources: ["secrets"] verbs: ["get", "list"] # Read secrets, not create --- # Bind role to service account apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: deployer-binding namespace: production subjects: - kind: ServiceAccount name: github-actions namespace: production roleRef: kind: Role name: deployer apiGroup: rbac.authorization.k8s.io
4. Secrets Management
Kubernetes Secrets Best Practices:
- ✓ Enable Encryption at Rest: Configure encryption provider for etcd
- ✓ Use External Secrets Operator: Sync from Vault/AWS Secrets Manager
- ✓ Limit Secret Access: RBAC to restrict which ServiceAccounts can read secrets
- ✓ Mount as Volumes: Not environment variables (visible in pod specs)
- ✓ Rotate Regularly: Automate secret rotation every 90 days
# External Secrets Operator example
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: app-secrets
namespace: production
spec:
refreshInterval: 1h
secretStoreRef:
name: vault-backend
kind: SecretStore
target:
name: app-secrets
creationPolicy: Owner
data:
- secretKey: database-password
remoteRef:
key: secret/production/database
property: password
- secretKey: api-key
remoteRef:
key: secret/production/api
property: key5. Runtime Security with Falco
Detect anomalous behavior in running containers:
# Custom Falco rules for Kubernetes
- rule: Suspicious Container Network Activity
desc: Detect outbound connections to suspicious IPs
condition: >
container and
fd.type=ipv4 and
evt.type=connect and
not fd.sip in (allowed_ips)
output: >
Suspicious network connection
(container=%container.name pod=%k8s.pod.name
ip=%fd.rip port=%fd.rport)
priority: WARNING
- rule: Unauthorized Process Execution
desc: Detect unexpected binaries running in container
condition: >
container and
proc.name not in (allowed_processes) and
k8s.ns.name=production
output: >
Unexpected process in production
(container=%container.name process=%proc.name
pod=%k8s.pod.name cmdline=%proc.cmdline)
priority: ERROR
- rule: Write to Non-Temporary Directory
desc: Detect writes outside /tmp (read-only root FS violation)
condition: >
container and
evt.type=open and
evt.dir=> and
fd.name startswith / and
not fd.name startswith /tmp
output: >
Write to read-only filesystem
(file=%fd.name container=%container.name)
priority: WARNING6. Image Security and Supply Chain
Container Image Security:
- ✓ Use private registries with authentication
- ✓ Scan images before deployment (Trivy, Grype, Clair)
- ✓ Sign images with Sigstore/Cosign
- ✓ Enforce image signing verification via admission controller
- ✓ Use specific image tags, never :latest
- ✓ Minimize image size (distroless, Alpine-based)
# Kyverno policy: Require signed images
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: verify-image-signatures
spec:
validationFailureAction: Enforce
rules:
- name: verify-signature
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "myregistry.io/*"
attestors:
- entries:
- keys:
publicKeys: |-
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...
-----END PUBLIC KEY-----7. Audit Logging and Monitoring
Enable Comprehensive Audit Logs:
- • All API server requests (who, what, when)
- • RBAC authorization decisions
- • Secrets access attempts
- • Pod creations and deletions
- • ConfigMap/Secret modifications
Kubernetes Security Checklist
- Enable Pod Security Standards (Restricted level for production)
- Implement Network Policies (default-deny + explicit allow)
- Configure RBAC with least privilege per namespace
- Encrypt secrets at rest and use external secrets management
- Deploy runtime security monitoring (Falco, Tetragon)
- Scan and sign all container images before deployment
Kubernetes Security at Scale
Securus Mind provides unified Kubernetes security posture management across clusters with policy enforcement, compliance monitoring, and runtime threat detection.
Schedule a Demo