# Implementing Opa Gatekeeper For Policy Enforcement

> 使用 OPA Gatekeeper 通过 ConstraintTemplate、Rego 规则和 Gatekeeper 策略库强制执行 Kubernetes 准入策略。

- Skill: `killvxk/implementing-opa-gatekeeper-for-policy-enforcement` (Agent Skill, multi-file: 8 files)
- Install (CLI): `npx skillmds@latest add killvxk/implementing-opa-gatekeeper-for-policy-enforcement`
- Raw SKILL.md: https://api.skillmd.com/api/skills/killvxk/implementing-opa-gatekeeper-for-policy-enforcement/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- License: Apache-2.0
- Author: killvxk (https://skillmd.com/u/killvxk)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/killvxk/implementing-opa-gatekeeper-for-policy-enforcement

---


# 使用 OPA Gatekeeper 实施策略强制执行

## 概述

OPA Gatekeeper 是一个 Kubernetes 准入控制器，用于强制执行用 Rego 语言编写的策略。它使用 ConstraintTemplate（包含 Rego 逻辑的策略蓝图）和 Constraint（带参数的实例化策略）在准入时验证、变更或拒绝 Kubernetes 资源请求。

## 前置条件

- Kubernetes 集群 v1.24+
- Helm 3
- 具有 cluster-admin 权限的 kubectl
- 熟悉 Rego 策略语言

## 安装 Gatekeeper

```bash
# 通过 Helm 安装
helm repo add gatekeeper https://open-policy-agent.github.io/gatekeeper/charts
helm repo update

helm install gatekeeper gatekeeper/gatekeeper \
  --namespace gatekeeper-system --create-namespace \
  --set replicas=3 \
  --set audit.replicas=1 \
  --set audit.logLevel=INFO

# 验证安装
kubectl get pods -n gatekeeper-system
kubectl get crd | grep gatekeeper
```

### 验证安装

```bash
# 检查 Webhook
kubectl get validatingwebhookconfigurations gatekeeper-validating-webhook-configuration

# 检查 CRD
kubectl get crd constrainttemplates.templates.gatekeeper.sh
kubectl get crd configs.config.gatekeeper.sh
```

## ConstraintTemplate 示例

### 1. 要求资源包含 Label

```yaml
# template-required-labels.yaml
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: k8srequiredlabels
spec:
  crd:
    spec:
      names:
        kind: K8sRequiredLabels
      validation:
        openAPIV3Schema:
          type: object
          properties:
            labels:
              type: array
              items:
                type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8srequiredlabels

        violation[{"msg": msg, "details": {"missing_labels": missing}}] {
          provided := {label | input.review.object.metadata.labels[label]}
          required := {label | label := input.parameters.labels[_]}
          missing := required - provided
          count(missing) > 0
          msg := sprintf("缺少必需的 Label：%v", [missing])
        }
```

```yaml
# constraint-require-team-label.yaml
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
  name: require-team-label
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Namespace"]
      - apiGroups: ["apps"]
        kinds: ["Deployment"]
  parameters:
    labels:
      - "team"
      - "environment"
```

### 2. 阻断特权容器

```yaml
# template-block-privileged.yaml
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: k8sblockprivileged
spec:
  crd:
    spec:
      names:
        kind: K8sBlockPrivileged
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8sblockprivileged

        violation[{"msg": msg}] {
          container := input.review.object.spec.containers[_]
          container.securityContext.privileged == true
          msg := sprintf("不允许特权容器：%v", [container.name])
        }

        violation[{"msg": msg}] {
          container := input.review.object.spec.initContainers[_]
          container.securityContext.privileged == true
          msg := sprintf("不允许特权初始化容器：%v", [container.name])
        }
```

```yaml
# constraint-block-privileged.yaml
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sBlockPrivileged
metadata:
  name: block-privileged-containers
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
    namespaces:
      - "production"
      - "staging"
```

### 3. 限制容器镜像仓库

```yaml
# template-allowed-repos.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 image_matches(container.image)
          msg := sprintf("容器镜像 %v 不来自允许的仓库。允许的仓库：%v", [container.image, input.parameters.repos])
        }

        violation[{"msg": msg}] {
          container := input.review.object.spec.initContainers[_]
          not image_matches(container.image)
          msg := sprintf("初始化容器镜像 %v 不来自允许的仓库。允许的仓库：%v", [container.image, input.parameters.repos])
        }

        image_matches(image) {
          repo := input.parameters.repos[_]
          startswith(image, repo)
        }
```

```yaml
# constraint-allowed-repos.yaml
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sAllowedRepos
metadata:
  name: restrict-image-repos
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
  parameters:
    repos:
      - "gcr.io/my-project/"
      - "ghcr.io/my-org/"
      - "registry.k8s.io/"
```

### 4. 强制资源限制

```yaml
# template-require-limits.yaml
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: k8srequirelimits
spec:
  crd:
    spec:
      names:
        kind: K8sRequireLimits
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8srequirelimits

        violation[{"msg": msg}] {
          container := input.review.object.spec.containers[_]
          not container.resources.limits.cpu
          msg := sprintf("容器 %v 未设置 CPU 限制", [container.name])
        }

        violation[{"msg": msg}] {
          container := input.review.object.spec.containers[_]
          not container.resources.limits.memory
          msg := sprintf("容器 %v 未设置内存限制", [container.name])
        }
```

### 5. 阻断 latest 镜像标签

```yaml
# template-block-latest-tag.yaml
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: k8sblocklatesttag
spec:
  crd:
    spec:
      names:
        kind: K8sBlockLatestTag
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8sblocklatesttag

        violation[{"msg": msg}] {
          container := input.review.object.spec.containers[_]
          endswith(container.image, ":latest")
          msg := sprintf("容器 %v 使用了 ':latest' 标签，请使用具体版本标签。", [container.name])
        }

        violation[{"msg": msg}] {
          container := input.review.object.spec.containers[_]
          not contains(container.image, ":")
          msg := sprintf("容器 %v 未指定标签（默认为 latest），请使用具体版本标签。", [container.name])
        }
```

### 6. 强制只读根文件系统

```yaml
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: k8sreadonlyroot
spec:
  crd:
    spec:
      names:
        kind: K8sReadOnlyRoot
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8sreadonlyroot

        violation[{"msg": msg}] {
          container := input.review.object.spec.containers[_]
          not container.securityContext.readOnlyRootFilesystem
          msg := sprintf("容器 %v 必须将 readOnlyRootFilesystem 设置为 true", [container.name])
        }
```

## 审计与强制执行模式

```yaml
# 演练模式（仅审计，不阻断）
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sBlockPrivileged
metadata:
  name: block-privileged-dryrun
spec:
  enforcementAction: dryrun   # dryrun | deny | warn
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
```

### 检查审计违规

```bash
# 列出所有约束违规
kubectl get k8sblockprivileged block-privileged-containers -o yaml | grep -A 20 violations

# 检查所有约束的审计状态
kubectl get constraints -o json | jq '.items[] | {name: .metadata.name, violations: (.status.violations // [] | length)}'
```

## Gatekeeper 配置（豁免命名空间）

```yaml
apiVersion: config.gatekeeper.sh/v1alpha1
kind: Config
metadata:
  name: config
  namespace: gatekeeper-system
spec:
  match:
    - excludedNamespaces:
        - kube-system
        - gatekeeper-system
        - calico-system
      processes:
        - "*"
```

## 监控

```bash
# 检查 Gatekeeper 指标
kubectl port-forward -n gatekeeper-system svc/gatekeeper-webhook-service 8443:443

# Prometheus 指标
kubectl get --raw /metrics | grep gatekeeper
```

## 最佳实践

1. **从演练模式开始** - 先以 `dryrun` 模式部署约束，审查违规后再切换为 `deny`
2. **使用策略库** - 利用 https://github.com/open-policy-agent/gatekeeper-library 中的预置模板
3. **豁免系统命名空间** - 始终排除 kube-system 和 gatekeeper-system
4. **版本控制策略** - 将 ConstraintTemplate 和 Constraint 存入 Git 仓库
5. **监控审计结果** - 定期检查约束的 `.status.violations`
6. **测试 Rego 策略** - 部署前使用 `opa test` 或 Rego Playground 验证
7. **与准入 Webhook 结合** - 将 Gatekeeper 与 Pod Security Admission 分层部署实现纵深防御

