Kubernetes Series - Part 6: Security and Access Control
/ 4 min read
Series Navigation
- Part 1: Core Fundamentals
- Part 2: Workload Management
- Part 3: Networking Essentials
- Part 4: Storage and Persistence
- Part 5: Configuration and Secrets
- Part 6: Security and Access Control (Current)
- Part 7: Observability
- Part 8: Advanced Patterns
- Part 9: Production Best Practices
Introduction
After securing numerous Kubernetes clusters in production environments, I’ve learned that security requires a comprehensive, layered approach. In this article, I’ll share practical insights from implementing security measures across various organizations.
Role-Based Access Control (RBAC)
Here’s our production RBAC setup for different teams:
---apiVersion: rbac.authorization.k8s.io/v1kind: Rolemetadata: name: developer namespace: developmentrules:- apiGroups: ["", "apps", "batch"] resources: ["pods", "deployments", "services", "jobs"] verbs: ["get", "list", "watch", "create", "update", "patch"]- apiGroups: [""] resources: ["configmaps", "secrets"] verbs: ["get", "list"]---apiVersion: rbac.authorization.k8s.io/v1kind: RoleBindingmetadata: name: dev-team-binding namespace: developmentsubjects:- kind: Group name: development-team apiGroup: rbac.authorization.k8s.ioroleRef: kind: Role name: developer apiGroup: rbac.authorization.k8s.ioRBAC Best Practices
-
Principle of Least Privilege
- Grant minimal required permissions
- Regular access reviews
- Document role assignments
-
Role Organization
- Create roles per responsibility
- Use aggregated roles
- Implement role hierarchy
Pod Security Standards
Our pod security policy implementation:
apiVersion: pod-security.kubernetes.io/v1kind: SecurityContextmetadata: name: restricted-podsspec: runAsNonRoot: true runAsUser: 1000 runAsGroup: 3000 fsGroup: 2000 supplementalGroups: [1000] seccompProfile: type: RuntimeDefault capabilities: drop: ["ALL"]Container Security
Secure container configuration:
apiVersion: apps/v1kind: Deploymentmetadata: name: secure-appspec: template: spec: securityContext: runAsNonRoot: true runAsUser: 1000 containers: - name: app securityContext: allowPrivilegeEscalation: false capabilities: drop: ["ALL"] readOnlyRootFilesystem: true resources: limits: memory: "256Mi" cpu: "500m"Security Context Tips
-
Container Hardening
- Run as non-root
- Use read-only root filesystem
- Drop unnecessary capabilities
-
Resource Controls
- Set appropriate limits
- Implement quotas
- Monitor resource usage
Network Security
Our comprehensive network policy:
apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: secure-policyspec: podSelector: matchLabels: app: secure-app policyTypes: - Ingress - Egress ingress: - from: - namespaceSelector: matchLabels: name: frontend - podSelector: matchLabels: role: frontend ports: - protocol: TCP port: 8080 egress: - to: - namespaceSelector: matchLabels: name: backend ports: - protocol: TCP port: 5432Network Security Best Practices
-
Segmentation
- Implement zero-trust model
- Use namespace isolation
- Control egress traffic
-
Monitoring
- Log denied connections
- Monitor policy effectiveness
- Regular security audits
Service Accounts
How we manage service accounts:
apiVersion: v1kind: ServiceAccountmetadata: name: app-service-account annotations: eks.amazonaws.com/role-arn: arn:aws:iam::account-id:role/app-role---apiVersion: rbac.authorization.k8s.io/v1kind: Rolemetadata: name: app-rolerules:- apiGroups: [""] resources: ["configmaps", "secrets"] verbs: ["get"]---apiVersion: rbac.authorization.k8s.io/v1kind: RoleBindingmetadata: name: app-role-bindingsubjects:- kind: ServiceAccount name: app-service-accountroleRef: kind: Role name: app-role apiGroup: rbac.authorization.k8s.ioService Account Tips
-
Access Management
- Use dedicated service accounts
- Implement proper RBAC
- Regular rotation of credentials
-
Cloud Integration
- Use cloud provider IAM
- Implement proper role assumption
- Monitor access patterns
Secrets Management
Our approach to secure secrets:
apiVersion: secrets-store.csi.x-k8s.io/v1kind: SecretProviderClassmetadata: name: aws-secretsspec: provider: aws parameters: objects: | - objectName: "production/app1/secret1" objectType: "secretsmanager" objectVersion: "AWSCURRENT" secretObjects: - secretName: app-secret type: Opaque data: - objectName: production/app1/secret1 key: secret-keySecrets Best Practices
-
Storage
- Use external secret managers
- Encrypt secrets at rest
- Implement proper rotation
-
Access Control
- Implement least privilege
- Audit secret access
- Monitor usage patterns
Audit Logging
Our audit policy configuration:
apiVersion: audit.k8s.io/v1kind: Policyrules:- level: RequestResponse resources: - group: "" resources: ["secrets", "configmaps"]- level: Metadata resources: - group: "" resources: ["pods", "services"]- level: None users: ["system:kube-proxy"] resources: - group: "" # core resources: ["endpoints", "services", "services/status"]Audit Best Practices
-
Log Management
- Configure appropriate log levels
- Implement log retention
- Regular log analysis
-
Monitoring
- Set up alerts
- Monitor suspicious activities
- Regular security reviews
Common Security Issues
From my experience, here are frequent problems and solutions:
-
Access Control
- Over-privileged service accounts
- Insufficient network policies
- Improper RBAC configuration
-
Container Security
- Running as root
- Unnecessary capabilities
- Vulnerable dependencies
-
Secret Management
- Exposed secrets in configs
- Improper rotation
- Insufficient monitoring
Production Checklist
✅ Access Control
- RBAC implementation
- Service account configuration
- Regular access reviews
- Audit logging
✅ Pod Security
- Security contexts
- Resource limits
- Image scanning
- Runtime security
✅ Network Security
- Network policies
- Ingress/Egress controls
- Service mesh
- TLS configuration
✅ Monitoring
- Security logging
- Audit trails
- Alert configuration
- Regular audits
Real-world Example
Complete example of a secure application deployment:
---apiVersion: v1kind: ServiceAccountmetadata: name: secure-app---apiVersion: apps/v1kind: Deploymentmetadata: name: secure-appspec: template: metadata: annotations: seccomp.security.alpha.kubernetes.io/pod: runtime/default spec: serviceAccountName: secure-app securityContext: runAsNonRoot: true runAsUser: 1000 fsGroup: 2000 containers: - name: app image: secure-app:1.0.0 securityContext: allowPrivilegeEscalation: false capabilities: drop: ["ALL"] readOnlyRootFilesystem: true resources: limits: memory: "256Mi" cpu: "500m" volumeMounts: - name: secrets mountPath: /mnt/secrets-store readOnly: true volumes: - name: secrets csi: driver: secrets-store.csi.k8s.io readOnly: true volumeAttributes: secretProviderClass: aws-secretsConclusion
Kubernetes security requires a comprehensive approach covering multiple layers. Key takeaways from my experience:
- Implement security at every layer
- Follow the principle of least privilege
- Monitor and audit continuously
- Keep dependencies updated
- Regular security reviews
In the next part, we’ll explore observability in Kubernetes, where I’ll share practical tips for monitoring and troubleshooting your applications.