跳转至

认证与安全

Kubernetes 的安全模型是分层的:先证明你是谁,再判断你能做什么,最后在准入阶段拦截不合规的请求。任何一层缺失,后面的隔离都不可靠。

难度 · 进阶 预计 55 分钟 前置:架构与对象模型、网络

你将学到

  • 认证、授权、准入、审计四层模型
  • 用户与 ServiceAccount 的区别
  • RBAC 的 Role / ClusterRole / Binding 与最小权限
  • SecurityContext 与 Pod Security Standards
  • 用 CSR API 手工签发客户端证书
  • Secret、NetworkPolicy、镜像安全的基本边界

四层模型

flowchart LR
  U[请求] --> A[认证<br/>你是谁]
  A --> B[授权<br/>你能做什么]
  B --> C[准入<br/>请求是否合规]
  C --> D[持久化 / 执行]
  D --> E[审计日志]

图:API Server 的请求处理链。任何一层拒绝,请求都不会落库。

层 解决的问题 常见机制
认证 身份是否可信 客户端证书、Bearer Token、OIDC、Webhook
授权 是否有权限 RBAC、ABAC、Node、Webhook
准入 是否符合策略 Mutating / Validating Webhook、PSA、配额
审计 谁做了什么 Audit Policy + 后端

用户与 ServiceAccount

维度 普通用户 ServiceAccount
管理方式 外部(证书 / OIDC) Kubernetes 对象
作用范围 集群 命名空间
用途 人 Pod 内的进程
凭证 kubeconfig 自动挂载的 Token / 投影卷

Kubernetes 不存储普通用户对象。你用证书或 OIDC 登录,API Server 只认证书里的 CN/O 或 Token 里的 claims。

查看当前身份:

kubectl auth whoami
kubectl config view --minify

ServiceAccount

serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: reader
  namespace: demo
automountServiceAccountToken: false

Pod 使用:

spec:
  serviceAccountName: reader
  automountServiceAccountToken: false

最佳实践:

  • 每个应用一个 SA,不要共用 default;
  • 不需要访问 API 的应用关闭自动挂载;
  • 需要 Token 时用投影卷,设置过期时间与 audience。

RBAC

RBAC 由四个对象组成:

对象 作用域 作用
Role namespace 定义一组权限
ClusterRole 集群 定义集群级权限,或可复用的权限集
RoleBinding namespace 把 Role/ClusterRole 绑给主体
ClusterRoleBinding 集群 把 ClusterRole 绑给主体
rbac.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-reader
  namespace: demo
rules:
  - apiGroups: [""]
    resources: ["pods", "pods/log"]
    verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: pod-reader-binding
  namespace: demo
subjects:
  - kind: ServiceAccount
    name: reader
    namespace: demo
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: pod-reader

验证:

kubectl auth can-i get pods -n demo \
  --as=system:serviceaccount:demo:reader
kubectl auth can-i delete pods -n demo \
  --as=system:serviceaccount:demo:reader
kubectl auth can-i --list -n demo \
  --as=system:serviceaccount:demo:reader

常用 verbs

verb 含义
get 读取单个资源
list 列出资源
watch 监听变化
create 创建
update 更新
patch 局部更新
delete 删除
deletecollection 批量删除

get 与 list 是不同权限。只给 get 时,kubectl get pods(列表)仍会被拒绝。

最小权限原则

  • 优先用 Role,不用 ClusterRoleBinding;
  • 不要给 * 资源或 * verbs;
  • 需要读日志时单独给 pods/log;
  • 定期审计 system:masters、cluster-admin 的绑定;
  • 用 kubectl auth reconcile 管理 RBAC 变更。

cluster-admin 不是万能钥匙

给应用绑定 cluster-admin,等于把整个集群交给它。一旦容器被攻破,攻击者可以直接创建特权 Pod、读取所有 Secret。生产环境应使用命名空间级 Role。

SecurityContext

Pod 级与容器级的安全配置:

secure-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: secure-demo
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    runAsGroup: 3000
    fsGroup: 2000
    seccompProfile:
      type: RuntimeDefault
  containers:
    - name: app
      image: nginx:1.27
      securityContext:
        allowPrivilegeEscalation: false
        readOnlyRootFilesystem: true
        capabilities:
          drop: ["ALL"]
      volumeMounts:
        - name: cache
          mountPath: /var/cache/nginx
        - name: run
          mountPath: /var/run
  volumes:
    - name: cache
      emptyDir: {}
    - name: run
      emptyDir: {}
字段 作用 建议
runAsNonRoot 禁止 root 用户 开启
allowPrivilegeEscalation 禁止提权 false
readOnlyRootFilesystem 根文件系统只读 开启,需挂可写目录
capabilities.drop 去掉 Linux capabilities 至少 drop ALL
seccompProfile 系统调用过滤 RuntimeDefault

Pod Security Standards

Kubernetes 内置三档 Pod 安全标准:

级别 限制 适用
privileged 几乎不限制 系统组件
baseline 禁止特权、hostNetwork 等 一般业务
restricted 强制非 root、只读根、drop caps 高安全业务

