kyverno: [BUG] Openshift DeploymentConfig resources being stripped of fields
Software version numbers
- Kubernetes version: OCP 4.6.21 (based on Kubernetes v1.19.0)
- Kyverno version: 1.3.4
Describe the bug
DeploymentConfig resources in Openshift have many fields removed. DeploymentConfig resources are very similar to Deployments, but with a few extra features (more info here).
When using a policy that behaves correctly with Deployment, StatefulSet or DaemonSet, the DeploymentConfig has many fields removed.
To Reproduce Steps to reproduce the behavior:
- Apply policy to
DeploymentConfigkinds - Create a
DeploymentConfig DeploymentConfigresource rejected by Openshift for not having necessary fields
Expected behavior
Additional fields added that match the policy, similar to Deployment, StatefulSet or DaemonSet resources.
Additional context
The policy in question is: -
---
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: set-service-labels
annotations:
pod-policies.kyverno.io/autogen-controllers: none
spec:
background: false
rules:
- name: set-service-labels-pods
match:
resources:
kinds:
- Pod
exclude:
resources:
namespaces:
- "kube*"
- "openshift*"
- "kube-*"
- "openshift-*"
preconditions:
any:
- key: "{{ request.operation }}"
operator: Equals
value: "CREATE"
mutate:
patchStrategicMerge:
metadata:
labels:
+(service): "{{ request.object.metadata.labels.app }}"
spec:
containers:
- (name): "*"
env:
- name: "SERVICE"
value: "{{ request.object.metadata.labels.app }}"
- name: set-service-labels-deployments-and-sets
match:
resources:
kinds:
- Deployment
- DeploymentConfig
- DaemonSet
- StatefulSet
exclude:
resources:
namespaces:
- "kube*"
- "openshift*"
- "kube-*"
- "openshift-*"
preconditions:
any:
- key: "{{ request.operation }}"
operator: Equals
value: "CREATE"
mutate:
patchStrategicMerge:
spec:
template:
metadata:
labels:
+(service): "{{ request.object.spec.template.metadata.labels.app }}"
spec:
containers:
- (name): "*"
env:
- name: "SERVICE"
value: "{{ request.object.spec.template.metadata.labels.app }}"
Supplying a standard Deployment, I see the following: -
deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: example
namespace: default
spec:
selector:
matchLabels:
app: hello-openshift
replicas: 3
template:
metadata:
labels:
app: hello-openshift
spec:
containers:
- name: hello-openshift
image: openshift/hello-openshift
ports:
- containerPort: 8080
Outcome (output snipped): -
kind: Pod
apiVersion: v1
[...]
metadata:
labels:
app: hello-openshift
service: hello-openshift
spec:
containers:
- name: hello-openshift
image: openshift/hello-openshift
ports:
- containerPort: 8080
env:
- name: "SERVICE"
value: "hello-openshift"
When supplying a DeploymentConfig (notice the similarity to a Deployment): -
deployment_config.yaml
apiVersion: apps.openshift.io/v1
kind: DeploymentConfig
metadata:
name: example
namespace: default
spec:
selector:
app: hello-openshift
replicas: 3
template:
metadata:
labels:
app: hello-openshift
spec:
containers:
- name: hello-openshift
image: openshift/hello-openshift
ports:
- containerPort: 8080
The response is below: -
$ oc apply -f deployment_config.yaml
The DeploymentConfig "example" is invalid: spec.template.spec.containers[0].image: Required value
Debug Logging
I turned on debug logging, and found the following, which is very worrying: -
I0422 12:12:06.371948 1 strategicMergePatch.go:84] EngineMutate "msg"="generating JSON patches from patched resource" "kind"="DeploymentConfig" "name"="example" "namespace"="default" "policy"="set-service-labels" "rule"="set-service-labels-deployments-and-sets" "patchedResource"={"apiVersion":"apps.openshift.io/v1","kind":"DeploymentConfig","metadata":{"managedFields":[{"apiVersion":"apps.openshift.io/v1","fieldsType":"FieldsV1","fieldsV1":{"f:spec":{"f:replicas":{},"f:selector":{".":{},"f:app":{}},"f:strategy":{"f:activeDeadlineSeconds":{},"f:rollingParams":{".":{},"f:intervalSeconds":{},"f:maxSurge":{},"f:maxUnavailable":{},"f:timeoutSeconds":{},"f:updatePeriodSeconds":{}},"f:type":{}},"f:template":{".":{},"f:metadata":{".":{},"f:creationTimestamp":{},"f:labels":{".":{},"f:app":{}}},"f:spec":{".":{},"f:containers":{".":{},"k:{\"name\":\"hello-openshift\"}":{".":{},"f:image":{},"f:imagePullPolicy":{},"f:name":{},"f:ports":{".":{},"k:{\"containerPort\":8080,\"protocol\":\"TCP\"}":{".":{},"f:containerPort":{},"f:protocol":{}}},"f:resources":{},"f:terminationMessagePath":{},"f:terminationMessagePolicy":{}}},"f:dnsPolicy":{},"f:restartPolicy":{},"f:schedulerName":{},"f:securityContext":{},"f:terminationGracePeriodSeconds":{}}},"f:triggers":{}}},"manager":"Mozilla","operation":"Update","time":"2021-04-22T12:12:03Z"}],"name":"example","namespace":"default"},"spec":{"replicas":3,"selector":{"app":"hello-openshift"},"strategy":{"activeDeadlineSeconds":21600,"resources":{},"rollingParams":{"intervalSeconds":1,"maxSurge":"25%","maxUnavailable":"25%","timeoutSeconds":600,"updatePeriodSeconds":1},"type":"Rolling"},"template":{"metadata":{"labels":{"app":"hello-openshift","tags.datadoghq.com/service":"hello-openshift"}},"spec":{"containers":[{"env":[{"name":"SERVICE","value":"hello-openshift"}],"name":"hello-openshift"}],"dnsPolicy":"ClusterFirst","restartPolicy":"Always","schedulerName":"default-scheduler","securityContext":{},"terminationGracePeriodSeconds":30}},"test":false,"triggers":[{"type":"ConfigChange"}]},"status":{"availableReplicas":0,"latestVersion":0,"observedGeneration":0,"replicas":0,"unavailableReplicas":0,"updatedReplicas":0}}
I0422 12:12:06.372306 1 strategicMergePatch.go:96] EngineMutate "msg"="generated patch" "kind"="DeploymentConfig" "name"="example" "namespace"="default" "policy"="set-service-labels" "rule"="set-service-labels-deployments-and-sets" "patch"="{\"op\":\"add\",\"path\":\"/spec/template/spec/containers/0/env\",\"value\":[{\"name\":\"SERVICE\",\"value\":\"hello-openshift\"}]}"
I0422 12:12:06.372348 1 strategicMergePatch.go:96] EngineMutate "msg"="generated patch" "kind"="DeploymentConfig" "name"="example" "namespace"="default" "policy"="set-service-labels" "rule"="set-service-labels-deployments-and-sets" "patch"="{\"op\":\"remove\",\"path\":\"/spec/template/spec/containers/0/terminationMessagePolicy\"}"
I0422 12:12:06.372380 1 strategicMergePatch.go:96] EngineMutate "msg"="generated patch" "kind"="DeploymentConfig" "name"="example" "namespace"="default" "policy"="set-service-labels" "rule"="set-service-labels-deployments-and-sets" "patch"="{\"op\":\"remove\",\"path\":\"/spec/template/spec/containers/0/image\"}"
I0422 12:12:06.372411 1 strategicMergePatch.go:96] EngineMutate "msg"="generated patch" "kind"="DeploymentConfig" "name"="example" "namespace"="default" "policy"="set-service-labels" "rule"="set-service-labels-deployments-and-sets" "patch"="{\"op\":\"remove\",\"path\":\"/spec/template/spec/containers/0/imagePullPolicy\"}"
I0422 12:12:06.372445 1 strategicMergePatch.go:96] EngineMutate "msg"="generated patch" "kind"="DeploymentConfig" "name"="example" "namespace"="default" "policy"="set-service-labels" "rule"="set-service-labels-deployments-and-sets" "patch"="{\"op\":\"remove\",\"path\":\"/spec/template/spec/containers/0/ports\"}"
I0422 12:12:06.372478 1 strategicMergePatch.go:96] EngineMutate "msg"="generated patch" "kind"="DeploymentConfig" "name"="example" "namespace"="default" "policy"="set-service-labels" "rule"="set-service-labels-deployments-and-sets" "patch"="{\"op\":\"remove\",\"path\":\"/spec/template/spec/containers/0/resources\"}"
I0422 12:12:06.372508 1 strategicMergePatch.go:96] EngineMutate "msg"="generated patch" "kind"="DeploymentConfig" "name"="example" "namespace"="default" "policy"="set-service-labels" "rule"="set-service-labels-deployments-and-sets" "patch"="{\"op\":\"remove\",\"path\":\"/spec/template/spec/containers/0/terminationMessagePath\"}"
I0422 12:12:06.372554 1 strategicMergePatch.go:96] EngineMutate "msg"="generated patch" "kind"="DeploymentConfig" "name"="example" "namespace"="default" "policy"="set-service-labels" "rule"="set-service-labels-deployments-and-sets" "patch"="{\"op\":\"add\",\"path\":\"/spec/template/metadata/labels/tags.datadoghq.com~1service\",\"value\":\"hello-openshift\"}"
This implies that nearly all of the fields are being removed, specifically: -
"spec": {
"containers": [{
"env": [{
"name": "SERVICE",
"value": "hello-openshift"
}],
"name": "hello-openshift"
}],
Do you know why a DeploymentConfig would be treated differently to a Deployment?
I inspected the AdmissionRequest coming in from the DeploymentConfig (using my own tool) and it appears to be no different than a standard Deployment request. Let me know if you would like the output from that too (it is the full JSON admission request object)
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 20 (10 by maintainers)
Latest update - I have a version of this working!
The below works as expected: -
This seems to do what we need.
I suppose the limitation we now have is that the
DeploymentConfigrule only takes effect on the first container. This will be fine in a lot of cases, but it won’t always be the case.Is there a way we can apply this to all container definitions, rather than just the first?