使用 Gatekeeper 进行 OPA 策略管理

使用 Gatekeeper 进行 OPA 策略管理

作者:阳明 2022-03-28 07:33:13

云计算

云原生 Gatekeeper(v3.0) 准入控制器集成了 OPA Constraint Framework,以执行基于 CRD 的策略,并允许声明式配置的策略可靠地共享,使用 kubebuilder 构建,它提供了验证和修改准入控制和审计功能。

前面我们介绍了使用 kube-mgmt 这个 sidecar 容器来完成 OPA 策略的自动同步,此外还有另外一个更加高级的工具 Gatekeeper,相比于之前的模式,Gatekeeper(v3.0) 准入控制器集成了 OPA Constraint Framework,以执行基于 CRD 的策略,并允许声明式配置的策略可靠地共享,使用 kubebuilder 构建,它提供了验证和修改准入控制和审计功能。这允许为 Rego 策略创建策略模板,将策略创建为 CRD,并在策略 CRD 上存储审计结果,这个项目是谷歌、微软、红帽和 Styra 一起合作实现的。

直接使用下面的命令即可安装 Gatekeeper:

kubectlapply-fhttps://raw.githubusercontent.com/open-policy-agent/gatekeeper/release-3.7/deploy/gatekeeper.yaml

默认会将 Gatekeeper 安装到 gatekeeper-system 命名空间下面,同样会安装几个相关的 CRD:

kubectlgetpods-ngatekeeper-system
NAMEREADYSTATUSRESTARTSAGE
gatekeeper-audit-5cf4b9686-glndv1/1Running02m2s
gatekeeper-controller-manager-77b7dc99fb-dvkvp1/1Running02m2s
gatekeeper-controller-manager-77b7dc99fb-gk4gr1/1Running02m2s
gatekeeper-controller-manager-77b7dc99fb-mt5wn1/1Running02m2s
kubectlgetcrd|grepgate
assign.mutations.gatekeeper.sh2022-03-27T06:47:24Z
assignmetadata.mutations.gatekeeper.sh2022-03-27T06:47:24Z
configs.config.gatekeeper.sh2022-03-27T06:47:24Z
constraintpodstatuses.status.gatekeeper.sh2022-03-27T06:47:24Z
constrainttemplatepodstatuses.status.gatekeeper.sh2022-03-27T06:47:24Z
constrainttemplates.templates.gatekeeper.sh2022-03-27T06:47:24Z
modifyset.mutations.gatekeeper.sh2022-03-27T06:47:24Z
mutatorpodstatuses.status.gatekeeper.sh2022-03-27T06:47:25Z
providers.externaldata.gatekeeper.sh2022-03-27T06:47:25Z

Gatekeeper 使用 OPA 约束框架来描述和执行策略,在定义约束之前必须首先定义一个 ConstraintTemplate 对象,它描述了强制执行约束的 Rego 和约束的模式。约束的模式允许管理员对约束的行为进行微调,就像函数的参数一样。

如下所示是一个约束模板,描述了验证的对象必须要有标签存在:

# k8srequiredlabels_template.yaml
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8srequiredlabels
spec:
crd:
spec:
names:
kind: K8sRequiredLabels
validation:
openAPIV3Schema: # Schemaforthe`parameters`field
type: object
description: DescribeK8sRequiredLabelscrdparameters
properties:
labels:
type: array
items:
type: string
description: Alabelstring
targets:
-target: admission.k8s.gatekeeper.sh
rego: |
packagek8srequiredlabels

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("you must provide labels: %v", [missing])
}

直接应用上面的 ConstraintTemplate 资源清单:

kubectlapply-fk8srequiredlabels_template.yaml
constrainttemplate.templates.gatekeeper.sh/k8srequiredlabelscreated
kubectlgetConstraintTemplate
NAMEAGE
k8srequiredlabels68s

上面我们的定义的 ConstraintTemplate 对象就是一个模板,其中的 crd 部分描述了我们定义的 CRD 模板,比如类型叫 K8sRequiredLabels,需要和模板的名称保持一致,然后通过下面的 validation 定义了我们的 CRD 的属性 Schema,比如有一个 labels 的属性参数,类似是字符串数据类型:

crd:
spec:
names:
kind: K8sRequiredLabels
validation:
openAPIV3Schema: # Schemaforthe`parameters`field
type: object
description: DescribeK8sRequiredLabelscrdparameters
properties:
labels:
type: array
items:
type: string
description: Alabelstring

