编写限制条件模板

本主题说明如何编写自定义限制条件模板并使用它扩展政策控制器

概览

限制条件模板可用于扩展政策控制器。如果找不到适合您需要的预写模板,则可以编写自己的模板。

使用 OPA 限制框架描述政策控制器政策,并使用 Rego 编写。政策可以评估 Kubernetes 对象的任何字段。

使用 Rego 编写政策是一项专门技能。因此,默认情况下会安装常见限制条件模板库。创建限制条件时,大多数用户可以调用这些限制条件模板。如果您有特殊需要,则可以创建您自己的限制条件模板。

限制条件模板使您可以将政策的逻辑与其特定要求分开,以进行重复使用和委任。您可以使用第三方(例如,开源项目,软件供应商或监管专家)开发的限制条件模板来创建限制条件。

准备工作

限制条件模板示例

以下是限制条件模板示例,该模板拒绝其名称与限制条件创建者提供的值匹配的所有资源。本页面的其余部分将讨论模板的内容,并重点介绍其中的重要概念。

限制条件模板

apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
  name: k8sdenyname
spec:
  crd:
    spec:
      names:
        kind: K8sDenyName
      validation:
        # Schema for the `parameters` field
        openAPIV3Schema:
          properties:
            invalidName:
              type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8sdenynames
        violation[{"msg": msg}] {
          input.review.object.metadata.name == input.parameters.invalidName
          msg := sprintf("The name %v is not allowed", [input.parameters.invalidName])
        }

限制

这是一个限制条件示例,用户可能实施该限制条件以拒绝所有名为“policy-violation”的资源:

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sDenyName
metadata:
  name: no-policy-violation
spec:
  parameters:
    invalidName: "policy-violation"

限制条件模板的组成部分

限制条件模板有两个重要部分:

  • 您希望用户创建的限制条件的架构。限制条件模板的架构存储在 crd 字段中。

  • 评估限制条件时执行的 Rego 源代码。模板的 Rego 源代码存储在 targets 字段中。

CRD 字段

CRD 字段是用于创建 Kubernetes 自定义资源定义的蓝图,该定义定义了 Kubernetes API 服务器的限制条件资源。您只需要填充以下字段:

  • spec.crd.spec.names.kind 是限制条件的种类。小写时,此字段的值必须等于 metadata.name
  • spec.crd.spec.validation.openAPIV3Schema 是限制条件资源的 spec.parameters 字段的架构(限制条件的其余架构由 Anthos Config Management 自动定义)。它遵循与常规 CRD 资源相同的规则。此处记录了该定义。

为限制条件模板添加名称“K8s”前缀是一种规则,该规则使我们能够避免与其他种类的限制条件模板(例如,针对 GCP 资源的 Forseti 模板)发生冲突。

Rego 源代码

位置

Rego 源代码存储在 spec.targets 字段下,其中 targets 是格式为 {"target": "admission.k8s.gatekeeper.sh", "rego": <REGO SOURCE CODE>, "libs": <LIST OF REGO LIBRARIES>} 的对象数组。当前,targets 中仅允许一个条目。

  • target 告诉 Anthos Config Management 我们正在看什么系统(在本例中为 Kubernetes)
  • rego 是限制条件的源代码
  • libs 是可用于限制条件模板的 Rego 代码库的可选列表。它旨在简化共享库的使用,并且不在本教程的讨论范围之内。

源代码

让我们来看一下上述限制条件的 Rego:

package k8sdenynames

violation[{"msg": msg}] {
   input.review.object.metadata.name == input.parameters.invalidName
   msg := sprintf("The name %v is not allowed", [input.parameters.invalidName])
}

这里有一些注意事项:

  • OPA(Rego 的运行时环境)需要 package k8sdenynames。该值被忽略。
  • 政策控制器调用以查看是否存在任何违规的 Rego 规则称为 violation。如果此规则匹配,则发生违反限制条件的情况。
  • violation 规则具有签名 violation[{"msg": "violation message for the user"}],其中 "msg" 的值是将返回给用户的违规消息。
  • 提供给限制条件的参数在关键字 input.parameters 下可用。
  • 被测请求存储在关键字 input.review

input.review 具有以下字段:

  • uid 是此特定请求的唯一 ID,在审核期间不可用
  • kind 是被测对象的种类信息。其格式为:
    • kind 资源种类
    • group 资源组
    • version 资源版本
  • name 是资源名称。 如果用户依靠 API 服务器在 CREATE 请求上生成名称,则该字段可能为空。
  • namespace 是资源命名空间(集群范围内的资源未提供)
  • operation 是请求的操作(例如 CREATE 或 UPDATE),在审核期间不可用。
  • userInfo 是发出请求的用户的信息,在审核
      期间不可用
    • username 是发出请求的用户
    • uid 是用户的 UID
    • groups 是用户所属的组的列表
    • extra 是 Kubernetes 提供的任何其他用户信息
  • object 是用户试图修改/创建的对象
  • oldObject 是对象的原始状态,仅在 UPDATE 操作中可用
  • dryRun 是此请求是否由 kubectl --dry-run 调用,在审核期间不可用

编写参照限制条件模板

参照限制条件模板是允许用户相对于其他对象限制一个对象的模板。一个示例可能是,“不允许在已知存在匹配的入口之前创建 pod”。另一个示例可能是,“不允许两个服务具有相同的主机名”。

通过政策控制器,您可以通过查看 API 服务器中用户提供的资源集来编写参照限制条件。修改资源后,政策控制器会将其缓存到本地,以便 Rego 源代码可以轻松地引用它。政策控制器在 data.inventory 关键字下使此缓存可用。

集群范围的资源缓存在以下位置:

data.inventory.cluster[<groupVersion>][<kind>][<name>]

例如,可以在下面找到名为 my-favorite-node 的节点

data.inventory.cluster["v1"]["Node"]["my-favorite-node"]

命名空间范围的资源在此处缓存:

data.inventory.namespace[<namespace>][<groupVersion>][<kind>][<name>]

例如,可以在下面的命名空间 shipping-prod 中找到名为 production-variables 的 ConfigMap。

data.inventory.namespace["shipping-prod"]["v1"]["ConfigMap"]["production-variables"]

对象的全部内容存储在此缓存位置,如果您认为合适,可以在 Rego 中引用。

关于 Rego 的更多信息

以上信息提供了政策控制器的独特功能,这些功能使在 Rego 中轻松编写关于 Kubernetes 资源的限制条件成为可能。有关如何在 Rego 中进行编写的完整教程不在本指南范围之内。但是,Open Policy Agent 网站具有有关 Rego 语言本身的语法和功能的文档

安装限制条件模板

创建限制条件模板后,只需对它进行 kubectl apply 处理,政策控制器将负责接收它。确保检查限制条件模板的 status 字段,以确保实例化没有错误。成功提取后,status 字段应显示 created: true,并且 status 字段中记录的 observedGeneration 应该等于 metadata.generation 字段。

提取模板后,您可以按照创建限制条件中的说明对其应用限制条件。

删除限制条件模板

首先,确认没有要保留的限制条件正在使用限制条件模板:

kubectl get [TEMPLATE-NAME]

如果限制条件模板的名称与集群中的其他对象之间的命名冲突,则可以改用以下命令:

kubectl get [TEMPLATE-NAME].constraints.gatekeeper.sh

删除限制条件模板:

kubectl delete constrainttemplate [CONSTRAINT-TEMPLATE-NAME]

删除限制条件模板后,将无法再创建引用它的限制条件。

后续步骤