Kyverno生成资源

生成资源

根据资源创建或更新创建其他资源。

generate 规则可用于在创建新资源或更新源时创建其他资源。这对于创建支持资源很有用,例如命名空间的新 RoleBindings 或 NetworkPolicies。

generate 规则像其它规则一样,支持 matchexclude 块。因此,可以在创建任何资源时触发该规则。还可以根据subjects、roles等匹配或排除 API 请求。

在执行 API CREATE 操作时触发 generate 规则。您可以使用 synchronize 属性,在更改时保持资源同步。当 synchronize 被设为 true 时,衍生资源会和源资源(可以定义为策略的一部分,也可以是现有资源)保持同步,并且衍生资源不能被用户修改。如果 synchronize 被设为 false,用户可以直接修改或删除衍生资源。

注意:在 Kyverno 1.3.0 中,synchronize=true 的衍生资源可能会被其它 Kubernetes 控制器及有相应访问权限的用户修改或删除,Kyverno 将重新创建或更新资源以符合配置的策略。

当使用 generate 规则时,源资源既可以是由 Kubernetes 定义的、已存在的资源,也可以是由规则定义的新资源。如果源资源是已存在的资源,如 ConfigMap 或 Secret,将使用 clone 对象。如果源资源是规则中定义的新资源,将使用 data 对象。这些是相互排斥的,并且只能在规则中指定一个。

警告:删除包含有使用 data 对象的 generate 规则,且 synchronize=true 的策略时,将导致立即删除下游的衍生资源。包含 clone 对象的策略不受此行为的影响。

在 CustomResourceDefinitions (CRD) 中定义的 CustomResources 之前,Kubernetes 就有许多默认资源类型。Kyverno 也可以像生成 Kubernetes 默认资源一样,生成 CustomResources,但都需要给 generate 行为所依赖的 ClusterRole 授予额外的权限。要想允许 Kyverno 生成这些类型,需要修改名为 kyverno:generate 的 ClusterRole,并为其添加或更新规则以涵盖所需的资源和动词。

