欢迎光临

Kubernetes OPA/Gatekeeper 实战指南:用 Policy-as-Code 实现集群安全策略的自动化治理

为什么你需要 OPA/Gatekeeper?

随着 Kubernetes 集群规模的增长,多团队共享集群的场景变得越来越普遍。开发团队自助部署应用、运维团队负责基础设施——这种模式下,如何确保每个人都遵守集群的安全规范?如何防止有人提交了违反规则的资源?如何在不影响开发效率的前提下,实现合规治理的自动化?

传统的做法是编写运维文档、开审批流程、人工审核 YAML 文件。但这种方式在几十个团队、数百个微服务的规模下完全不可行。我们需要一种 Policy-as-Code(策略即代码) 的方案——将安全策略和合规规则写成代码,在资源创建的瞬间自动拦截违规请求。

这就是 OPA(Open Policy Agent) 和它的 Kubernetes 专属集成 Gatekeeper 登场的地方。OPA 是一个通用的策略引擎,而 Gatekeeper 将其作为 Kubernetes 的 准入控制器(Admission Controller) 运行,在资源被持久化到 etcd 之前,对每个 API 请求进行策略评估。

Kubernetes 集群安全策略架构

OPA 与 Gatekeeper 的核心概念

什么是 OPA?

OPA(Open Policy Agent)是一个开源的、通用的策略引擎,由 Styra 公司创建并捐赠给 CNCF(目前已毕业)。它的核心思想是 将策略从业务逻辑中解耦。无论你是在 Kubernetes、微服务 API 网关、Terraform 还是 CI/CD 流水线中做策略决策,OPA 都提供统一的声明式策略语言——Rego

OPA 的工作方式可以概括为:

  • 输入(Input):传入一个 JSON 结构,代表需要评估的对象(例如一个 Pod 的 YAML 定义)
  • 策略(Policy):用 Rego 语言编写的规则集合
  • 输出(Output):策略评估的结果——允许、拒绝或警告,附带详细的决策理由

什么是 Gatekeeper?

Gatekeeper 是 OPA 的 Kubernetes 原生集成方案。它本质上是一个 Kubernetes 准入 Webhook,通过 ValidatingAdmissionWebhook 机制拦截所有资源的创建、更新请求,交给 OPA 引擎进行策略评估。

Gatekeeper 引入了几种关键的 Kubernetes 自定义资源(CRD):

CRD 名称 作用 类比
1
ConstraintTemplate
定义策略的模板(Rego 代码 + Schema) 类似编程中的”类”
1
Constraint
策略的具体实例,指定参数和生效范围 类似编程中的”对象实例”
1
Config
配置 Gatekeeper 的同步行为(哪些资源需要被缓存) 类似配置文件

安装 Gatekeeper

Gatekeeper 的安装非常简单,一条命令即可完成:


1
2
3
4
5
6
7
8
9
# 使用最新稳定版
kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper/release-3.17/deploy/gatekeeper.yaml

# 验证安装
kubectl get pods -n gatekeeper-system
NAME                                             READY   STATUS    RESTARTS
gatekeeper-audit-5d8d9c6b7f-abcde               1/1     Running   0
gatekeeper-controller-manager-7f8d9c6b7-xyz     1/1     Running   0
gatekeeper-controller-manager-7f8d9c6b7-uvw     1/1     Running   0

安装完成后,Gatekeeper 会在

1
gatekeeper-system

命名空间部署两个组件:

  • controller-manager:处理准入请求的主要组件,通常部署 2~3 个副本保证高可用
  • audit:定期审计集群中已有的资源,检查是否违反策略,并将结果记录在 Constraint 的 status 中

编写第一个 ConstraintTemplate

下面我们从一个实际场景开始:禁止在非生产命名空间中使用

1
latest

标签的容器镜像。

