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
DeploymentConfig
kinds - Create a
DeploymentConfig
DeploymentConfig
resource 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
DeploymentConfig
rule 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?