Kubernetes Security: The CIO's Checklist
Kubernetes security conversations often swing between two extremes: either "we'll secure it later" (spoiler: you won't), or "we need to implement every possible security control" (you'll never ship anything).
Here's what you actually need: a prioritized security baseline that protects against the majority of real attacks without becoming operational theater.
This checklist reflects what Hidora implements for production workloads at Swiss and European enterprises.
Layer 1: Cluster-Level Security (Foundation)
1. Network Policy (CRITICAL)
By default, all pods can talk to all other pods. This is nearly indefensible.
What to do:
- Enable Network Policy in your Kubernetes cluster
- Default-deny all ingress traffic
- Explicitly allow traffic only where needed
Example:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
spec:
podSelector: {}
policyTypes:
- Ingress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-api
spec:
podSelector:
matchLabels:
tier: api
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
tier: frontend
ports:
- protocol: TCP
port: 8080
Reality check: This prevents lateral movement when one pod is compromised. It's not perfect, but it's foundational.
2. RBAC (Role-Based Access Control)
Kubernetes RBAC controls who can do what on your cluster.
Minimum setup:
- No user or service account has cluster-admin by default
- Service accounts are created per application, not reused across teams
- Read-only access for developers, change access only for automated deployments
- Auditing enabled for all API calls
Checklist:
- Default cluster-admin role not used by regular operations
- All service accounts have minimal required permissions
- Kubernetes RBAC audit logs are shipped to a SIEM or log aggregator
- Quarterly review of who has what permissions
Why this matters: A compromised pod with broad RBAC can take down your entire cluster or steal secrets from other teams.
3. Pod Security Standards (Previously Pod Security Policy)
Enforce baseline security settings for all pods.
Restrictive (recommended for most teams):
- No root containers
- No privileged containers
- Read-only root filesystem where possible
- No host network access
- Security scanning before deployment
Implementation:
apiVersion: policy/v1alpha1
kind: PodSecurityPolicy
metadata:
name: restricted
spec:
privileged: false
allowPrivilegeEscalation: false
requiredDropCapabilities:
- ALL
requiredCapabilities:
- NET_BIND_SERVICE
fsGroup:
rule: 'MustRunAs'
ranges:
- min: 1000
max: 65535
runAsUser:
rule: 'MustRunAsNonRoot'
readOnlyRootFilesystem: true
Reality check: This prevents dozens of container escape techniques. Most applications work fine under these constraints.
4. Secret Management
Kubernetes secrets are base64-encoded by default. That's not encryption; that's obscuration.
What to do:
- Enable Kubernetes secret encryption at rest (EncryptionConfiguration)
- Use an External Secrets Operator to fetch secrets from a managed vault
- Never commit secrets to Git
- Rotate secrets regularly
Recommended approach for Swiss companies: Deploy HashiCorp Vault (or equivalent) with secret rotation policies. External Secrets Operator fetches secrets at pod startup. If a secret is compromised, rotate it in Vault and Kubernetes pods refresh automatically within minutes.
Checklist:
- Secrets encrypted at rest in etcd
- Secret access is audited
- Secrets are rotated every 90 days
- Emergency secret rotation procedure is documented and tested
Layer 2: Container and Image Security
5. Container Image Scanning
A vulnerability in a base image is a vulnerability in all your containers.
Minimum setup:
- Scan all images before they reach your registry
- Fail the build if critical vulnerabilities are found
- Re-scan images periodically (vulnerabilities are discovered after images are built)
Tools:
- Trivy (free, open-source, fast)
- Snyk (commercial, excellent for integrating with CI/CD)
- Aqua Security (comprehensive)
Pipeline integration:
Code → Build image → Scan image → Fail if critical vulnerabilities → Push to registry
Realistic policy:
- Block critical and high-severity vulnerabilities
- Allow medium and low severity (you'll fix them, but don't delay deployment)
- Document exceptions
6. Registry Access Control
Your container registry is a critical asset. It shouldn't be accessible to the entire internet.
Checklist:
- Only authenticated users can push images
- Audit logging on all push/pull operations
- Images are signed (cosign or Notary)
- Only signed images are deployed (admission controller enforces this)
- Registry backups are encrypted and tested regularly
7. Non-Root Containers
Running containers as root is unnecessary and risky.
What to do:
- All Dockerfiles specify a non-root USER
- Kubernetes securityContext enforces runAsNonRoot
- If an application absolutely requires root, investigate why (often unnecessary)
Example Dockerfile:
FROM alpine:3.18
RUN useradd -m -u 1000 appuser
COPY --chown=appuser:appuser ./app /app
USER appuser
ENTRYPOINT ["/app/myapp"]
Layer 3: Workload Security
8. Resource Limits
Pods without resource limits can starve other workloads or crash nodes.
What to do:
apiVersion: v1
kind: Pod
metadata:
name: myapp
spec:
containers:
- name: app
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
Requests = guaranteed capacity, Limits = maximum allowed.
Reality check: Set limits slightly above your average usage, not at peak. Too-tight limits cause pod evictions.
9. Health Checks (Liveness and Readiness Probes)
Kubernetes should know when your application is healthy or degraded.
Liveness probe: Is the application still running? Kubernetes restarts it if not. Readiness probe: Is the application ready to serve traffic? Removes it from load balancers if not.
Example:
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 10
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
10. Admission Controllers and Policy Enforcement
Automated gatekeepers that prevent misconfigurations before they reach production.
Essential policies:
- Require image pull policy to be "Always"
- Block containers running as root
- Require resource limits
- Prevent privileged containers
- Block unknown registries
Tools:
- Kyverno (Kubernetes-native, easier to learn)
- OPA/Gatekeeper (more powerful, steeper curve)
Example Kyverno policy:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-resource-limits
spec:
validationFailureAction: audit
rules:
- name: check-resources
match:
resources:
kinds:
- Pod
validate:
message: "CPU and memory limits required"
pattern:
spec:
containers:
- resources:
limits:
memory: "?*"
cpu: "?*"
Layer 4: Supply Chain Security
11. SBOM (Software Bill of Materials)
Know what's inside your containers.
- Generate SBOMs for all container images
- Track SBOMs in your artifact repository
- Use them for impact analysis when vulnerabilities are discovered
Tool: Syft (free, integrates easily)
12. Signed Commits and Images
Ensure code and container provenance.
- Commits must be signed by developers (GPG or SSH keys)
- Container images must be signed (cosign)
- Admission controllers verify signatures before deployment
Layer 5: Observability for Security
13. Audit Logging
Kubernetes API audit logs are your security event stream.
What to log:
- All API calls (enabled by default, but often not shipped anywhere)
- Authentication failures
- Authorization failures
- Secret access
- Configuration changes
Setup:
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: RequestResponse
verbs: ["create", "update", "patch", "delete"]
- level: Metadata
verbs: ["get", "list", "watch"]
Ship logs to a central SIEM (Elasticsearch, Splunk, Datadog).
14. Runtime Security Monitoring
Detect suspicious behavior at runtime.
What to monitor:
- Unexpected process execution (e.g., a web server spawning a shell)
- Unexpected network connections
- Unauthorized file modifications
- Privilege escalation attempts
Tools:
- Falco (free, open-source)
- Sysdig (commercial, more polished)
The 90-Day Implementation Plan
Month 1: Foundation
- Enable Network Policy (default-deny)
- Enable RBAC auditing
- Implement Pod Security Standards
- Enable secret encryption at rest
Month 2: Image and Container Security
- Set up container image scanning in CI/CD
- Enforce non-root containers
- Implement admission controllers (Kyverno basic policies)
- Review registry access controls
Month 3: Hardening
- Deploy Falco for runtime security
- Implement signed images and cosign verification
- Set up SBOMs for all images
- Run security audit and penetration test
Common Mistakes to Avoid
Mistake 1: Implementing everything at once → You'll miss critical baseline and burn out the team. Fix: Prioritize by risk. Network Policy and RBAC first.
Mistake 2: Security controls without automation → Manual security doesn't scale. Fix: Automate policy enforcement. Admission controllers, not spreadsheets.
Mistake 3: Security theater over substance → "We have 47 security policies" means nothing if Network Policy is disabled. Fix: Focus on preventative controls, not documentation.
Mistake 4: Ignoring supply chain security → Vulnerabilities are shipped in base images, not just code. Fix: Image scanning is non-negotiable.
The Reality
Kubernetes security is about layers. No single control is sufficient. But this checklist (Network Policy, RBAC, Pod Security Standards, image scanning, admission controllers, and audit logging) covers the 80% of risks that cause real damage.
The other 20% (zero-day exploits, advanced persistent threats) require threat hunting and incident response capabilities. That's where managed security services and expert consultation matter.
Related reading:
- DevSecOps: Shift Left, Not Just Shift Hard
- Swiss Data Sovereignty: Why It Matters for Your Kubernetes Deployment
Found this helpful? See how Hidora can help: Professional Services · Managed Services · SLA Expert



