Kubernetes RBAC chi tiết, Pod Security Standards (PSS), ServiceAccount best practices, least-privilege access, audit logging, và security hardening cho cluster.
🔒 DevSecOps — Bài 36
BÀI 36: RBAC & POD SECURITY STANDARDS
Deploy Microservices On-Premises với Kubernetes HA
Phần 9: Security Hardening
xdev.asia
🎯 MỤC TIÊU BÀI HỌC
✅ Kubernetes RBAC (Role, ClusterRole, Binding)
✅ Pod Security Standards (Privileged, Baseline, Restricted)
✅ ServiceAccount best practices
✅ Audit logging configuration
✅ Security hardening checklist
PHẦN 1: KUBERNETES RBAC
RBAC Model:
User/ServiceAccount
│
▼
┌──────────────┐ ┌──────────────────┐
│ RoleBinding │────►│ Role │
│(namespace) │ │ (namespace) │
│ │ │ - get pods │
│ │ │ - list services │
└──────────────┘ └──────────────────┘
┌──────────────────┐ ┌──────────────────┐
│ClusterRoleBinding│─►│ ClusterRole │
│ (cluster-wide) │ │ (cluster-wide) │
│ │ │ - get nodes │
│ │ │ - list PVs │
└──────────────────┘ └──────────────────┘
# Role for app namespace (least privilege):
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: app-developer
namespace: default
rules:
- apiGroups: [""]
resources: ["pods", "services", "configmaps"]
verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "watch", "update", "patch"]
- apiGroups: [""]
resources: ["pods/log"]
verbs: ["get"]
# Explicitly deny secrets access (not listed)
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: developer-binding
namespace: default
subjects:
- kind: User
name: [email protected]
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: app-developer
apiGroup: rbac.authorization.k8s.io
# ClusterRole for read-only monitoring:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: monitoring-reader
rules:
- apiGroups: [""]
resources: ["pods", "nodes", "services", "endpoints"]
verbs: ["get", "list", "watch"]
- apiGroups: ["metrics.k8s.io"]
resources: ["pods", "nodes"]
verbs: ["get", "list"]
- nonResourceURLs: ["/metrics"]
verbs: ["get"]
PHẦN 2: SERVICEACCOUNT BEST PRACTICES
# Dedicated ServiceAccount per workload:
apiVersion: v1
kind: ServiceAccount
metadata:
name: order-service
namespace: default
automountServiceAccountToken: false # Disable auto-mount
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-service
spec:
template:
spec:
serviceAccountName: order-service
automountServiceAccountToken: false # Double ensure
containers:
- name: app
image: registry.local/order-service:v1.0
securityContext:
allowPrivilegeEscalation: false
runAsNonRoot: true
runAsUser: 1000
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
PHẦN 3: POD SECURITY STANDARDS
Level Description Use Case
Privileged No restrictions System-level (CNI, storage drivers)
Baseline Prevent known privilege escalation Default for most workloads
Restricted Hardened, all best practices Sensitive workloads
# Apply PSS via namespace labels:
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
# Enforce restricted:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/enforce-version: latest
# Warn on baseline violations:
pod-security.kubernetes.io/warn: restricted
pod-security.kubernetes.io/audit: restricted
---
# Namespace for system workloads:
apiVersion: v1
kind: Namespace
metadata:
name: kube-system
labels:
pod-security.kubernetes.io/enforce: privileged
# Pod that complies with Restricted:
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: registry.local/app:v1
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi
PHẦN 4: AUDIT LOGGING
# /etc/kubernetes/audit-policy.yaml:
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
# Log all auth failures:
- level: Metadata
omitStages: ["RequestReceived"]
users: ["system:anonymous"]
# Log secret access:
- level: RequestResponse
resources:
- group: ""
resources: ["secrets"]
verbs: ["get", "list", "watch", "create", "update", "delete"]
# Log RBAC changes:
- level: RequestResponse
resources:
- group: "rbac.authorization.k8s.io"
resources: ["roles", "rolebindings", "clusterroles", "clusterrolebindings"]
# Log pod exec/attach:
- level: RequestResponse
resources:
- group: ""
resources: ["pods/exec", "pods/attach"]
# Default: metadata only
- level: Metadata
omitStages: ["RequestReceived"]
# Enable in kube-apiserver:
# /etc/kubernetes/manifests/kube-apiserver.yaml
# Add flags:
# --audit-policy-file=/etc/kubernetes/audit-policy.yaml
# --audit-log-path=/var/log/kubernetes/audit.log
# --audit-log-maxage=30
# --audit-log-maxbackup=10
# --audit-log-maxsize=100
# Forward audit logs to Loki:
# Configure Promtail to scrape /var/log/kubernetes/audit.log
PHẦN 5: SECURITY HARDENING CHECKLIST
# Item Status
1 RBAC enabled, no cluster-admin for apps ☐
2 Pod Security Standards enforced ☐
3 ServiceAccount token auto-mount disabled ☐
4 Network Policies deny-all default ☐
5 Audit logging enabled ☐
6 etcd encryption at rest ☐
7 API server on private network only ☐
8 Kubelet authn/authz enabled ☐
9 Container images signed/scanned ☐
10 Secrets in Vault (not plain K8s secrets) ☐
💡 KEY TAKEAWAYS
RBAC : Least privilege — only grant needed verbs/resources
ServiceAccount : Per-workload, disable token auto-mount
PSS : Enforce Restricted for production namespaces
Audit : Log secret access, RBAC changes, pod exec
SecurityContext : runAsNonRoot, drop ALL capabilities, readOnlyRootFilesystem
🎯 BÀI TẬP
Bài tập 1: RBAC Setup
Create developer/ops Roles with different permissions
Test access with kubectl --as=developer
Enable audit logging, verify secret access is logged
Bài tập 2: Pod Security
Label namespace with restricted PSS
Deploy a privileged pod → verify rejection
Fix pod to comply with restricted level
📚 BÀI TIẾP THEO
Trong Bài 37: Kyverno Policy Engine , chúng ta sẽ implement policy-as-code cho cluster.