4. 策略执行异常场景一:Pod创建被Gatekeeper拒绝——分析AdmissionReview日志
4.1 场景概述
在云原生环境中,Gatekeeper 作为 Kubernetes 的准入控制器(Admission Controller),负责拦截所有 API 请求并根据预定义的 OPA(Open Policy Agent)策略进行校验。当 Pod 创建请求违反约束模板(ConstraintTemplate)或约束(Constraint)时,Gatekeeper 会返回拒绝响应,并记录详细的 AdmissionReview 日志。
本场景模拟一个常见的策略执行异常:用户尝试创建一个未设置 securityContext.runAsNonRoot: true 的 Pod,被 Gatekeeper 拒绝。运维人员需要通过分析 AdmissionReview 日志,定位策略违规的具体原因。
关键概念: AdmissionReview 是 Kubernetes API Server 与准入控制器之间的标准请求/响应格式。Gatekeeper 将策略评估结果封装在 AdmissionReview 的
response 字段中,包含 allowed、status 和 message 等关键信息。
4.2 故障现象与初步排查
用户执行 kubectl apply -f pod.yaml 后,收到类似以下错误:
Error from server (Forbidden): error when creating "pod.yaml": admission webhook "validation.gatekeeper.sh" denied the request: [denied by require-run-as-nonroot] container "nginx" must set securityContext.runAsNonRoot=true
初步排查步骤:
- 确认 Gatekeeper 组件状态: 检查
gatekeeper-controller-managerPod 是否正常运行。 - 检查约束与约束模板: 使用
kubectl get constraints和kubectl get constrainttemplates确认策略已正确部署。 - 查看 Gatekeeper 日志: 通过
kubectl logs -n gatekeeper-system deployment/gatekeeper-controller-manager获取原始日志。
4.3 AdmissionReview 日志结构分析
Gatekeeper 的日志通常以 JSON 格式输出,核心是 AdmissionReview 对象。以下是一个典型的拒绝日志片段:
{
"level": "info",
"ts": 1712345678.123456,
"logger": "webhook",
"msg": "admission review response",
"hook": "validation.gatekeeper.sh",
"admission_review": {
"request": {
"uid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"kind": {"group": "", "version": "v1", "kind": "Pod"},
"resource": {"group": "", "version": "v1", "resource": "pods"},
"name": "my-pod",
"namespace": "default",
"operation": "CREATE",
"object": {
"apiVersion": "v1",
"kind": "Pod",
"metadata": {"name": "my-pod"},
"spec": {
"containers": [{
"name": "nginx",
"image": "nginx:latest",
"securityContext": {}
}]
}
}
},
"response": {
"uid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"allowed": false,
"status": {
"code": 403,
"message": "denied by require-run-as-nonroot: container \"nginx\" must set securityContext.runAsNonRoot=true"
}
}
}
}
4.4 日志关键字段解析
| 字段路径 | 含义 | 本场景值 |
|---|---|---|
admission_review.request.operation |
请求操作类型 | CREATE |
admission_review.request.object.spec.containers[0].securityContext |
容器安全上下文 | {}(空对象,未设置 runAsNonRoot) |
admission_review.response.allowed |
是否允许请求 | false(拒绝) |
admission_review.response.status.code |
HTTP 状态码 | 403(Forbidden) |
admission_review.response.status.message |
拒绝原因描述 | denied by require-run-as-nonroot: container "nginx" must set securityContext.runAsNonRoot=true |
排查技巧: 在 Gatekeeper 日志中,
response.status.message 字段直接引用了约束名称(require-run-as-nonroot)和违规的具体容器名称。这是定位策略违规的最快入口。
4.5 策略执行流程与 AdmissionReview 交互
下图展示了从 Pod 创建请求到 Gatekeeper 返回拒绝响应的完整流程:
4.6 日志分析实战步骤
当面对大量 Gatekeeper 日志时,推荐使用以下方法快速定位问题:
- 过滤关键日志行: 使用
grep或jq提取包含"admission review response"的日志条目。 - 提取拒绝请求: 过滤
response.allowed == false的条目。 - 解析拒绝原因: 从
response.status.message中提取约束名称和违规详情。 - 关联请求对象: 查看
request.object中的 Pod 定义,确认缺失的字段。
常见陷阱: 不要仅依赖
kubectl 返回的错误信息。有时错误信息会被截断或泛化,而 AdmissionReview 日志中包含了完整的请求对象和策略评估细节,是排查的黄金数据源。
4.7 修复与验证
根据日志分析结果,修复 Pod 定义,添加 securityContext.runAsNonRoot: true:
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
securityContext:
runAsNonRoot: true
containers:
- name: nginx
image: nginx:latest
securityContext:
runAsNonRoot: true
runAsUser: 1000
重新应用后,Pod 创建成功,Gatekeeper 日志中对应的新请求将显示 "allowed": true。
4.8 日志分析工具推荐
| 工具 | 用途 | 示例命令 |
|---|---|---|
| jq | 解析 JSON 格式的 AdmissionReview 日志 | kubectl logs ... | jq 'select(.admission_review.response.allowed == false)' |
| grep | 快速过滤包含特定约束名称的日志行 | kubectl logs ... | grep "require-run-as-nonroot" |
| stern | 多 Pod 日志聚合,便于查看所有 Gatekeeper 副本日志 | stern -n gatekeeper-system gatekeeper |
生产建议: 将 Gatekeeper 日志接入集中式日志系统(如 ELK、Loki),并创建针对
response.allowed == false 的告警规则,实现策略违规的实时监控。