如何配置Kyverno仅在存在指定ConfigMap时注入环境变量?
解决Kyverno策略仅在指定ConfigMap存在时生效的问题
问题场景
尝试使用Kyverno策略,通过Pod所在命名空间的nsenvvars ConfigMap向容器注入环境变量,但在没有该ConfigMap的命名空间中创建Pod时会失败,期望规则仅在目标ConfigMap存在时才执行注入操作。以下是最初报错的配置:
apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: add-env-vars-from-cm annotations: policies.kyverno.io/title: "Add Environment Variables from ConfigMap" policies.kyverno.io/minversion: "1.6.0" policies.kyverno.io/subject: "Pod" policies.kyverno.io/category: "Other" policies.kyverno.io/description: "Instead of defining a common set of environment variables multiple times either in manifests or separate policies, Pods can reference entire collections stored in a ConfigMap. This policy mutates all initContainers (if present) and containers in a Pod with environment variables defined in a ConfigMap named `nsenvvars` that must exist in the Destination Namespace." spec: rules: - name: add-env-vars-from-cm match: any: - resources: kinds: - "Pod" context: - name: envVarsCmCount apiCall: urlPath: "/api/v1/namespaces/{{ request.namespace }}/configmaps/nsenvvars" jmesPath: "data | length(@)" default: 0 preconditions: all: - key: envVarsCmCount operator: "GreaterThan" value: 0 mutate: patchStrategicMerge: spec: initContainers: - (name): "*" envFrom: - configMapRef: name: "nsenvvars" containers: - (name): "*" envFrom: - configMapRef: name: "nsenvvars"
问题原因
原配置中直接通过apiCall请求指定名称的ConfigMap,当该ConfigMap不存在时,API会返回404错误,此时default: 0参数不会生效,导致envVarsCmCount变量无有效值,进而使preconditions判断逻辑失效,最终导致Pod创建请求被拦截。
解决方案
修改apiCall的请求方式,改为查询命名空间下所有ConfigMap,通过JMESPath过滤目标ConfigMap并统计数量,确保无论ConfigMap是否存在都能返回有效数值,再通过preconditions判断是否执行注入操作。
修正后的完整配置:
apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: add-env-vars-from-cm annotations: policies.kyverno.io/title: "Add Environment Variables from ConfigMap" policies.kyverno.io/minversion: "1.6.0" policies.kyverno.io/subject: "Pod" policies.kyverno.io/category: "Other" policies.kyverno.io/description: "仅当目标命名空间存在`nsenvvars` ConfigMap时,向Pod的所有initContainers和容器注入该ConfigMap定义的环境变量。" spec: rules: - name: add-env-vars-from-cm match: any: - resources: kinds: - "Pod" context: - name: envVarsCmExists apiCall: urlPath: "/api/v1/namespaces/{{ request.namespace }}/configmaps" jmesPath: "items[?metadata.name == 'nsenvvars'] | length(@)" preconditions: all: - key: "{{ envVarsCmExists }}" operator: "GreaterThan" value: 0 mutate: patchStrategicMerge: spec: initContainers: - (name): "*" envFrom: - configMapRef: name: "nsenvvars" containers: - (name): "*" envFrom: - configMapRef: name: "nsenvvars"
修改说明
- 将
apiCall改为查询命名空间下所有ConfigMap,通过items[?metadata.name == 'nsenvvars'] | length(@)过滤统计目标ConfigMap的数量,存在时返回1,不存在时返回0。 - 调整preconditions的判断变量为
envVarsCmExists,确保只有当目标ConfigMap存在时才执行mutate操作。 - 更新了annotation中的description,明确策略生效条件。
内容的提问来源于stack exchange,提问作者user2229657
相关产品推荐
相关产品推荐