定义 ConstraintTemplate


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: k8sdisallowedtags
spec:
  crd:
    spec:
      names:
        kind: K8sDisallowedTags
      validation:
        openAPIV3Schema:
          type: object
          properties:
            tags:
              type: array
              items:
                type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8sdisallowedtags

        violation[{"msg": msg}] {
          container := input.review.object.spec.containers[_]
          tag := container.image
          # 提取镜像标签
          contains(tag, ":latest")
          not startswith(tag, "sha256:")
          msg := sprintf("镜像 %v 使用了 'latest' 标签,请指定明确的版本号", [container.image])
        }

        # 也检查 initContainers
        violation[{"msg": msg}] {
          container := input.review.object.spec.initContainers[_]
          tag := container.image
          contains(tag, ":latest")
          not startswith(tag, "sha256:")
          msg := sprintf("Init 容器 %v 使用了 'latest' 标签,请指定明确的版本号", [container.image])
        }

创建 Constraint 实例


1
2
3
4
5
6
7
8
9
10
11
12
13
14
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sDisallowedTags
metadata:
  name: block-latest-tags
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
    namespaces:
      - "!production"  # 排除 production 命名空间
  parameters:
    tags:
      - "latest"

部署后,尝试在 staging 命名空间创建使用

1
latest

标签的 Pod 会被直接拒绝:


1
2
3
kubectl create deployment nginx --image=nginx:latest -n staging
# Error: admission webhook "validation.gatekeeper.sh" denied the request:
# 镜像 nginx:latest 使用了 'latest' 标签,请指定明确的版本号

Policy as Code 代码审查

深入理解 Rego 语言

Rego 是 OPA 的声明式查询语言,受到 Datalog 的启发。对于刚接触的人来说,Rego 的语法可能会有些陌生——它不像传统的 if-else 命令式编程,而是基于”规则”和”条件”的声明式推理。

Rego 的核心概念

理解 Rego 的关键在于记住以下几点:

  • 规则(Rules):Rego 中的规则有两种类型——
    1
    complete rules

    (完整规则,赋值一次)和

    1
    incremental rules

    (增量规则,可以多次赋值)

  • 迭代(Iteration):使用
    1
    some

    关键字或下划线

    1
    _

    进行隐式迭代

  • 匹配(Matching):Rego 中的赋值使用
    1
    :=

    ,而相等判断使用

    1
    ==

    1
    =
  • 集合(Comprehension):类似于 Python 的列表推导式

下面是一个更复杂的 Rego 示例,演示如何检查容器是否设置了资源限制:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package k8srequiredresources

# 检查容器是否设置了资源请求和限制
violation[{"msg": msg, "details": details}] {
  container := input.review.object.spec.containers[_]
  not container_resources_set(container)
  msg := sprintf("容器 %v 未设置资源限制和请求", [container.name])
  details := {
    "container_name": container.name,
    "suggestion": "设置 resources.requests 和 resources.limits"
  }
}

# 辅助函数:检查容器是否设置了资源
container_resources_set(container) {
  container.resources.requests != {}
  container.resources.limits != {}
}

# 用于 audit 阶段的汇总查询
count_violations := count_violations_result

count_violations_result := violations {
  violations := [true | container := input.review.object.spec.containers[_]; not container_resources_set(container)]
  count(violations) > 0
}

Gatekeeper 的审计功能

Gatekeeper 的一大优势是它不仅有 实时准入控制(在资源创建时拦截),还提供 定期审计 功能。这意味着即使某个资源在创建时绕过了策略检查(比如在 Gatekeeper 部署之前就已经存在),审计组件也会定期扫描集群中所有已有资源,标记出违反策略的对象。

审计结果可以通过查看 Constraint 对象的 status 获取:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
kubectl get constraint block-latest-tags -o yaml | grep -A 10 status:
status:
  auditTimestamp: "2026-07-17T10:00:00Z"
  totalViolations: 5
  violations:
  - enforcementAction: deny
    kind: Pod
    message: 镜像 nginx:latest 使用了 'latest' 标签
    name: old-nginx-pod
    namespace: staging
  - enforcementAction: deny
    kind: Pod
    message: 镜像 redis:latest 使用了 'latest' 标签
    name: cache-pod
    namespace: default