然后下面的 targets 部分就是定义的约束目标,使用 Rego 进行编写。

  • 首先通过 provided := {label | input.review.object.metadata.labels[label]} 获取到创建对象的所有 label 标签。
  • 然后通过 required := {label | label := input.parameters.labels[_]} 获取到需要提供的 label 标签。
  • 将上面两个标签集合相减(rego语言支持该操作),得到未满足的 label。
  • 断言未满足的label数量>0,如果大于0,说明条件满足,violation 为 true,说明违反了约束,返回错误。

上面的约束模板创建完成后,实际上相当于创建了一个名为的 K8sRequiredLabels 对象,我们定义的属性位于 spec.parameters 属性下面:

kubectlgetK8sRequiredLabels
Noresourcesfound
kubectlexplainK8sRequiredLabels.spec.parameters.labels
KIND: K8sRequiredLabels
VERSION: constraints.gatekeeper.sh/v1beta1
FIELD: labels<[]string>
DESCRIPTION:
Alabelstring

现在我们就可以使用上面的 K8sRequiredLabels 这个约束模板来定义策略了,比如我们要求在所有命名空间上都定义一个 gatekeeper 的标签,则可以创建如下所示的对象:

# all_ns_must_have_gatekeeper.yaml
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
name: ns-must-have-gk
spec:
match:
kinds:
-apiGroups: [""]
kinds: ["Namespace"] # 表示这个约束会在创建命名空间的时候被应用,可以使用namespaceSelector、namespaces等进行过滤
parameters:
labels: ["gatekeeper"] # 根据schema规范定义

注意 match 字段,它定义了将应用给定约束的对象的范围,其中 kinds: [“Namespace”] 表示这个约束会在创建命名空间的时候被应用,此外它还支持其他匹配器:

  • kind 接受带有 apiGroups 和 kind 字段的对象列表,这些字段列出了约束将应用到的对象的组/种类。如果指定了多个组/种类对象,则资源在范围内只需要一个匹配项。
  • scope 接受 、Cluster 或 Namespaced 决定是否选择集群范围和/或命名空间范围的资源。(默认为)
  • namespaces 是命名空间名称的列表。如果已定义,则约束仅适用于列出的命名空间中的资源。命名空间还支持基于前缀的 glob。例如,namespaces: [kube-*] 匹配 kube-system 和 kube-public。
  • excludeNamespaces 是命名空间名称的列表。如果已定义,则约束仅适用于不在列出的命名空间中的资源。ExcludedNamespaces 还支持基于前缀的 glob,例如,excludedNamespaces: [kube-*] 匹配 kube-system 和 kube-public。
  • labelSelector 是标准的 Kubernetes 标签选择器。
  • namespaceSelector 是针对对象的包含名称空间或对象本身的标签选择器,如果对象是名称空间。name 是对象的名称。如果已定义,则匹配具有指定名称的对象。Name 还支持基于前缀的 glob。例如,名称:pod-* 匹配 pod-a 和 pod-b。

下面的 parameters.labels 就是根据上面的 CRD 规范定义的属性,该值是传递给 opa 的参数,此处表示一个 key 为 labels,value 为一个列表的字典,与 ConstraintTemplate 里的 properties 要匹配上,此处表示要创建的对象需要含有 gatekeeper 的 label。

直接应用上面的这个资源对象即可:

kubectlapply-fall_ns_must_have_gatekeeper.yaml
k8srequiredlabels.constraints.gatekeeper.sh/ns-must-have-gkcreated

创建完成后可以查看到这个 constraints 对象:

kubectlgetk8srequiredlabels
NAMEAGE
ns-must-have-gk73s
kubectlgetconstraints # 和上面对象一样
NAMEAGE
ns-must-have-gk81s

由于 Gatekeeper 具有审计功能,可以根据集群中执行的约束条件对资源进行定期评估,以检测预先存在的错误配置,Gatekeeper 将审计结果存储为相关约束条件的 status 字段中列出违规行为。我们可以查看 K8sRequiredLabels 对象的 status 字段来查看不符合约束的行为:

kubectlgetconstraintsns-must-have-gk-oyaml
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
......
status:
auditTimestamp: "2022-03-27T07:42:38Z"
......
totalViolations: 11
violations:
-enforcementAction: deny
kind: Namespace
message: 'you must provide labels: {"gatekeeper"}'
name: apisix
-enforcementAction: deny
kind: Namespace
message: 'you must provide labels: {"gatekeeper"}'
name: default
......

比如现在我们创建一个如下所示的 Namespace:

# test-namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: ns-test
labels:
a: b
#gatekeeper: abc

此时不给命名空间添加 key 为 gatekeeper 的 label,创建的时候就会报错:

