Kubernetes Security
Security best practices for Kubernetes deployments.
Pod Security
Run as Non-Root
spec: securityContext: runAsNonRoot: true runAsUser: 1000 fsGroup: 1000
Read-Only Root Filesystem
spec: containers:
- name: app
securityContext:
readOnlyRootFilesystem: true
volumeMounts:
- name: tmp mountPath: /tmp volumes:
- name: tmp emptyDir: {}
Drop Capabilities
spec: containers:
- name: app securityContext: capabilities: drop: - ALL add: - NET_BIND_SERVICE
Prevent Privilege Escalation
spec: containers:
- name: app securityContext: allowPrivilegeEscalation: false privileged: false
Network Security
Network Policies
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: api-allow spec: podSelector: matchLabels: app: api policyTypes:
- Ingress
- Egress ingress:
- from:
- podSelector: matchLabels: app: frontend ports:
- protocol: TCP port: 8080 egress:
- to:
- podSelector: matchLabels: app: database ports:
- protocol: TCP port: 5432
RBAC
ServiceAccount
apiVersion: v1 kind: ServiceAccount metadata: name: app-sa namespace: default
Role
apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: pod-reader rules:
- apiGroups: [""] resources: ["pods"] verbs: ["get", "list"]
RoleBinding
apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: read-pods subjects:
- kind: ServiceAccount name: app-sa namespace: default roleRef: kind: Role name: pod-reader apiGroup: rbac.authorization.k8s.io
Secrets Management
Encrypt at Rest
Enable encryption for secrets at rest in etcd.
External Secrets
Use external secret management:
apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: app-secrets spec: refreshInterval: 1h secretStoreRef: name: vault-backend kind: SecretStore target: name: app-secrets data:
- secretKey: password remoteRef: key: secret/data/app property: password
Avoid Hardcoding
Bad
env:
- name: DB_PASSWORD value: "hardcoded-password"
Good
env:
- name: DB_PASSWORD valueFrom: secretKeyRef: name: db-secret key: password
Resource Limits
Prevent Resource Exhaustion
spec: containers:
- name: app resources: limits: memory: "256Mi" cpu: "500m" requests: memory: "128Mi" cpu: "250m"
LimitRange
apiVersion: v1 kind: LimitRange metadata: name: mem-limit-range spec: limits:
- max: memory: 512Mi min: memory: 64Mi type: Container
ResourceQuota
apiVersion: v1 kind: ResourceQuota metadata: name: compute-quota spec: hard: requests.cpu: "10" requests.memory: 20Gi limits.cpu: "20" limits.memory: 40Gi
Image Security
Use Specific Tags
Bad
image: nginx:latest
Good
image: nginx:1.21.6
Image Pull Policies
spec: containers:
- name: app image: myapp:1.0.0 imagePullPolicy: IfNotPresent
Private Registries
spec: imagePullSecrets:
- name: registry-credentials containers:
- name: app image: private.registry.com/myapp:1.0.0
Pod Security Standards
Restricted Profile
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
Security Scanning
Scan manifests with kubesec
kubesec scan pod.yaml
Scan images with trivy
trivy image nginx:1.21
Policy validation with OPA
opa eval -d policy.rego -i manifest.yaml