使用 Kyverno Generate 规则
使用 Kyverno generate 规则,在匹配到资源被创建或更新时自动创建 Kubernetes 资源。generate 规则定义了:
- 使用
match 指定要监视的源资源。
- 使用可选的
preconditions 指定哪些变更应触发生成。
- 使用
generate 指定 Kyverno 应创建的目标资源。
- 指定 Kyverno 是否应将生成的资源与源资源保持同步。
本指南以 ConfigMap 更新作为示例工作流。当特定命名空间中的特定 ConfigMap 发生变化时,Kyverno 会创建一个平台 NotificationMessage 资源。随后通知服务会向指定收件人发送电子邮件。
有关上游 Kyverno 参考信息,请参阅官方 Kyverno generate rules 文档。
Generate 的工作方式
Kyverno generate 规则是 ClusterPolicy 或 Policy 的一部分。
rules:
- name: <rule-name>
match:
any:
- resources:
kinds:
- <source-kind>
operations:
- CREATE
- UPDATE
preconditions:
all:
- key: <expression>
operator: <operator>
value: <expression>
generate:
apiVersion: <target-api-version>
kind: <target-kind>
name: <target-name>
namespace: <target-namespace>
synchronize: false
data:
<target-resource-content>
当每次触发都应创建一个独立的目标资源时,请使用 synchronize: false。只有在生成的资源应随着源资源一起更新或删除时,才使用 synchronize: true。
示例场景
在此示例中:
- 源命名空间是
app-team-a。
- 源 ConfigMap 是
app-notification-source。
- 仅匹配
UPDATE 操作。
- 只有对
ConfigMap.data 的更改会触发生成。
- Kyverno 会在
cpaas-system 中创建一个短生命周期的 NotificationMessage。
- 生成的消息会直接向
platform-operator@example.com 发送电子邮件。
本示例使用的通知消息 API 是 notificationmessages.aitextensions.alauda.io/v1beta1。它由平台通知 API 提供,并在创建后很快被消费。
前提条件
- 已安装 Alauda Container Platform Compliance with Kyverno。
- 平台通知能力已安装在同一集群中。
- 已配置电子邮件通知服务器。平台默认电子邮件服务器存储为
cpaas-system 命名空间中的 platform-email-server Secret。
cpaas-system 命名空间中存在用于电子邮件消息的通知模板。
- Kyverno 具有在目标命名空间中创建
NotificationMessage 资源的权限。
此示例不需要 notification rule、notification policy、notification receiver 或 notification sender 资源。收件人电子邮件地址直接在生成的 NotificationMessage 中指定。
准备目标资源依赖项
生成的 NotificationMessage 会引用一个电子邮件模板。在应用 Kyverno policy 之前,请先创建该模板。
apiVersion: ait.alauda.io/v1beta1
kind: NotificationTemplate
metadata:
name: configmap-change-email-template
namespace: cpaas-system
labels:
cpaas.io/template.email.body.type: Html
cpaas.io/template.language: EN
spec:
templates:
- type: Email
subject: "ConfigMap {{ .labels.namespace }}/{{ .labels.name }} changed"
content: |-
The watched ConfigMap was updated.
Namespace: {{ .labels.namespace }}
Name: {{ .labels.name }}
Resource version: {{ .labels.resourceVersion }}
Application: {{ .labels.application }}
Owner: {{ .labels.owner }}
Severity: {{ .labels.severity }}
准备源资源
创建 Kyverno 将监视的命名空间和 ConfigMap。
apiVersion: v1
kind: Namespace
metadata:
name: app-team-a
---
apiVersion: v1
kind: ConfigMap
metadata:
name: app-notification-source
namespace: app-team-a
data:
application: payment
owner: platform-ops
severity: warning
授予 Kyverno 权限
Kyverno 通过其后台 controller 创建生成的资源。请授予该 controller 在目标命名空间中创建 NotificationMessage 资源的权限。
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: kyverno-generate-notificationmessages
namespace: cpaas-system
rules:
- apiGroups:
- aitextensions.alauda.io
- aiops.alauda.io
resources:
- notificationmessages
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: kyverno-generate-notificationmessages
namespace: cpaas-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: kyverno-generate-notificationmessages
subjects:
- kind: ServiceAccount
name: kyverno-background-controller
namespace: kyverno
如果 Kyverno 安装在不同的命名空间中,或者使用了不同的后台 controller ServiceAccount 名称,请在应用 YAML 之前更新 subjects 部分。
创建 Generate Policy
创建一个 ClusterPolicy,仅当 app-team-a/app-notification-source 被更新且其 data 字段发生变化时,才生成 NotificationMessage。
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: generate-notificationmessage-on-configmap-change
annotations:
policies.kyverno.io/title: Generate NotificationMessage on ConfigMap Change
policies.kyverno.io/category: Operations
policies.kyverno.io/subject: ConfigMap, NotificationMessage
policies.kyverno.io/description: >-
Generates a platform NotificationMessage resource when the watched ConfigMap data changes.
spec:
background: false
rules:
- name: generate-email-notificationmessage
match:
any:
- resources:
kinds:
- ConfigMap
namespaces:
- app-team-a
names:
- app-notification-source
operations:
- UPDATE
preconditions:
all:
- key: "{{ request.object.data || `{}` }}"
operator: NotEquals
value: "{{ request.oldObject.data || `{}` }}"
generate:
apiVersion: aitextensions.alauda.io/v1beta1
kind: NotificationMessage
name: "cm-change-{{ request.object.metadata.namespace }}-{{ request.object.metadata.name }}-{{ request.object.metadata.resourceVersion }}"
namespace: cpaas-system
synchronize: false
data:
metadata:
labels:
app.kubernetes.io/managed-by: kyverno
app.kubernetes.io/part-of: configmap-change-notification
configmap-change/source-namespace: "{{ request.object.metadata.namespace }}"
configmap-change/source-name: "{{ request.object.metadata.name }}"
annotations:
configmap-change/resource-version: "{{ request.object.metadata.resourceVersion }}"
spec:
body:
labels:
namespace: "{{ request.object.metadata.namespace }}"
name: "{{ request.object.metadata.name }}"
resourceVersion: "{{ request.object.metadata.resourceVersion }}"
application: "{{ request.object.data.application || '' }}"
owner: "{{ request.object.data.owner || '' }}"
severity: "{{ request.object.data.severity || '' }}"
notifications:
- name: "configmap-change-email-{{ request.object.metadata.resourceVersion }}"
ephemeral:
methods:
- Email
template: configmap-change-email-template
receivers:
- destination: platform-operator@example.com
generate 规则使用以下关键字段:
match.resources:仅监视指定的 ConfigMap 和 UPDATE 操作。
preconditions:比较新的和旧的 data 字段,以避免仅元数据更新时生成消息。
generate.apiVersion、kind、name 和 namespace:定义目标资源标识。
generate.data:定义完整的生成资源主体。
synchronize: false:为每个匹配的更新创建一个单独的目标资源。
生成的 NotificationMessage 使用 spec.body.labels 作为模板变量,使用 ephemeral.methods 选择电子邮件传递方式,使用 ephemeral.template 引用电子邮件模板,并使用 receivers[].destination 指定收件人电子邮件地址。
验证 Generate 规则
更新被监视的 ConfigMap。
kubectl patch configmap app-notification-source \
-n app-team-a \
--type merge \
-p '{"data":{"severity":"critical"}}'
检查 Kyverno 后台 controller 日志。日志会显示 Kyverno 已创建生成的目标资源。
kubectl logs -n kyverno deploy/kyverno-background-controller --since=5m
日志输出将包含类似以下内容的生成目标:
created generate target resource target=aitextensions.alauda.io/v1beta1/NotificationMessage/cpaas-system/cm-change-app-team-a-app-notification-source-19377570
在本示例中,还需要检查通知 API 日志。成功发送电子邮件时,会显示一个任务、电子邮件发送方和收件人,以及 Done 状态。
kubectl logs -n cpaas-system deploy/courier-api --since=5m
日志输出将包含类似以下内容的条目:
Try to exec {"tasks": 1}
Email begin {"from": ["user@example.com"], "to": ["platform-operator@example.com"]}
Email end {"from": ["user@example.com"], "to": ["platform-operator@example.com"]}
"status":{"conditions":[{"method":"Email","addresses":["platform-operator@example.com"],"type":"Ready","status":"True"}],"phase":"Done"}
NotificationMessage 资源生命周期较短,并由通知 API 消费。常规的 kubectl get 命令在消息被接受后可能无法显示该生成的消息。
故障排查
如果没有生成目标资源,请检查 Kyverno update requests。
kubectl get updaterequests -A
如果某个 update request 失败,请查看其详细错误信息。
kubectl describe updaterequest -n kyverno <update-request-name>
常见原因包括:
- 源资源更新未匹配
match.resources 过滤器。
- ConfigMap 更新未更改
data 字段,因此未满足前提条件。
- Kyverno 后台 controller 没有权限在
cpaas-system 中创建 notificationmessages.aitextensions.alauda.io 资源。
notificationmessages.aitextensions.alauda.io/v1beta1 API 在目标集群中不可用。
- 生成的资源名称超过了 Kubernetes DNS label 长度限制。
ephemeral.template 引用的电子邮件模板不存在。
- 电子邮件通知服务器未配置或不可用。