Back to Blog
Cloud Security22 min read2024-11-22

Kubernetes Security Best Practices: Securing Container Orchestration

A comprehensive guide to securing Kubernetes clusters. Learn essential security controls, configurations, and best practices for production environments.

A

Asfaleia Team

Chief Security Researcher

Kubernetes Security Best Practices: Securing Container Orchestration
Sections

Introduction to Kubernetes Security

Kubernetes has become the de facto standard for container orchestration, running critical workloads across industries. However, its complexity and power also introduce significant security challenges. Misconfigured Kubernetes clusters are a leading cause of cloud security incidents.

Kubernetes Security Challenges:
Large attack surface
Default configurations often insecure
Complex RBAC management
Secrets management complexity
Container supply chain risks
Network policy complexity
Security Statistics:
94% of organizations experienced a K8s security incident
67% delayed deployments due to security concerns
78% run containers in production
55% have experienced a misconfiguration incident

The 4C's of Cloud Native Security

Kubernetes security follows a layered approach:

1. Cloud Security

Infrastructure provider security
Network security
IAM configuration
Encryption at rest

2. Cluster Security

API server hardening
Etcd security
Node security
Control plane protection

3. Container Security

Image security
Runtime protection
Resource limits
Privilege restrictions

4. Code Security

Application vulnerabilities
Dependency scanning
Secure coding practices
Secret management in code

Cluster Hardening

API Server Security

The API server is the control plane gateway—secure it rigorously.

Key Configurations:
Authentication:
# Disable anonymous authentication
--anonymous-auth=false
# Enable OIDC authentication
--oidc-issuer-url=https://your-idp.com
--oidc-client-id=kubernetes
--oidc-username-claim=email
--oidc-groups-claim=groups
Authorization:
# Use RBAC
--authorization-mode=RBAC,Node
# Enable admission controllers
--enable-admission-plugins=NodeRestriction,PodSecurityPolicy
Audit Logging:
# Enable audit logging
--audit-log-path=/var/log/kubernetes/audit.log
--audit-log-maxage=30
--audit-log-maxbackup=10
--audit-policy-file=/etc/kubernetes/audit-policy.yaml

Etcd Security

Etcd stores all cluster state—it must be heavily protected.

Security Measures:
Enable TLS for all communications
Restrict access to control plane only
Encrypt data at rest
Regular backups with encryption
Network isolation
Configuration:
# TLS configuration
--cert-file=/path/to/server.crt
--key-file=/path/to/server.key
--trusted-ca-file=/path/to/ca.crt
--client-cert-auth=true
--peer-cert-file=/path/to/peer.crt
--peer-key-file=/path/to/peer.key
--peer-client-cert-auth=true

Kubelet Security

Hardening Configuration:
# kubelet configuration
authentication:
  anonymous:
    enabled: false
  webhook:
    enabled: true
authorization:
  mode: Webhook
readOnlyPort: 0  # Disable read-only port
protectKernelDefaults: true

RBAC Best Practices

Principle of Least Privilege

Namespace-Scoped Roles:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: production
  name: pod-reader
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
  namespace: production
subjects:
- kind: User
  name: [email protected]
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io
Cluster-Wide Restrictions:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: namespace-admin
rules:
- apiGroups: [""]
  resources: ["namespaces"]
  verbs: ["get", "list"]
  # NO create, delete, or update

RBAC Audit

Regularly audit RBAC:

Review ClusterRoleBindings
Check for overly permissive roles
Identify unused service accounts
Remove default service account tokens
Audit Command:
# List all cluster-admin bindings
kubectl get clusterrolebindings -o json | jq '.items[] | select(.roleRef.name=="cluster-admin") | .subjects'
# Find pods with service account tokens
kubectl get pods --all-namespaces -o json | jq '.items[] | select(.spec.automountServiceAccountToken != false) | .metadata.name'

Pod Security

Pod Security Standards

Kubernetes provides three security profiles:

Privileged:
Unrestricted policy
For system-level workloads only
Baseline:
Minimally restrictive
Prevents known privilege escalations
Restricted:
Heavily restricted
Best practice security
Enforcement:
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 Context

Secure Pod Definition:
apiVersion: v1
kind: Pod
metadata:
  name: secure-pod
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    runAsGroup: 3000
    fsGroup: 2000
    seccompProfile:
      type: RuntimeDefault
  containers:
  - name: app
    image: myapp:1.0
    securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      capabilities:
        drop:
          - ALL
    resources:
      limits:
        cpu: "500m"
        memory: "128Mi"
      requests:
        cpu: "100m"
        memory: "64Mi"

Key Security Settings

Always Set:
`runAsNonRoot: true`
`allowPrivilegeEscalation: false`
`readOnlyRootFilesystem: true`
`capabilities.drop: ["ALL"]`
Never Use (unless required):
`privileged: true`
`hostNetwork: true`
`hostPID: true`
`hostIPC: true`

Network Policies

Default Deny

Start with default deny and explicitly allow required traffic.

Default Deny All:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: production
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress
Allow Specific Traffic:
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

Network Segmentation

