立起注入、生成的规则与权限
目标
用清单实现 mutate 的两种方式和 generate 的两种方式,并在集群中亲自建立 generate 实际运行所需的 RBAC,连同权限一起验证。
为什么重要
generate 规则是 Kyverno 中最容易静默失败的功能。由于 admission 会成功,kubectl 不会报告任何错误,只是目标资源没有生成。原因通常有两种:要么没有匹配 match,要么后台控制器没有权限。在本实验中亲自创建权限并用 auth can-i 检查后,将来遇到生成物不可见时,你会先检查 UpdateRequest 和权限,而不是立即翻查策略 YAML。注入 Sidecar 时同时设置资源限制的习惯,也是同类预防措施。
步骤
- 创建
/root/kca-mutate/目录,在mutate-labels.yaml中填写 kindClusterPolicy、metadata.namekca-add-team-label。创建规则add-managed-by,在match的 kinds 中加入Deployment,并通过mutate.patchStrategicMerge将metadata.labels的kca.io/managed-by设为kyverno。 - 在同一文件中添加规则
inject-sidecar。用match.any[0].resources.selector.matchLabels中的kca.io/inject选择目标;在mutate.patchStrategicMerge.spec.template.spec.containers[0]中加入 namelog-collector、image,以及resources.limits中的memory和cpu。 - 在
/root/kca-mutate/mutate-json6902.yaml中填写 kindClusterPolicy,使用spec.rules[0].mutate.patchesJson6902编写 add 操作,添加注解kca.io/owner。路径位于/metadata/annotations/下,并且必须转义键名中的斜杠。 - 在
/root/kca-mutate/generate-netpol.yaml中填写 kindClusterPolicy、metadata.namekca-generate-default-deny。match 的 kinds 为Namespace;generate.apiVersion为networking.k8s.io/v1;kind为NetworkPolicy;name为default-deny;namespace使用接收新命名空间名称的变量;synchronize为true;在generate.data.spec.policyTypes中加入Ingress和Egress。 - 在
/root/kca-mutate/generate-clone.yaml中填写 kindClusterPolicy、metadata.namekca-clone-baseline。generate.kind为ConfigMap,name为kca-baseline,clone.namespace为kca-shared,clone.name为kca-baseline-config,synchronize为true,并且不要使用data。 - 在集群中创建命名空间
kca-shared,并在其中实际创建 Rolekca-clone-reader。只允许对核心组的configmaps执行get、list、watch,不要加入delete。 - 在集群中创建命名空间
kyverno以及其中的 ServiceAccountkyverno-background-controller;再在kca-shared中实际创建 RoleBindingkca-clone-reader,将 Rolekca-clone-reader绑定到该服务账号。 - 在
kca-shared中实际创建 ConfigMapkca-baseline-config。数据包含log-level=info和retention=7d两项。然后使用kubectl auth can-i确认该服务账号能够读取此命名空间中的 configmaps,但不能读取 secrets。
参考
- 可以使用
kubectl create role kca-clone-reader --verb=get,list,watch --resource=configmaps -n kca-shared快速创建。 - 权限检查命令是
kubectl auth can-i get configmaps --as=system:serviceaccount:kyverno:kyverno-background-controller -n kca-shared。 - 常见错误 1:在 generate 中同时使用 clone 和 data。两者只能选择一个。
- 常见错误 2:在 JSON Patch 路径中原样保留键名里的斜杠。这样无法将它与路径分隔符区分。
用 patchStrategicMerge 注入标签
创建 /root/kca-mutate/ 目录,在 mutate-labels.yaml 中填写 kind ClusterPolicy、metadata.name kca-add-team-label。创建规则 add-managed-by,在 match 的 kinds 中加入 Deployment,并通过 mutate.patchStrategicMerge 将 metadata.labels 的 kca.io/managed-by 设为 kyverno。
在 mutate 块中按对象原有形状写出内容,只会合并对应部分。标签键包含点和斜杠时,请在 YAML 中用引号括起来。
注入 Sidecar 并设置资源限制
在同一文件中添加规则 inject-sidecar。用 match.any[0].resources.selector.matchLabels 中的 kca.io/inject 选择目标;在 mutate.patchStrategicMerge.spec.template.spec.containers[0] 中加入 name log-collector、image,以及 resources.limits 中的 memory 和 cpu。
必须为注入的容器设置资源限制。请思考 mutate 先于 validate 执行这一事实为何在这里很重要。同时确保只为标签选中的工作负载注入,而不是所有工作负载。
使用 JSON Patch 添加注解
在 /root/kca-mutate/mutate-json6902.yaml 中填写 kind ClusterPolicy,使用 spec.rules[0].mutate.patchesJson6902 编写 add 操作,添加注解 kca.io/owner。路径位于 /metadata/annotations/ 下,并且必须转义键名中的斜杠。
JSON Pointer 使用斜杠分隔路径。键名本身包含斜杠时需要特殊转义;如果不知道该写法,路径会指向错误位置。
为每个命名空间生成 default-deny
在 /root/kca-mutate/generate-netpol.yaml 中填写 kind ClusterPolicy、metadata.name kca-generate-default-deny。match 的 kinds 为 Namespace;generate.apiVersion 为 networking.k8s.io/v1;kind 为 NetworkPolicy;name 为 default-deny;namespace 使用接收新命名空间名称的变量;synchronize 为 true;在 generate.data.spec.policyTypes 中加入 Ingress 和 Egress。
generate 必须完整指定生成什么(apiVersion/kind)、使用什么名称以及放在哪个命名空间。目标命名空间就是刚创建的命名空间,因此通过变量取得。
使用 clone 方式复制
在 /root/kca-mutate/generate-clone.yaml 中填写 kind ClusterPolicy、metadata.name kca-clone-baseline。generate.kind 为 ConfigMap,name 为 kca-baseline,clone.namespace 为 kca-shared,clone.name 为 kca-baseline-config,synchronize 为 true,并且不要使用 data。
clone 需要指定源资源的命名空间和名称。请确认它不能与 data 同时使用,并找出让副本跟随源资源变化所需的字段。
创建读取复制源的 Role
在集群中创建命名空间 kca-shared,并在其中实际创建 Role kca-clone-reader。只允许对核心组的 configmaps 执行 get、list、watch,不要加入 delete。
从这里开始操作真实集群。只需要读取,因此三个动词就足够;核心组资源的 apiGroups 是空字符串。
绑定到后台控制器
在集群中创建命名空间 kyverno 以及其中的 ServiceAccount kyverno-background-controller;再在 kca-shared 中实际创建 RoleBinding kca-clone-reader,将 Role kca-clone-reader 绑定到该服务账号。
目标是 kyverno 命名空间中的服务账号。本实验环境中该命名空间和服务账号都不存在,因此也需要一并创建。
创建源 ConfigMap 并验证权限
在 kca-shared 中实际创建 ConfigMap kca-baseline-config。数据包含 log-level=info 和 retention=7d 两项。然后使用 kubectl auth can-i 确认该服务账号能够读取此命名空间中的 configmaps,但不能读取 secrets。
复制源必须真实存在,clone 才能成立。为 kubectl auth can-i 使用 --as 模拟服务账号,即可手动确认权限是否正确绑定。