自动化租户接入的 generate 策略
目标
编写生成策略,使新租户命名空间一创建就同时生成默认的安全和资源对象,并补齐该策略要在真实集群中运行所需的其他配置。
为什么重要
为新团队提供一个命名空间,通常依靠检查清单执行:应用 NetworkPolicy、设置 ResourceQuota、加入 LimitRange、复制镜像仓库 Secret。只要由人工操作,迟早会漏掉某一步;如果恰好遗漏的是默认拒绝策略,那个命名空间就可能开放数月。生成规则会把这份检查清单直接绑定到命名空间创建事件。这里将学习三点。第一,如果不使用标签缩小触发范围,系统命名空间也会成为目标。第二,对于 Secret 这类不能把内容写进策略文件的对象,应使用 clone 仅指向原对象——因为策略会进入 git。第三,后台控制器按最小权限安装,因此必须另外授予它所需生成资源种类的权限;而且如果没有权限,请求仍会成功,只是资源会悄无声息地不生成。 此环境不运行控制器,因此不会实际创建资源;评分依据是使用 kyverno CLI 进行本地评估的结果和策略 YAML 结构。
步骤
- 在
/root/policy/generate/add-networkpolicy.yaml中创建kind: ClusterPolicy。在spec.rules[0].generate中写入apiVersion: networking.k8s.io/v1、kind: NetworkPolicy、name: default-deny,并在generate.data.spec中设置podSelector: {}和policyTypes,其中必须包含Ingress。 - 将同一规则的
match.any[0].resources.kinds设为Namespace,并在selector.matchLabels中写入labhub.io/tenant: "true",使其仅响应租户命名空间。 - 将
generate.synchronize设为true。然后在/root/policy/generate/out/sync-note.txt中同时写明启用时的行为(有人手动修改后会恢复原状)以及禁用时的区别(只在创建时介入一次)。 - 创建
/root/policy/generate/clone-registry-secret.yaml。generate.kind为Secret,generate.clone.namespace为pol-lab,generate.clone.name为registry-creds。不得使用generate.data,策略文件中也不得包含 Secret 内容。 - 将
add-networkpolicy.yaml的generate.namespace设为"{{ request.object.metadata.name }}",并明确指定generate.name。然后在/root/policy/generate/out/vars-note.txt中整理策略可使用的变量,其中必须包含request.object以及承载请求者信息的变量(request.operation或request.userInfo)。 - 在
/root/policy/generate/background-rbac.yaml中创建kind: ClusterRole。在rules中包含networkpolicies,并在verbs中加入create和update(已启用同步,因此也需要更新权限)。在metadata.labels中添加类似rbac.kyverno.io/aggregate-to-background-controller: "true"的聚合标签。 - 运行
kyverno apply /root/policy/generate/add-networkpolicy.yaml --resource /opt/lab/fixtures/policy/resources/target-ns.yaml,并将仅生成的 NetworkPolicy 清单保存到/root/policy/generate/out/generated.txt。不要包含运行摘要行(pass: ..., error: 0 ...)。 - 在
/root/policy/generate/tenant-onboarding.yaml中创建一项包含 3 条规则的策略。每条规则分别生成NetworkPolicy、ResourceQuota、LimitRange,规则名称必须互不相同,且三条规则都必须设置generate.synchronize: true。然后在/root/policy/generate/out/onboarding-report.json中把trigger_namespace设为tenant-alpha,并在generated数组中放入至少 3 个将生成的资源,每项都包含kind键(其中必须有ResourceQuota)。
参考
- 触发器夹具位于
/opt/lab/fixtures/policy/resources/target-ns.yaml,名称为tenant-alpha,标签为labhub.io/tenant: "true"。 - 如果第 7 步的结果文件中出现
error字样,评分会失败。摘要行包含error: 0,因此请只保留生成的清单。 generate.clone和generate.data只能使用其中一个。- 常见错误 1:在第 4 步的策略文件中模拟写入 Secret 值。如果文件中出现
password、token等字符串,使用 clone 的意义就不存在了。 - 常见错误 2:在第 8 步复制规则后保留相同名称。名称重复时,策略会被拒绝。
编写生成默认 NetworkPolicy 的规则
在 /root/policy/generate/add-networkpolicy.yaml 中创建 kind: ClusterPolicy。在 spec.rules[0].generate 中写入 apiVersion: networking.k8s.io/v1、kind: NetworkPolicy、name: default-deny,并在 generate.data.spec 中设置 podSelector: {} 和 policyTypes,其中必须包含 Ingress。
生成规则首先要写明待创建资源的 apiVersion、kind、name、namespace。策略另有一个键用于直接写入资源内容。
缩小触发器和目标选择器范围
将同一规则的 match.any[0].resources.kinds 设为 Namespace,并在 selector.matchLabels 中写入 labhub.io/tenant: "true",使其仅响应租户命名空间。
在 match 中写明创建何种对象时触发。如果对所有命名空间生成,系统命名空间也会成为目标,因此请用标签缩小范围。
启用同步并说明其含义
将 generate.synchronize 设为 true。然后在 /root/policy/generate/out/sync-note.txt 中同时写明启用时的行为(有人手动修改后会恢复原状)以及禁用时的区别(只在创建时介入一次)。
启用后,系统在资源创建之后仍会持续监视。你必须在文件中写明它与禁用状态的区别才能通过。
编写复制原对象的 clone 规则
创建 /root/policy/generate/clone-registry-secret.yaml。generate.kind 为 Secret,generate.clone.namespace 为 pol-lab,generate.clone.name 为 registry-creds。不得使用 generate.data,策略文件中也不得包含 Secret 内容。
如果把 Secret 内容写入策略文件,策略本身就会成为泄露途径。可以只指明原对象所在位置,而且这种方式不能与直接写入内容的键同时使用。
使用请求上下文变量确定目标
将 add-networkpolicy.yaml 的 generate.namespace 设为 "{{ request.object.metadata.name }}",并明确指定 generate.name。然后在 /root/policy/generate/out/vars-note.txt 中整理策略可使用的变量,其中必须包含 request.object 以及承载请求者信息的变量(request.operation 或 request.userInfo)。
从请求对象中取得刚创建的命名空间名称。必须整理出三种策略可用的变量才能通过。
编写授予生成权限的 ClusterRole
在 /root/policy/generate/background-rbac.yaml 中创建 kind: ClusterRole。在 rules 中包含 networkpolicies,并在 verbs 中加入 create 和 update(已启用同步,因此也需要更新权限)。在 metadata.labels 中添加类似 rbac.kyverno.io/aggregate-to-background-controller: "true" 的聚合标签。
后台控制器自身没有任何权限。启用同步后,除了创建权限还需要更新权限。也不要忘记用于汇集权限的聚合标签。
使用触发资源运行并保存生成结果
运行 kyverno apply /root/policy/generate/add-networkpolicy.yaml --resource /opt/lab/fixtures/policy/resources/target-ns.yaml,并将仅生成的 NetworkPolicy 清单保存到 /root/policy/generate/out/generated.txt。不要包含运行摘要行(pass: ..., error: 0 ...)。
应保存的是生成资源的清单。不要加入运行摘要行——评分程序会查找错误字符串。
创建入驻策略组和结果报告
在 /root/policy/generate/tenant-onboarding.yaml 中创建一项包含 3 条规则的策略。每条规则分别生成 NetworkPolicy、ResourceQuota、LimitRange,规则名称必须互不相同,且三条规则都必须设置 generate.synchronize: true。然后在 /root/policy/generate/out/onboarding-report.json 中把 trigger_namespace 设为 tenant-alpha,并在 generated 数组中放入至少 3 个将生成的资源,每项都包含 kind 键(其中必须有 ResourceQuota)。
在同一策略中用不同规则分别创建网络、配额和默认资源三类对象。规则名称不得重复,并且必须全部启用同步。