高级策略模式

1. 数据同步与外部数据引用

Gatekeeper 支持将集群中的已有资源缓存到 OPA 引擎中,这允许我们编写跨资源的策略。例如,检查所有 Ingress 是否引用了已存在的 Service:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 启用数据同步:在 Config 中配置
apiVersion: config.gatekeeper.sh/v1alpha1
kind: Config
metadata:
  name: config
  namespace: gatekeeper-system
spec:
  sync:
    syncOnly:
      - group: ""
        version: "v1"
        kind: "Service"
      - group: "networking.k8s.io"
        version: "v1"
        kind: "Ingress"
---
# 在 Rego 中引用同步数据
package ingress_valid_service

violation[{"msg": msg}] {
  ingress := input.review.object
  ingress.serviceName := ingress.spec.rules[_].http.paths[_].backend.service.name
  not data.inventory.namespace[ingress.metadata.namespace]["v1"]["Service"][ingress.serviceName]
  msg := sprintf("Ingress %v 引用了不存在的 Service: %v", [ingress.metadata.name, ingress.serviceName])
}

2. 参数化策略

通过 Constraint 的 spec.parameters 字段,我们可以让同一个 ConstraintTemplate 在不同场景下有不同的行为:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
  name: require-team-label
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Namespace"]
  parameters:
    labels:
      - key: "team"
        allowedRegex: "^(platform|infra|product|data)$"
      - key: "environment"
        allowedRegex: "^(dev|staging|prod)$"

3. 多种执行动作

Gatekeeper 3.11+ 支持

1
enforcementAction

字段,允许策略以不同的方式执行:

Action 行为 适用场景
1
deny
直接拒绝违反策略的请求 严格的安全策略
1
dryrun
允许请求但记录违规 新策略试运行、灰度发布
1
warn
允许请求但返回警告信息 非强制性的最佳实践建议

1
2
3
4
5
6
7
8
9
10
11
12
13
# 使用 dryrun 模式测试新策略
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sBlockHostNetwork
metadata:
  name: block-host-network-dryrun
spec:
  enforcementAction: dryrun  # 先观察,不拦截
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
  parameters:
    blockHostNetwork: true

自动化策略治理流程

生产环境最佳实践

策略组织结构

在我们管理多个 Kubernetes 集群的经验中,以下策略组织方式被证明是行之有效的:

  • 安全基线(Security Baseline):禁止特权容器、禁止 hostNetwork、禁止 hostPID、禁止挂载敏感路径
  • 运维规范(Operational Standards):要求设置资源限制、要求配置健康检查、禁止使用 latest 标签
  • 合规要求(Compliance):要求携带特定标签(如 cost-center、owner)、限制命名空间命名规则
  • 多租户隔离(Multi-tenancy):限制跨命名空间的访问、限制可使用的 StorageClass、限制可使用的 Ingress 域名

逐步推行策略

直接在生产集群上执行

1
deny

模式的新策略可能会造成事故。推荐的推行流程是:

  1. Audit Only 阶段:先部署策略,观察审计结果,了解集群中现有的违规情况
  2. Dryrun 阶段:收集违规数据,与团队沟通,制定整改计划
  3. Warn 阶段:用户创建资源时会看到警告,但不会被阻止;给团队一个缓冲期去修复
  4. Deny 阶段:正式生效,拒绝所有违反策略的资源创建请求

Gatekeeper 的

1
--disable-validating-webhook

启动参数可以在排查问题时临时关闭准入拦截,只保留审计功能:


1
2
3
4
# 临时只开启审计,关闭准入拦截
kubectl patch validatingwebhookconfiguration gatekeeper-validating-webhook \
  -p '{"webhooks":[{"name":"validation.gatekeeper.sh","clientConfig":{"caBundle":""}}]}' \
  --type=merge

监控与告警

