OPA 与 Gatekeeper 策略执行
High Contrast
Dark Mode
Light Mode
Sepia
Forest
2 min read304 words

OPA 与 Gatekeeper 策略执行

核心问题:静态扫描在 CI 中检查,但如何阻止不符合规范的资源直接通过 kubectl apply 进入集群?


准入控制器(Admission Controller)

graph LR USER["kubectl apply
或 ArgoCD 同步"] AUTHN["认证
(Authentication)"] AUTHZ["授权
(RBAC)"] MUT["Mutating
Webhook
(修改资源)"] VAL["Validating
Webhook
(验证资源)"] ETCD["etcd
(存储)"] USER --> AUTHN --> AUTHZ --> MUT --> VAL --> ETCD VAL -->|拒绝| USER

Gatekeeper 是基于 OPA(Open Policy Agent)的 Kubernetes 准入控制器,在 Validating Webhook 阶段执行自定义策略。


安装 Gatekeeper

# Helm 安装
helm repo add gatekeeper https://open-policy-agent.github.io/gatekeeper/charts
helm upgrade --install gatekeeper gatekeeper/gatekeeper \
--namespace gatekeeper-system \
--create-namespace \
--version "3.14.0" \
--set replicas=2 \
--set auditInterval=30

两步定义策略

Step 1:ConstraintTemplate(策略模板)

用 Rego 语言定义规则逻辑:

# ConstraintTemplate:要求容器设置 CPU/内存 Limits
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8srequiredresourcelimits
spec:
crd:
spec:
names:
kind: K8sRequiredResourceLimits
validation:
openAPIV3Schema:
type: object
properties:
containers:
type: array
items:
type: string
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8srequiredresourcelimits
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
not container.resources.limits.cpu
msg := sprintf("容器 '%v' 必须设置 CPU limits", [container.name])
}
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
not container.resources.limits.memory
msg := sprintf("容器 '%v' 必须设置 Memory limits", [container.name])
}

Step 2:Constraint(策略实例)

声明策略应用的范围:

# Constraint:在 production 命名空间强制执行
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredResourceLimits
metadata:
name: production-resource-limits
spec:
match:
kinds:
- apiGroups: ["apps"]
kinds: ["Deployment", "StatefulSet", "DaemonSet"]
namespaces: ["production", "staging"]
enforcementAction: deny     # deny | warn | dryrun

常用内置策略

# 安装 Gatekeeper Library(官方策略集合)
kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/library/general/allowedrepos/template.yaml

要求镜像来自指定仓库

apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8sallowedrepos
spec:
crd:
spec:
names:
kind: K8sAllowedRepos
validation:
openAPIV3Schema:
type: object
properties:
repos:
type: array
items:
type: string
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8sallowedrepos
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
not starts_with(container.image, input.parameters.repos[_])
msg := sprintf("镜像 '%v' 不在允许的仓库列表中", [container.image])
}
---
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sAllowedRepos
metadata:
name: allowed-repos
spec:
match:
kinds:
- apiGroups: ["*"]
kinds: ["Pod"]
namespaces: ["production"]
parameters:
repos:
- "registry.example.com/"   # 私有仓库
- "bitnami/"                 # 允许 bitnami 官方镜像

禁止 latest tag

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sDisallowedTags
metadata:
name: no-latest-tag
spec:
match:
kinds:
- apiGroups: ["*"]
kinds: ["Pod"]
enforcementAction: deny
parameters:
tags: ["latest"]

要求必要标签

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
name: required-labels
spec:
match:
kinds:
- apiGroups: ["apps"]
kinds: ["Deployment"]
namespaces: ["production"]
parameters:
labels:
- key: app.kubernetes.io/name
- key: app.kubernetes.io/version
- key: team

Mutating Webhook:自动注入默认值

Gatekeeper 也支持 MutationPolicy(v3.10+)自动为资源添加默认配置:

apiVersion: mutations.gatekeeper.sh/v1
kind: Assign
metadata:
name: assign-default-security-context
spec:
applyTo:
- groups: [""]
kinds: ["Pod"]
versions: ["v1"]
match:
scope: Namespaced
namespaces: ["production"]
location: "spec.securityContext.runAsNonRoot"
parameters:
assign:
value: true    # 自动为所有 Pod 设置 runAsNonRoot: true

审计模式:现有资源合规检查

# 查看违规资源列表
kubectl get k8srequiredresourcelimits -o yaml
# 查看所有 Constraint 的违规情况
kubectl get constraints -A
# 查看具体违规
kubectl describe k8srequiredresourcelimits production-resource-limits
# Violations:
#   - Message: 容器 'nginx' 必须设置 CPU limits
#     Resource: namespace: production, name: nginx-deployment, group: apps, version: v1, kind: Deployment

OPA vs Kyverno 对比

维度 OPA/Gatekeeper Kyverno
策略语言 Rego(专用) YAML(K8s 原生风格)
学习曲线 高(需学 Rego) 低(纯 YAML)
功能 极强(任意 Rego 表达式) 足够(常见场景全覆盖)
Mutating 支持(v3.10+) 强大(Pattern/Overlay)
社区 成熟,有大量模板 快速增长

Kyverno 简化示例(无需学 Rego):

# Kyverno Policy:禁止 latest tag(YAML 风格)
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-latest-tag
spec:
validationFailureAction: Enforce
rules:
- name: require-image-tag
match:
any:
- resources:
kinds: [Pod]
validate:
message: "镜像必须指定具体版本 tag,不能使用 :latest"
pattern:
spec:
containers:
- image: "!*:latest"

下一节变更审批与 PR Review 流程