Best Practices:
Isolate namespaces
Segment by application tier
Restrict egress traffic
Use service mesh for mTLS

Secrets Management

Kubernetes Secrets Limitations

Native K8s secrets are only base64 encoded—not encrypted by default.

Improvement Options:
1. Encryption at Rest:
# EncryptionConfiguration
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources:
      - secrets
    providers:
      - aescbc:
          keys:
            - name: key1
              secret: <base64-encoded-key>
      - identity: {}
2. External Secrets Management:
HashiCorp Vault
AWS Secrets Manager
Azure Key Vault
Google Secret Manager
Vault Integration Example:
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultStaticSecret
metadata:
  name: app-secret
spec:
  vaultAuthRef: vault-auth
  mount: secret
  path: app/config
  destination:
    name: app-secret
    create: true

Secrets Best Practices

Never commit secrets to Git
Use external secrets operators
Rotate secrets regularly
Limit secret access with RBAC
Audit secret access
Use short-lived credentials where possible

Image Security

Container Image Best Practices

1. Use Minimal Base Images:
# Good: Distroless images
FROM gcr.io/distroless/static:nonroot
# Good: Alpine for minimal footprint
FROM alpine:3.18
# Avoid: Full OS images
# FROM ubuntu:22.04
2. Scan Images for Vulnerabilities:
# Trivy scanning
trivy image myapp:1.0
# Grype scanning
grype myapp:1.0
3. Sign and Verify Images:
# Sign with cosign
cosign sign --key cosign.key myregistry/myapp:1.0
# Verify signature
cosign verify --key cosign.pub myregistry/myapp:1.0

Admission Control

Image Policy Enforcement:
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
  name: image-policy
webhooks:
- name: image-policy.example.com
  rules:
  - apiGroups: [""]
    apiVersions: ["v1"]
    operations: ["CREATE", "UPDATE"]
    resources: ["pods"]
Policy Requirements:
Images from approved registries only
Signed images only
No images with critical vulnerabilities
Specific tag requirements (no :latest)

Runtime Security

Container Runtime Protection

Key Capabilities:
Process monitoring
File integrity monitoring
Network activity monitoring
Syscall filtering
Tools:
Falco: Runtime threat detection
Sysdig: Container monitoring
Aqua Security: Runtime protection
Prisma Cloud: Container security
Falco Example Rule:
- rule: Terminal shell in container
  desc: A shell was spawned in a container
  condition: >
    spawned_process and container and
    shell_procs and proc.tty != 0
  output: >
    Shell spawned in container
    (user=%user.name container=%container.name
    shell=%proc.name)
  priority: WARNING
  tags: [container, shell]

Syscall Filtering with Seccomp

Restricted Profile:
apiVersion: v1
kind: Pod
metadata:
  name: secure-pod
spec:
  securityContext:
    seccompProfile:
      type: RuntimeDefault  # Or custom profile
  containers:
  - name: app
    image: myapp:1.0

Monitoring and Auditing

Essential Logs

API Server Audit Logs:
All authenticated requests
Response codes
User information
Resources accessed
Container Logs:
Application logs
Error tracking
Security events
System Logs:
Kubelet logs
Container runtime logs
Node-level events

Security Monitoring

Key Metrics:
Failed authentication attempts
Privilege escalation attempts
Unusual pod behavior
Network policy violations
Resource limit violations
Alerting Rules:
Privileged container creation
Host path mounts
New ClusterRoleBindings
Secrets access from unusual pods
Exec into pods

Security Checklist

Cluster Level

API server authentication enabled
RBAC authorization configured
Etcd encrypted and secured
Audit logging enabled
Network policies enforced
Pod Security Standards applied

Workload Level

Non-root containers
Read-only root filesystem
Dropped capabilities
Resource limits set
Security contexts defined
Service account tokens restricted

Image Level

Vulnerability scanning in CI/CD
Image signing and verification
Approved registry enforcement
Minimal base images
No secrets in images

Operational

Regular updates and patches
Backup and recovery tested
Security monitoring active
Incident response plan
Regular security assessments

Conclusion

Kubernetes security requires a comprehensive, layered approach. From cluster hardening to pod security to runtime protection, each layer contributes to the overall security posture. Start with the basics—RBAC, network policies, and pod security—then build toward more advanced controls.

Key Takeaways:
Defense in depth is essential
Defaults are often insecure—configure explicitly
Automate security checks in CI/CD
Monitor and audit continuously
Stay current with updates and patches

Asfaleia-Tech offers Kubernetes security assessments, implementation support, and ongoing monitoring. Contact us to secure your container infrastructure.

Tags

#Kubernetes#Container Security#DevSecOps#Cloud Native#K8s

Downloadable-style takeaway

Use this as a working assessment checklist.

Pull the headings into your next security review, assign owners, and mark each section as ready, partial, or missing.

A

Written by

Asfaleia Team

Chief Security Researcher

Written by the Asfaleia Tech Security Team, combining field experience across offensive testing, detection engineering, incident readiness, and compliance evidence.

Ready to Strengthen Your Security?

Let's discuss how Asfaleia-Tech can help protect your organization.