将 Gatekeeper 的审计指标接入 Prometheus:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Gatekeeper 默认暴露 metrics 端点
# 在 Prometheus 中配置 scrape
- job_name: 'gatekeeper'
  kubernetes_sd_configs:
    - role: endpoints
  relabel_configs:
    - source_labels: [__meta_kubernetes_service_name]
      regex: gatekeeper-controller-manager-metrics
      action: keep

# 常用告警规则示例
groups:
  - name: gatekeeper-alerts
    rules:
      - alert: GatekeeperAuditViolations
        expr: gatekeeper_constraints_violations > 0
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Gatekeeper 检测到策略违规"
          description: "有 {{ $value }} 个资源违反了集群策略"

OPA/Gatekeeper vs 其他策略方案

方案 策略语言 运行时 审计能力 适用场景
OPA/Gatekeeper Rego 准入 Webhook 内置审计引擎 通用策略引擎,K8s 原生
Kyverno YAML DSL 准入 Webhook 内置审计 + 报告 K8s 专属,学习成本低
Kubewarden WASM(多种语言) 准入 Webhook 需额外配置 高性能,多语言编写策略
内置 Admission Plugins YAML 配置 API Server 内置 无审计 简单场景,无需额外部署

选择哪种方案取决于你的团队背景和需求。如果你的团队对 Rego 不熟悉,Kyverno 的纯 YAML 风格可能更适合;如果你需要跨平台(K8s、Terraform、微服务)的统一策略引擎,OPA 是唯一的选择;如果你追求极致性能,Kubewarden 的 WASM 方案值得关注。

常见问题与排错

Gatekeeper 自己被打倒了怎么办?

这是一个经典的”鸡生蛋蛋生鸡”问题——Gatekeeper 的 ValidatingWebhookConfiguration 会拦截所有资源的创建,包括它自己。如果配置错误,可能导致整个集群的 API 调用被阻塞。解决方案是预先创建一个 ClusterRole 和 ClusterRoleBinding,允许

1
system:gatekeeper

用户绕过 Webhook:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: gatekeeper-emergency-override
rules:
  - apiGroups: ["*"]
    resources: ["*"]
    verbs: ["*"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: gatekeeper-emergency-override
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
  - kind: User
    name: system:gatekeeper
    apiGroup: rbac.authorization.k8s.io

Rego 调试技巧

Rego 的调试可以借助 OPA 的 REPL 工具:


1
2
3
4
5
6
7
8
9
# 安装 opa 命令行工具
curl -L -o /usr/local/bin/opa https://openpolicyagent.org/downloads/latest/opa_linux_amd64
chmod +x /usr/local/bin/opa

# 使用 REPL 交互式调试
opa run

# 加载策略文件后测试
> data.k8srequiredresources.violation with input as {"review": {"object": {"spec": {"containers": [{"name": "test", "image": "nginx:latest"}]}}}}}

总结

OPA 和 Gatekeeper 为 Kubernetes 集群提供了强大的策略治理能力,让安全团队和平台团队能够用代码定义规则,自动执行合规检查,而无需依赖人工审核流程。通过本文,你应该已经掌握了:

  • OPA 和 Gatekeeper 的核心架构与工作原理
  • 如何使用 Rego 语言编写策略
  • 如何通过 ConstraintTemplate 和 Constraint 模型部署策略
  • Gatekeeper 的审计机制和多种执行动作
  • 生产环境推行的最佳实践和排错方法

Policy-as-Code 不仅是技术工具的选择,更是一种运维文化的转变——从”人治”到”代码治”,从”事后追责”到”事前拦截”。在云原生基础设施日益复杂的今天,这无疑是保障集群安全与合规的必由之路。

如果你想深入了解更多关于 OPA 和 Rego 的高级用法,推荐阅读 OPA 官方文档 和 Gatekeeper 的 Github 仓库

【本站文章皆为原创,未经允许不得转载】:汤不热吧 » Kubernetes OPA/Gatekeeper 实战指南:用 Policy-as-Code 实现集群安全策略的自动化治理
分享到: 更多 (0)