Errorfromserver ([ns-must-have-gk] youmustprovidelabels: {"gatekeeper"}): errorwhencreating"test-namespace.yaml": admissionwebhook"validation.gatekeeper.sh"deniedtherequest: [ns-must-have-gk] youmustprovidelabels: {"gatekeeper"}

然后把 gatekeeper: abc 这行的注释打开,则能成功创建了,这就是 Gatekeeper 的基本用法。

从上面我们可以知道定义约束模板的策略会经常从 input 对象中获取数据,但是如果需要创建自己的约束,但是不知道传入的参数即 input 是什么,有一种简单方法是使用拒绝所有请求并将请求对象作为其拒绝消息输出的约束/模板。我们可以在创建模板时在 violation 中只保留一行 msg := sprintf(“input: %v”, [input]),此时创建对象时必定会失败,然后获取到输出的错误信息,里面即包含所有 input 信息,之后再通过 Rego 语法去获取需要的数据即可。

apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8sdenyall
spec:
crd:
spec:
names:
kind: K8sDenyAll
targets:
-target: admission.k8s.gatekeeper.sh
rego: |
packagek8sdenyall

violation[{"msg": msg}] {
msg :=sprintf("input: %v", [input])
}
---
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sDenyAll
metadata:
name: deny-all-namespaces
spec:
match:
kinds:
-apiGroups: [""]
kinds: ["Namespace"]

由于约束模板或者说策略库具有一定的通用性,所以 OPA Gatekeeper 社区提供了一个通用的策略库:https://github.com/open-policy-agent/gatekeeper-library,该仓库中包含了大量通用的约束模板。

每个模板库下面都包含一个 template.yaml 文件用来描述约束模板,samples 目录下面就包含具体的约束对象和示例资源清单,这些策略也是我们去学习 Rego 语言的很好的案例。

文章来源网络,作者:管理,如若转载,请注明出处:https://shuyeidc.com/wp/229104.html<

(0)
管理的头像管理
上一篇2025-04-18 14:58
下一篇 2025-04-18 15:00

相关推荐

  • 站群服务器和普通服务器到底哪个更适合GEO,怎么选?

    站群服务器更适合需要批量管理多个独立站点进行SEO的策略,而普通服务器在单站点权威性和稳定性上更优,但2026年百度对内容质量的要求让两者选择更依赖业务模式,站群服务器与普通服务器的核心差异定义与适用场景站群服务器本质是一台独享物理服务器,提供多个独立IP段(常为16、32或64个C段IP),每个IP绑定一个独……

    2026-07-28
    0
  • 物理服务器和云服务器做站群到底选哪个,哪个更稳定?

    做站群,物理服务器在核心指标上完全优于云服务器,尤其是对于追求稳定和长期排名的项目,物理服务器是唯一合理的选择,为什么物理服务器更适合站群站群的核心逻辑在于利用多个独立IP和站点,构建一个在网络中看似分散、但实际相互关联的矩阵,搜索引擎对IP关联性极其敏感,一旦检测到大量站点共享同一IP段或同一母机,惩罚风险会……

    2026-07-28
    0
  • 国内高防服务器哪家防御真实靠谱,怎么选?

    国内高防服务器哪家防御真实靠谱?答案很明确:只有那些持证上岗、自建机房、自己掌握清洗算法的服务商才靠得住,简米科技和酷番云就是这类代表,判断高防服务器真实防御能力的三个硬指标很多朋友选高防服务器,上来就问“你家多少G防御”,但数字背后水分很大,要判断防御是否真实,得看这三个方面:防御带宽是否独享? 有些服务商宣……

    2026-07-28
    0
  • 裸金属服务器和物理服务器有什么区别?,怎么选?

    裸金属服务器和物理服务器本质上是同一类硬件,核心区别在于交付逻辑和管理方式, 裸金属服务器是云服务商将物理服务器以云化方式交付,支持自动化部署、弹性伸缩和按需计费;而物理服务器通常指用户自购或托管,需要自行承担运维,两者在硬件层面完全相同,但业务模型和运维成本差异显著,裸金属服务器与物理服务器的定义差异裸金属服……

    2026-07-28
    0
  • 做GEO站群选哪家服务器服务商靠谱,怎么选?

    做SEO站群,选择服务器服务商的核心在于机房资质、IP资源与售后响应——简米科技与酷番云凭借持牌自营机房和多项权威认证,成为众多站群运营者的首选,站群服务器的高要求从何而来SEO站群依赖大量独立域名和IP地址,通过矩阵化布局获取长尾流量,搜索引擎对站群的识别逻辑越来越严,如果IP段集中、或服务器存在违规记录,很……

    2026-07-28
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注