本页面介绍了如果您找不到适合您的需求的预先写好的限制条件模板,可以如何编写自定义限制条件模板,以及如何使用该模板扩展政策控制器。
本页面适用于想要提供并维护自动化以进行审核或强制执行,并使用声明式配置模板,从而确保云平台中运行的所有资源满足组织合规性要求的 IT 管理员和运维人员。如需详细了解我们在 Google Cloud 内容中提及的常见角色和示例任务,请参阅常见的 GKE Enterprise 用户角色和任务。
Policy Controller 政策使用 OPA 限制条件框架进行描述,并采用 Rego 进行编写。政策可以评估 Kubernetes 对象的任何字段。
使用 Rego 编写政策是一项专门技能。因此,默认情况下,系统会安装常见限制条件模板库。创建限制条件时,您可能可调用这些限制条件模板。如果您有特殊需要,则可以创建您自己的限制条件模板。
通过限制条件模板,您可以将政策逻辑与其特定要求分离,以进行重复使用和委任。您可以使用第三方开发的限制条件模板(如开源项目、软件供应商或监管专家)来创建限制条件。
准备工作
限制条件模板示例
以下是一个限制条件模板示例,该模板拒绝名称与限制条件创建者提供的值匹配的所有资源。本页的其余部分讨论了模板的内容,并在此过程中突出显示一些重要概念。
如果您将 Config Sync 与分层代码库搭配使用,我们建议您在 cluster/
目录中创建自己的限制条件。
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 |
限制条件资源的 |
将限制条件模板前缀命名为 K8s
是一种惯例,以避免与其他其他类型的限制条件模板发生冲突,例如定位 Google Cloud 资源的 Forseti 模板。
Rego 源代码(targets
字段)
以下部分详细介绍了 Rego 源代码。
位置
Rego 源代码存储在 spec.targets
字段下,其中 targets
是采用以下格式的对象的数组:
{"target": "admission.k8s.gatekeeper.sh","rego": REGO_SOURCE_CODE, "libs": LIST_OF_REGO_LIBRARIES}
target
:告知 Policy Controller 我们正在查看的系统(在本例中为 Kubernetes);targets
中只允许有一个条目。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
。系统会忽略该值。 - Policy Controller 调用来查看是否存在任何违规行为的 Rego 规则称为
violation
。如果此规则匹配,则发生违反限制条件的情况。 violation
规则具有签名violation[{"msg": "violation message for the user"}]
,其中"msg"
是返回给用户的违规消息。- 提供给限制条件的参数在关键字
input.parameters
下可用。 request-under-test
存储在关键字input.review
下。
关键字 input.review
包含以下字段。
字段 | 说明 |
---|---|
uid |
特定请求的唯一 ID;它在审核期间无法使用。 |
kind |
|
name |
资源名称。 如果用户依赖 API 服务器在 CREATE 请求上生成名称,则资源名称可能会为空。 |
namespace |
资源命名空间(不适用于集群范围内的资源)。 |
operation |
所请求的操作(例如,CREATE 或 UPDATE)在审核期间不可用。 |
userInfo |
发出请求的用户信息在审核期间不可用。其格式如下:
|
object |
用户尝试修改或创建的对象。 |
oldObject |
对象的原始状态;它仅适用于 UPDATE 操作。 |
dryRun |
不论此请求是否由 kubectl --dry-run 调用;其在审核期间都不可用。 |
编写参照限制条件模板
参照限制条件模板是允许用户将一个对象相对于其他对象进行限制的模板。此模板的一个示例可能是,“不允许在已知存在匹配的入口之前创建 Pod”。另一个示例可能是,“不允许两个服务具有相同的主机名”。
借助 Policy Controller,您可以通过查看 API 服务器中用户提供的一组资源来编写参照限制条件。修改资源后,Policy Controller 会将其缓存到本地,以便 Rego 源代码可以轻松地引用它。Policy Controller 在 data.inventory
关键字下使此缓存可用。
集群范围的资源缓存在以下位置:
data.inventory.cluster["GROUP_VERSION"]["KIND"]["NAME"]
例如,可在以下位置找到名为 my-favorite-node
的节点:
data.inventory.cluster["v1"]["Node"]["my-favorite-node"]
命名空间范围的资源在此处缓存:
data.inventory.namespace["NAMESPACE"]["GROUP_VERSION"]["KIND"]["NAME"]
例如,可以在下面的命名空间 shipping-prod
中找到名为 production-variables
的 ConfigMap。
data.inventory.namespace["shipping-prod"]["v1"]["ConfigMap"]["production-variables"]
对象的全部内容存储在此缓存位置,如果您认为合适,可以在 Rego 源代码中引用。
有关 Rego 的更多信息
上述信息提供了 Policy Controller 的独特功能,让您能够轻松地采用 Rego 编写对 Kubernetes 资源的限制条件。有关如何采用 Rego 编写限制条件的完整教程不在本教程的讨论范围内。但是,Open Policy Agent 的文档包含有关 Rego 语言本身的语法和功能的信息。
安装限制条件模板
创建限制条件模板后,使用 kubectl apply
应用该模板,且 Policy Controller 负责提取它。请务必检查限制条件模板的 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
删除限制条件模板后,将无法再创建引用它的限制条件。
后续步骤
- 详细了解政策控制器。
- 查看限制条件模板库参考文档。
- 了解如何使用限制条件代替 PodSecurityPolicies。