Skip to content

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-app

2. RBAC(Role-Based Access Control)

2.1 RBAC 四大资源

资源作用域说明
RoleNamespace定义权限规则
ClusterRoleCluster集群级权限
RoleBindingNamespace绑定 Role 到用户/SA
ClusterRoleBindingCluster绑定 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.io
bash
# 常用 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: TCP
bash
# 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: None

6. 面试高频问题

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: restricted

Q: 如何实现 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"