使用 Kyverno Generate 规则
使用 Kyverno generate 规则,在创建或更新匹配的资源时自动创建 Kubernetes 资源。Generate 规则定义以下内容:
- 要监视的源资源,使用
match。
- 应触发生成的变更,使用可选的
preconditions。
- Kyverno 应创建的目标资源,使用
generate。
- Kyverno 是否应使生成的资源与源资源保持同步。
本指南以更新 ConfigMap 作为示例流程。当特定命名空间中的特定 ConfigMap 发生变更时,Kyverno 会创建平台 NotificationMessage 资源。随后,通知服务会向指定的收件人发送电子邮件。
有关上游 Kyverno 参考信息,请参阅官方的 Kyverno generate 规则文档。
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 由平台通知 API 提供,并会在创建后很快被消费。
前提条件
- 已安装 Alauda Container Platform Policy Management。
- 同一集群中已安装平台通知功能。
- 已配置电子邮件通知服务器。平台默认电子邮件服务器以
platform-email-server Secret 的形式存储在 cpaas-system 命名空间中。
cpaas-system 命名空间中存在用于电子邮件消息的通知模板。
- Kyverno 具有在目标命名空间中创建
NotificationMessage 资源的权限。
此示例不需要通知规则、通知策略、通知接收器或通知发送器资源。收件人的电子邮件地址直接在生成的 NotificationMessage 中指定。
准备目标资源依赖项
生成的 NotificationMessage 引用了一个电子邮件模板。在应用 Kyverno 策略之前创建该模板。
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 通过其后台控制器创建生成的资源。授予该控制器在目标命名空间中创建 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 安装在其他命名空间中,或使用不同的后台控制器 ServiceAccount 名称,请在应用 YAML 之前更新 subjects 部分。
创建生成策略
创建一个 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
生成规则使用以下关键字段:
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 指定收件人的电子邮件地址。
验证生成规则
更新受监视的 ConfigMap。
kubectl patch configmap app-notification-source \
-n app-team-a \
--type merge \
-p '{"data":{"severity":"critical"}}'
检查 Kyverno 后台控制器日志。日志显示 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 更新请求。
kubectl get updaterequests -A
如果更新请求失败,请检查详细错误信息。
kubectl describe updaterequest -n kyverno <update-request-name>
常见原因包括:
- 源资源更新与
match.resources 筛选条件不匹配。
- ConfigMap 更新未更改
data 字段,因此未满足前置条件。
- Kyverno 后台控制器没有权限在
cpaas-system 中创建 notificationmessages.aitextensions.alauda.io 资源。
- 目标集群中没有
notificationmessages.aitextensions.alauda.io/v1beta1 API。
- 生成的资源名称超过了 Kubernetes DNS 标签长度限制。
ephemeral.template 引用的电子邮件模板不存在。
- 电子邮件通知服务器未配置或不可用。