本文发布时间已超过一年。较旧的文章可能包含过时的内容。请检查页面中的信息自发布以来是否已不正确。
OPA Gatekeeper:Kubernetes 的策略和治理
可以利用 Open Policy Agent Gatekeeper 项目来帮助执行策略并加强 Kubernetes 环境中的治理。在这篇文章中,我们将介绍该项目的目标、历史和当前状态。
以下来自 Kubecon EU 2019 会议的录像是在使用 Gatekeeper 时很好的起点。
动机
如果你的组织一直在运行 Kubernetes,你可能一直在寻找控制最终用户在集群上可以做什么的方法,以及确保集群符合公司策略的方法。这些策略可能是为了满足治理和法律要求,或是为了实施最佳实践和组织惯例。有了 Kubernetes,如何在不牺牲开发敏捷性和运营独立性的前提下确保合规性?
例如,你可以强制执行以下策略:
- 所有镜像必须来自批准的存储库
- 所有 Ingress 主机名必须是全局唯一的
- 所有 Pod 必须有资源限制
- 所有命名空间都必须有一个列出联系人的标签
Kubernetes 允许通过 准入控制器 Webhook 将策略决策与 API 服务器分离,以便在它们作为对象持久化到 Kubernetes 中之前拦截准入请求。Gatekeeper 的创建是为了使用户可以通过配置而非代码来定制准入控制,并使他们了解集群的状态,而不仅仅是在准入时正在评估的单个对象。Gatekeeper 是一个用于 Kubernetes 的可定制准入 Webhook,它执行由 Open Policy Agent (OPA) 执行的策略,OPA 是 CNCF 托管的云原生环境的策略引擎。
演变
在我们深入研究 Gatekeeper 的当前状态之前,让我们先看看 Gatekeeper 项目是如何演变的。
- Gatekeeper v1.0 - 使用 OPA 作为准入控制器,kube-mgmt sidecar 执行基于 configmap 的策略。它提供验证和变更准入控制。由 Styra 捐赠。
- Gatekeeper v2.0 - 使用 Kubernetes 策略控制器作为准入控制器,OPA 和 kube-mgmt sidecar 执行基于 configmap 的策略。它提供验证和变更准入控制以及审计功能。由微软捐赠。
- Gatekeeper v3.0 - 准入控制器与 OPA Constraint Framework 集成,以强制执行基于 CRD 的策略,并允许以声明方式配置的策略可以可靠地共享。使用 kubebuilder 构建,它提供验证,并最终提供变更(待实现)准入控制和审计功能。这使得可以为 Rego 策略创建策略模板,创建作为 CRD 的策略,并将审计结果存储在策略 CRD 上。该项目是谷歌、微软、红帽和 Styra 之间的合作项目。
Gatekeeper v3.0 功能
现在让我们仔细看看 Gatekeeper 的当前状态,以及如何利用所有最新的功能。考虑一个组织想要确保集群中的所有对象都包含作为对象标签提供的部门信息。如何使用 Gatekeeper 实现这一点?
验证准入控制
一旦所有 Gatekeeper 组件都安装在你的集群中,每当集群中创建、更新或删除资源时,API 服务器将触发 Gatekeeper 准入 Webhook 以处理准入请求。
在验证过程中,Gatekeeper 充当 API 服务器和 OPA 之间的桥梁。API 服务器将强制执行 OPA 执行的所有策略。
策略和约束
通过集成 OPA Constraint Framework,Constraint 是一个声明,其作者希望系统满足给定的一组要求。每个 Constraint 都是使用 Rego 编写的,Rego 是 OPA 使用的声明式查询语言,用于枚举违反系统预期状态的数据实例。所有 Constraint 都被评估为逻辑 AND。如果一个 Constraint 不满足,则整个请求将被拒绝。
在定义 Constraint 之前,你需要创建一个 Constraint 模板,允许人们声明新的 Constraint。每个模板都描述了强制执行 Constraint 的 Rego 逻辑以及 Constraint 的模式,其中包括 CRD 的模式和可以传递到 Constraint 中的参数,很像函数的参数。
例如,这是一个 Constraint 模板 CRD,它要求在任意对象上存在某些标签。
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
name: k8srequiredlabels
spec:
crd:
spec:
names:
kind: K8sRequiredLabels
listKind: K8sRequiredLabelsList
plural: k8srequiredlabels
singular: k8srequiredlabels
validation:
# Schema for the `parameters` field
openAPIV3Schema:
properties:
labels:
type: array
items: string
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8srequiredlabels
deny[{"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("you must provide labels: %v", [missing])
}
一旦 Constraint 模板已部署在集群中,管理员现在可以创建由 Constraint 模板定义的单个 Constraint CRD。例如,这是一个 Constraint CRD,它要求所有命名空间上都存在标签 hr
。
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
name: ns-must-have-hr
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Namespace"]
parameters:
labels: ["hr"]
类似地,可以轻松地从同一 Constraint 模板创建另一个要求所有命名空间上都存在标签 finance
的 Constraint CRD。
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
name: ns-must-have-finance
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Namespace"]
parameters:
labels: ["finance"]
如你所见,通过 Constraint 框架,我们可以通过 Constraint 模板可靠地共享 Regos,使用 match 字段定义强制执行的范围,并为 Constraint 提供用户定义的参数,以便为每个 Constraint 创建自定义行为。
审计
审计功能可以定期评估复制的资源,以针对集群中强制执行的 Constraint 检测预先存在的不当配置。Gatekeeper 将审计结果存储为相关 Constraint 的 status
字段中列出的 violations
。
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
name: ns-must-have-hr
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Namespace"]
parameters:
labels: ["hr"]
status:
auditTimestamp: "2019-08-06T01:46:13Z"
byPod:
- enforced: true
id: gatekeeper-controller-manager-0
violations:
- enforcementAction: deny
kind: Namespace
message: 'you must provide labels: {"hr"}'
name: default
- enforcementAction: deny
kind: Namespace
message: 'you must provide labels: {"hr"}'
name: gatekeeper-system
- enforcementAction: deny
kind: Namespace
message: 'you must provide labels: {"hr"}'
name: kube-public
- enforcementAction: deny
kind: Namespace
message: 'you must provide labels: {"hr"}'
name: kube-system
数据复制
审计需要在 OPA 中复制 Kubernetes 资源,然后才能根据强制执行的 Constraint 对其进行评估。需要访问集群中除正在评估的对象之外的其他对象的 Constraint 也需要数据复制。例如,强制执行 Ingress 主机名唯一性的 Constraint 必须可以访问集群中的所有其他 Ingress。
要配置要复制的 Kubernetes 数据,请创建一个同步配置资源,其中包含要复制到 OPA 的资源。例如,以下配置将所有命名空间和 Pod 资源复制到 OPA。
apiVersion: config.gatekeeper.sh/v1alpha1
kind: Config
metadata:
name: config
namespace: "gatekeeper-system"
spec:
sync:
syncOnly:
- group: ""
version: "v1"
kind: "Namespace"
- group: ""
version: "v1"
kind: "Pod"
未来计划
Gatekeeper 项目背后的社区将专注于提供变更准入控制以支持变更场景(例如:在创建新资源时自动使用部门信息注释对象),支持外部数据以将集群外部的上下文注入到准入决策中,支持干运行以在强制执行之前查看策略对集群中现有资源的影响,以及更多审计功能。
如果你有兴趣了解更多关于该项目的信息,请查看 Gatekeeper 存储库。如果你有兴趣帮助定义 Gatekeeper 的方向,请加入 OPA Slack 上的 #kubernetes-policy 频道,并加入我们的 每周会议,讨论开发、问题、用例等。