主题
11 — 安全与 RBAC 深度教材
安全是 K8s 生产环境的基石。本章覆盖认证授权、RBAC 最小权限、NetworkPolicy、PodSecurity、Admission Controller。
1. 认证(Authentication)
K8s 认证方式(按优先级):
1. X509 客户端证书(kubelet、组件通信)
2. Bearer Token(静态 token、ServiceAccount token)
3. OIDC(企业 SSO 集成)
4. Webhook(自定义认证服务)
5. 匿名访问(不推荐,默认禁用)1.1 ServiceAccount Token
bash
# 每个 Pod 自动挂载 ServiceAccount Token(K8s 1.21+)
# Token 路径:/var/run/secrets/kubernetes.io/serviceaccount/token
# Token 是短期有效的(1 小时),自动轮换
# 禁用自动挂载(安全最佳实践)
spec:
automountServiceAccountToken: false
serviceAccountName: my-app
# 创建专用 ServiceAccount
kubectl create sa my-app -n default
kubectl create rolebinding my-app --clusterrole=view --serviceaccount=default:my-app2. RBAC(Role-Based Access Control)
2.1 RBAC 四大资源
| 资源 | 作用域 | 说明 |
|---|---|---|
| Role | Namespace | 定义权限规则 |
| ClusterRole | Cluster | 集群级权限 |
| RoleBinding | Namespace | 绑定 Role 到用户/SA |
| ClusterRoleBinding | Cluster | 绑定 ClusterRole |
2.2 生产 RBAC 配置
yaml
# 最小权限 Role:只允许查看 Pod 日志
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: log-viewer
namespace: production
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list"]
- apiGroups: [""]
resources: ["pods/log"]
verbs: ["get"]
---
# 绑定到开发者组
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: dev-log-viewer
namespace: production
roleRef:
name: log-viewer
kind: Role
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: Group
name: developers
apiGroup: rbac.authorization.k8s.iobash
# 常用 RBAC 检查命令
kubectl auth can-i get pods --as=system:serviceaccount:default:my-app -n production
kubectl auth can-i --list --as-group=developers -n production
# 查看某个 ServiceAccount 的所有权限
kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]?.name=="my-app")'3. NetworkPolicy(网络策略)
yaml
# 默认拒绝所有入站流量(零信任基础)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: production
spec:
podSelector: {} # 选择所有 Pod
policyTypes:
- Ingress
# 允许特定来源的入站
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-web-ingress
namespace: production
spec:
podSelector:
matchLabels:
app: web
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: ingress-nginx
- podSelector:
matchLabels:
app: api-gateway
ports:
- port: 8080
protocol: TCPbash
# NetworkPolicy 生效需要 CNI 插件支持
# Calico/Cilium/Weave 支持 NetworkPolicy
# Flannel 不支持(需要额外安装 NetworkPolicy 控制器)
# 测试 NetworkPolicy
kubectl exec <pod-a> -- curl -s http://<pod-b-ip>:8080
# 被拒绝 = NetworkPolicy 生效4. Pod Security Standards
yaml
# K8s 1.25+ 内置 Pod Security Admission
# 三个级别:Privileged > Baseline > Restricted
# Namespace 级别强制
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
# Restricted 级别要求:
# - 禁止特权容器(privileged: false)
# - 禁止 hostNetwork/hostPID/hostIPC
# - 禁止 hostPath 挂载
# - 必须 runAsNonRoot
# - 必须设置 securityContext(seccomp、capabilities)yaml
# Pod 安全最佳实践
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 2000
seccompProfile:
type: RuntimeDefault
containers:
- name: app
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]5. Admission Controller
bash
# 内置 Admission Controller
# AlwaysPullImages → 强制拉取镜像
# LimitRanger → 强制设置资源限制
# ResourceQuota → 限制 Namespace 资源总量
# PodSecurity → Pod 安全标准
# NodeRestriction → 限制 kubelet 权限
# Webhook Admission(自定义准入)
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"]
clientConfig:
service:
name: image-policy-webhook
namespace: kube-system
path: /validate
failurePolicy: Fail # webhook 失败时拒绝请求
sideEffects: None6. 面试高频问题
Q: 如何防止 Pod 逃逸到宿主机?
1. securityContext: runAsNonRoot, allowPrivilegeEscalation: false
2. 禁止 privileged: true
3. 禁止 hostNetwork/hostPID/hostIPC
4. capabilities drop ALL
5. readOnlyRootFilesystem
6. NetworkPolicy 限制出站
7. Pod Security Admission: restrictedQ: 如何实现 Namespace 级别的资源配额?
yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: production-quota
namespace: production
spec:
hard:
requests.cpu: "20"
requests.memory: 40Gi
limits.cpu: "40"
limits.memory: 80Gi
pods: "100"
services: "20"
persistentvolumeclaims: "50"