认证与安全¶
Kubernetes 的安全模型是分层的:先证明你是谁,再判断你能做什么,最后在准入阶段拦截不合规的请求。任何一层缺失,后面的隔离都不可靠。
你将学到¶
- 认证、授权、准入、审计四层模型
- 用户与 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。
查看当前身份:
ServiceAccount¶
apiVersion: v1
kind: ServiceAccount
metadata:
name: reader
namespace: demo
automountServiceAccountToken: false
Pod 使用:
最佳实践:
- 每个应用一个 SA,不要共用
default; - 不需要访问 API 的应用关闭自动挂载;
- 需要 Token 时用投影卷,设置过期时间与 audience。
RBAC¶
RBAC 由四个对象组成:
| 对象 | 作用域 | 作用 |
|---|---|---|
| Role | namespace | 定义一组权限 |
| ClusterRole | 集群 | 定义集群级权限,或可复用的权限集 |
| RoleBinding | namespace | 把 Role/ClusterRole 绑给主体 |
| ClusterRoleBinding | 集群 | 把 ClusterRole 绑给主体 |
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 级与容器级的安全配置:
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"
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。生产环境至少做三件事:
- 开启 etcd 静态加密(
EncryptionConfiguration); - 限制 Secret 的 RBAC,禁止普通用户
list; - 使用 External Secrets / Sealed Secrets 管理密钥来源。
检查是否有权限:
网络与供应链¶
- 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 |
进阶挑战¶
- 创建一个只能
get单个 Pod(resourceNames)的 Role,验证list被拒绝。 - 用
kubectl auth reconcile更新 RoleBinding,观察它如何合并权限。 - 给命名空间启用
baseline,找出一个不合规的 Pod 并修复。 - 用 CSR API 签发一个属于
dev组的证书,绑定一个只读 Role。 - 检查集群中所有
cluster-admin绑定,判断哪些可以降级。
小结¶
- 安全是分层防御:认证 → 授权 → 准入 → 审计。
- RBAC 要最小权限,避免给应用
cluster-admin。 - SecurityContext + PSA 是 Pod 层的基线,Secret 要配合加密与外部密钥管理。
- 认证与授权分离:证书只证明身份,权限来自 Binding。
延伸阅读¶
- RBAC 授权
- Pod 安全标准
- 证书签发
- 原仓库示例:examples/authn_and_authz
- 下一章:平台能力总览