注意:生成自定义资源时,需要设置 apiVersion(例如 spec.generate.apiVersion 和 kind(例如 spec.generate.kind)。

Kyverno 将创建一个名为 UpdateRequest 的中间对象,用于将工作项排队以生成最终资源。要获取生成资源的详细信息和状态,请检查 UpdateRequest 的详细信息。下面将给出 UpdateRequest 的列表。

kubectl get updaterequests -A

UpdateRequest 状态可以具有以下四个值之一:

  • Completed:UpdateRequest 控制器完成策略中定义的资源的创建。
  • Failed:UpdateRequest 控制器处理规则失败。
  • Pending:请求尚未处理或资源尚未创建。
  • Skip:通过向现有资源添加标签/注释来触发 generate 策略,而策略中未定义选择器。

使用内联数据生成 ConfigMap

此策略基于在规则中定义的 ConfigMap 为所有命名空间设置 Zookeeper 和 Kafka 连接字符串。请注意,此规则定义了 generate.data 对象,在这种情况下,该规则将使用规则清单中指定的数据创建一个名为 zk-kafka-address 的新 ConfigMap。

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: zk-kafka-address
spec:
  rules:
  - name: k-kafka-address
    match:
      any:
      - resources:
          kinds:
          - Namespace
    exclude:
      any:
      - resources:
          namespaces:
          - kube-system
          - default
          - kube-public
          - kyverno
    generate:
      synchronize: true
      apiVersion: v1
      kind: ConfigMap
      name: zk-kafka-address
      # 创建 namespace 时生成如下资源
      namespace: "{{request.object.metadata.name}}"
      data:
        kind: ConfigMap
        metadata:
          labels:
            somekey: somevalue
        data:
          ZK_ADDRESS: "192.168.10.10:2181,192.168.10.11:2181,192.168.10.12:2181"
          KAFKA_ADDRESS: "192.168.10.13:9092,192.168.10.14:9092,192.168.10.15:9092"

克隆 ConfigMap 并传播更改

此策略中,源数据是一个已存在于 default 命名空间中名为 config-template 的 ConfigMap。请注意,当原始数据存在于 Kubernetes 中时,此处的 generate 规则将使用 generate.clone 对象。

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: basic-policy
spec:
  rules:
  - name: Clone ConfigMap
    match:
      any:
      - resources:
          kinds:
          - Namespace
    exclude:
      any:
      - resources:
          namespaces:
          - kube-system
          - default
          - kube-public
          - kyverno
    generate:
      # Kind of generated resource
      kind: ConfigMap
      # apiVersion of the generated resource
      apiVersion: v1
      # Name of the generated resource
      name: default-config
      # namespace for the generated resource
      namespace: "{{request.object.metadata.name}}"
      # propagate changes from the upstream resource
      synchronize : true
      clone:
        namespace: default
        name: config-template

生成 Bindings

为了让 Kyverno 生成新的 RoleBinding 或 ClusterRoleBinding 资源,它的 ServiceAccount 必须首先绑定到您尝试生成的、相同 Role 或 ClusterRole。如果不这样做,Kubernetes 会阻止请求,因为它看到来自 Kyverno ServiceAccount 可能在尝试提升权限。这不是 Kyverno 的功能,而是 Kubernetes RBAC 的工作方式。

例如,如果你想要编写一个 generate 规则,该规则会创建一个新的 RoleBinding 资源,并授予某些用户在新命名空间上的 admin 角色,Kyverno ServiceAccount 必须通过 ClusterRoleBinding 与同样的 admin 角色绑定。

为 Kyverno 的 ServiceAccount(默认名为 kyverno )创建一个新的 ClusterRoleBinding。

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: kyverno:generate-admin
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: admin
subjects:
- kind: ServiceAccount
  name: kyverno
  namespace: kyverno

现在,像往常一样,创建一个 generate 规则,将名为 steven 的测试用户与新命名空间的 admin ClusterRole 相绑定。此规则中名为 admin 的内置 ClusterRole 必须与之前 ClusterRoleBinding 中授予 Kyverno ServiceAccount 的 ClusterRole 匹配。

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: steven-rolebinding
spec:
  rules:
  - name: steven-rolebinding
    match:
      any:
      - resources:
          kinds:
          - Namespace
    generate:
      kind: RoleBinding
      apiVersion: rbac.authorization.k8s.io/v1
      name: steven-rolebinding
      namespace: "{{request.object.metadata.name}}"
      data:  
        subjects:
        - kind: User
          name: steven
          apiGroup: rbac.authorization.k8s.io
        roleRef:
          kind: ClusterRole
          name: admin
          apiGroup: rbac.authorization.k8s.io

新创建命名空间时,Kyverno 会生成一个名为 steven-rolebinding 的 RoleBinding,并授予用户 steven 上述新命名空间的 admin ClusterRole。

生成 NetworkPolicy

在此示例中,新命名空间将接收到一个拒绝所有入站和出站流量的 NetworkPolicy。与第一个示例类似,generate.data 对象用于将 NetworkPolicy 资源的规范定义为覆盖模式。

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: default
spec:
  rules:
  - name: deny-all-traffic
    match:
      any:
      - resources:
          kinds:
          - Namespace
    exclude:
      any:
      - resources:
          namespaces:
          - kube-system
          - default
          - kube-public
          - kyverno
    generate:
      kind: NetworkPolicy
      apiVersion: networking.k8s.io/v1
      name: deny-all-traffic
      namespace: "{{request.object.metadata.name}}"
      data:  
        spec:
          # select all pods in the namespace
          podSelector: {}
          policyTypes:
          - Ingress
          - Egress

将资源与 ownerReferences 连接

在某些情况下,触发(源)资源和衍生(下游)资源需要共享相同的生命周期。也就是说,当触发资源被删除时,衍生资源也应该被删除。这样做是有价值的,因为某些资源只有在另一个资源存在时才需要,例如 LoadBalancer 类型的服务需要在某些 CNI 插件中使用特定的网络策略。虽然 Kyverno 不会在内部处理此任务,但 Kubernetes 可以通过在衍生资源中设置 ownerReferences 字段。对于下面的示例,当衍生的 ConfigMap 指定了 metadata.ownerReferences[] 对象,并定义了如下字段,包括引用触发的 Service 资源的 uid 时,就形成了所有者依赖关系。稍后,如果 Service 被删除,ConfigMap 也会被删除。有关更多详细信息,请参阅 Kubernetes 文档,包括有关这些参考范围的重要警告。命名空间级别资源不能是集群级别资源的所有者,也不允许跨命名空间引用。

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: demo-ownerref
spec:
  background: false
  rules:
  - name: demo-ownerref-svc-cm
    match:
      any:
      - resources:
          kinds:
          - Service
    generate:
      kind: ConfigMap
      apiVersion: v1
      name: "{{request.object.metadata.name}}-gen-cm"
      namespace: "{{request.namespace}}"
      synchronize: false
      data:
        metadata:
          ownerReferences:
          - apiVersion: v1
            kind: Service
            name: "{{request.object.metadata.name}}"
            uid: "{{request.object.metadata.uid}}"
        data:
          foo: bar

为现有资源生成衍生资源

在 Kyverno 1.7.0+ 中,Kyverno 支持为现有资源生成衍生资源。为现有资源生成衍生资源的策略在后台应用,根据策略中的匹配语句创建目标资源。它们也可以选择配置为在更新策略本身时应用。

在现有命名空间中生成 NetworkPolicy

默认情况下,安装时不会将策略应用于现有触发器资源。可以通过 generateExistingOnPolicyUpdate 属性配置该行为。只有 generateExistingOnPolicyUpdate 设置为 true 时,Kyverno 会在收到策略的 CREATEUPDATE 事件时,为现有的触发器生成目标衍生资源。

在这个示例中,触发器资源是 Namespace 类型,将会为所有新建或已存在的 Namespace 生成一个新的 NetworkPolicy。

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: generate-resources
spec:
  generateExistingOnPolicyUpdate: true
  rules:
  - name: generate-existing-networkpolicy
    match:
      any:
      - resources:
          kinds:
          - Namespace
    generate:
      kind: NetworkPolicy
      apiVersion: networking.k8s.io/v1
      name: default-deny
      namespace: "{{request.object.metadata.name}}"
      synchronize: true
      data:
        metadata:
          labels:
            created-by: kyverno
        spec:
          podSelector: {}
          policyTypes:
          - Ingress
          - Egress

为现有的 Deployment 生成 PodDisruptionBudget

下面这个策略会给已存在的或新建的 deployment 创建一个 PodDisruptionBudget 资源。

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: create-default-pdb
spec:
  generateExistingOnPolicyUpdate: true
  rules:
  - name: create-default-pdb
    match:
      any:
      - resources:
          kinds:
          - Deployment
    exclude:
      resources:
        namespaces:
        - local-path-storage
    generate:
      apiVersion: policy/v1
      kind: PodDisruptionBudget
      name: "{{request.object.metadata.name}}-default-pdb"
      namespace: "{{request.object.metadata.namespace}}"
      synchronize: true
      data:
        spec:
          minAvailable: 1
          selector:
            matchLabels:
              "{{request.object.metadata.labels}}"

故障排查

要对策略应用程序故障进行故障排查,请检查 UpdateRequest 自定义资源以获取详细信息。

例如,如果未授予 Kyverno 相应的权限,您应该在 updaterequest.status 中看到此错误:

$ kubectl get ur -n kyverno
NAME       POLICY               RULETYPE   RESOURCEKIND   RESOURCENAME           RESOURCENAMESPACE   STATUS   AGE
ur-7gtbx   create-default-pdb   generate   Deployment     nginx-deployment       test                Failed   2s

$ kubectl describe ur ur-7gtbx -n kyverno
Name:         ur-7gtbx
Namespace:    kyverno
...

status:
  message: 'poddisruptionbudgets.policy is forbidden: User "system:serviceaccount:kyverno:kyverno-service-account"
            cannot create resource "poddisruptionbudgets" in API group "policy" in the namespace "test"'
 state: Failed

你可能感兴趣的:(Kyverno生成资源)