用命名空间标签启用:

kubectl label namespace demo \
  pod-security.kubernetes.io/enforce=restricted \
  pod-security.kubernetes.io/audit=restricted \
  pod-security.kubernetes.io/warn=restricted

enforce 拒绝不合规 Pod,audit 记录,warn 返回警告。已有 Pod 不会因为打标签而被删除,但重建时会受限。

CSR API:手工签发证书

仓库中的 examples/authn_and_authz/certificate-sign-request-demo 演示了这条链路。核心步骤:

openssl genrsa -out mason.key 2048
openssl req -new -key mason.key -out mason.csr -subj "/CN=mason/O=dev"
mason-csr.yaml
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
  name: mason
spec:
  request: <base64 编码的 CSR>
  signerName: kubernetes.io/kube-apiserver-client
  usages:
    - client auth
# 生成 base64 并替换
CSR=$(cat mason.csr | base64 | tr -d '\n')
sed "s|<base64 编码的 CSR>|${CSR}|" mason-csr.yaml | kubectl apply -f -

kubectl get csr mason
kubectl certificate approve mason
kubectl get csr mason -o jsonpath='{.status.certificate}' | base64 -d > mason.crt

配置 kubeconfig:

kubectl config set-credentials mason \
  --client-certificate=mason.crt \
  --client-key=mason.key

kubectl config set-context mason \
  --cluster=kubernetes \
  --user=mason

kubectl --context=mason auth whoami

新用户默认没有任何权限,需要额外绑定 Role。这正是「认证」与「授权」分离的体现。

证书里有什么

CN 是用户名,O 是组。RBAC 的 subject 可以用 User 或 Group 匹配。不要把 O=system:masters 签给普通用户,那是超级权限组。

Secret 与静态加密

Secret 默认以 base64 存在 etcd。生产环境至少做三件事:

  1. 开启 etcd 静态加密(EncryptionConfiguration);
  2. 限制 Secret 的 RBAC,禁止普通用户 list;
  3. 使用 External Secrets / Sealed Secrets 管理密钥来源。

检查是否有权限:

kubectl auth can-i list secrets -n demo
kubectl auth can-i get secrets -n demo

网络与供应链

  • NetworkPolicy:默认拒绝 + 按需放行,参见 服务与网络。
  • 镜像:使用不可变 tag / digest,启用镜像签名与漏洞扫描。
  • 准入:用 Kyverno / OPA Gatekeeper 强制「禁止 latest」「必须设置 resources」等策略。
  • 运行时:启用 seccomp、AppArmor,限制 hostPath 与 hostNetwork。

实验:创建一个只读用户

1. 创建 SA、Role、RoleBinding

kubectl create namespace demo --dry-run=client -o yaml | kubectl apply -f -
kubectl apply -f serviceaccount.yaml
kubectl apply -f rbac.yaml

2. 验证权限

kubectl auth can-i get pods -n demo --as=system:serviceaccount:demo:reader
# yes
kubectl auth can-i delete pods -n demo --as=system:serviceaccount:demo:reader
# no

3. 用 Token 实际请求

TOKEN=$(kubectl create token reader -n demo)
kubectl get pods -n demo --token="$TOKEN" \
  --server=https://k8s-master01.magedu.com:6443 \
  --certificate-authority=/etc/kubernetes/pki/ca.crt

4. 启用 restricted 策略

kubectl label namespace demo pod-security.kubernetes.io/enforce=restricted --overwrite
kubectl run bad --image=nginx:1.27 -n demo

预期被拒绝,错误信息会指出违反了哪条 restricted 规则。给 Pod 补上 runAsNonRoot、seccompProfile、drop ALL 后再试。

排错表

现象 原因 处理
Forbidden RBAC 未授权 kubectl auth can-i --list、检查 Binding
Unauthorized 证书/Token 无效 kubectl config view、检查过期时间
SA 无法访问 API 未绑定 Role / Token 未挂载 describe pod、automountServiceAccountToken
Pod 被 PSA 拒绝 违反 restricted 看错误信息,补 securityContext
Secret 读不到 RBAC 限制 / 命名空间错 auth can-i get secrets
证书过期 客户端证书未轮换 重新签发,检查 kubeadm certs
exec 被拒绝 RBAC 缺少 pods/exec 单独授权 pods/exec

进阶挑战

  1. 创建一个只能 get 单个 Pod(resourceNames)的 Role,验证 list 被拒绝。
  2. 用 kubectl auth reconcile 更新 RoleBinding,观察它如何合并权限。
  3. 给命名空间启用 baseline,找出一个不合规的 Pod 并修复。
  4. 用 CSR API 签发一个属于 dev 组的证书,绑定一个只读 Role。
  5. 检查集群中所有 cluster-admin 绑定,判断哪些可以降级。

小结

  • 安全是分层防御:认证 → 授权 → 准入 → 审计。
  • RBAC 要最小权限,避免给应用 cluster-admin。
  • SecurityContext + PSA 是 Pod 层的基线,Secret 要配合加密与外部密钥管理。
  • 认证与授权分离:证书只证明身份,权限来自 Binding。

延伸阅读