DataGrid 8 Operator Webhooks in OCP 4
Environment
- Red hat OpenShift Container Platform (OCP)
- 4.x
- Red Hat Data Grid (RHDG)
- 8.x
Issue
- What are the webhooks on DataGrid Operator?
- What are the validation webhooks on DataGrid Operator?
- Data Grid Webhook has issues:
Error "failed calling webhook "minfinispan.kb.io": failed to call webhook: Post "https://infinispan-operator-controller-manager-service.mot-int-06.svc:443/mutate-infinispan-org-v1-infinispan?timeout=10s": context deadline exceeded" for field "undefined"
Resolution
Data Grid Operator 8.3.9 introduces the following validating and mutating webhooks:
$ oc get ValidatingWebhookConfiguration
NAME WEBHOOKS AGE
(...)
vbackup.kb.io-rcb5p 1 69m <------------------------ backup
vbatch.kb.io-rn25f 1 69m <------------------------ batch
vcache.kb.io-zg5kh 1 69m <------------------------ cache
vinfinispan.kb.io-kxk29 1 69m <------------------------ infinispan
vrestore.kb.io-vxtt5 1 69m <------------------------ restore
Data Grid Operator 8.3.9 introduces:
$ oc get MutatingWebhookConfiguration
mbackup.kb.io-nm9dd 1 4s <------------------------ backup
mcache.kb.io-vzn6h 1 4s <------------------------ cache
minfinispan.kb.io-x8gfk 1 4s <------------------------ infinispan
mrestore.kb.io-mnbgl 1 4s <------------------------ restore
Example
$ oc get MutatingWebhookConfiguration minfinispan.kb.io-x8gfk -o yaml
service:
name: infinispan-operator-controller-manager-service
namespace: openshift-operators
path: /mutate-infinispan-org-v1-infinispan
port: 443
failurePolicy: Fail
matchPolicy: Equivalent
name: minfinispan.kb.io
namespaceSelector: {}
objectSelector: {}
reinvocationPolicy: Never
rules:
- apiGroups:
- infinispan.org
apiVersions:
- v1
operations:
- CREATE
- UPDATE
resources:
- infinispans
scope: '*'
sideEffects: None
timeoutSeconds: 10
The above is a mutating webhook called minfinispan where match CREATE or UPDATE requests to v1 for the infinispan resources with 10 seconds timeout. So when api gets a CREATE or UPDATE request from infinispans resources, it will run the webhook to mutate the request (i.e. modify) data based on the condition. The scope above is not namespace-bounded, but rather cluster-wide.
Root Cause
DG Operator 8.3.9 introduces the webhooks where the OLM/CO installs them.
The MutatingWebhookConfiguration and ValidatingWebhookConfiguration are defined as part of the Operator CSV manifest. The mutation webhooks are called m+api, and the validation ones are called v+api.
### Validating webhook:
$ oc api-resources | grep -i valid
validatingwebhookconfigurations admissionregistration.k8s.io/v1 false ValidatingWebhookConfiguration
### Mutating webhook:
$ oc api-resources | grep -i mutat
mutatingwebhookconfigurations admissionregistration.k8s.io/v1 false MutatingWebhookConfiguration
Difference between Mutator Webhok vs Validation Webhook:
- ValidatingWebhook: validates a certain configuration
- MutatingWebhook: modify the original request for a custom one
The workflow of webhooks is highlighted as below:
- Resource gets submitted to k8s api-server
- api-server calls webhook implementation endpoint
- api-server accepts/rejects resource based upon response from 2
So if the API-server cannot complete step 2, because network traffic can't flow as expected to/from the webhook endpoint, then it has no choice but to reject the request
The webhook definitions are cluster-scoped, however, the webhook implementations must reside in a namespace. In this case, the implementation of the webhook(s) is provided by the DG Operator pod, so communication between the API-server and the Operator pods has to be possible. Therefore, netpol can play a role in this matter given step 2. Usage of network policies must insure the ingress of the DG operator pod works.
So example communication:
mutating webhook to service --> svc/infinispan-operator-controller-manager-service --> to pod -->infinispan-operator-controller-manager-pod in openshift-operators
Communication
The DG Operator must reach the API server's webhook all the time.
Workflow:
mutating webhook to service --> svc/infinispan-operator-controller-manager-service --> to pod -->infinispan-operator-controller-manager in DG Operator NS installation
- From mutating webhook yaml we track the service
- The service is called infinispan-operator-controller-manager-service and path: /mutate-infinispan-org-v1-infinispan
- and that service points to the dg operator manager
In summary:
a- The namespace that has the DG Operator must allow ingress (not necessarily egress but ingress) so then the DG Operator's service can listen to the request
b- In case the DG Operator and the DG (as in Infinispan CR) is on the same namespace, you need to make sure the allow-from-same-namespace is used.
c- If you have any network policies, you are denied everything else. That's the definition of the network policy. The network policies allow rules, so if you do not allow you are denied on the spot. That's because kubernets does not have a deny rule.
d- DG Operator must allow ingress for webhook validation.
The corollary from the above is if the DG Operator is in the same namespace as the CR, AND you have one network policy so then you MUST have an allow-from-same-namespace.
Finally, if you have a cluster-wide DG Operator, for instance on openshift-operators namespace, you need to make sure that the namespace has an allow ingress communicatoin for other namespaces.
Diagnostic Steps
Example of mutate issue:
Error "failed calling webhook "minfinispan.kb.io": failed to call webhook: Post "https://infinispan-operator-controller-manager-service.svc:443/mutate-infinispan-org-v1-infinispan?timeout=10s": context deadline exceeded" for field "undefined"
$ oc get MutatingWebhookConfigurations/minfinispan -o yaml:
service:
name: infinispan-operator-controller-manager-service
namespace: openshift-operators
path: /mutate-infinispan-org-v1-infinispan
port: 443
$ oc get svc/infinispan-operator-controller-manager-service -o yaml -n openshift-operators
selector:
app.kubernetes.io/name: infinispan-operator
control-plane: controller-manager
$ oc get pods -n openshift-operators --show-labels | grep infinispan-operator
infinispan-operator-controller-manager-7f5c84c5f9-vqcwq 1/1 Running 7 (25m ago) 84m app.kubernetes.io/name=infinispa
n-operator,control-plane=controller-manager,pod-template-hash=7f5c84c5f9
Enabling debug logs on the Catalog Operator shows:
$ oc logs catalog-operator-6f8d5c4c9-x68bc | grep -i infinispan | grep -i webhook
...
"apiservicedefinitions\":{},\"webhookdefinitions\":[{\"generateName\":\"vinfinispan.kb.io\",\"type\":\"ValidatingAdmissionWebhook\",\"deploymentName\":\"infinispan-operator-controller-manager\",\"containerPort\":443,\"targetPort\":9443,\"rules\":[{\"operations\":[\"CREATE\",\"UPDATE\"],\"apiGroups\":[\"infinispan.org\"],\"apiVersions\":[\"v1\"],\"resources\":[\"infinispans\"]}],\"failurePolicy\":\"Fail\",\"sideEffects\":\"None\",\"admissionReviewVersions\":[\"v1\",\"v1beta1\"],\"webhookPath\":\"/validate-infinispan-org-v1-infinispan\"},{\"generateName\":\"vbackup.kb.io\",\"type\":\"ValidatingAdmissionWebhook\",\"deploymentName\":\"infinispan-operator-controller-manager\",\"containerPort\":443,\"targetPort\":9443,\"rules\":[{\"operations\":[\"CREATE\",\"UPDATE\"],\"apiGroups\":[\"infinispan.org\"],\"apiVersions\":[\"v2alpha1\"],\"resources\":[\"backups\"]}],\"failurePolicy\":\"Fail\",\"sideEffects\":\"None\",\"admissionReviewVersions\":[\"v1\",\"v1beta1\"],\"webhookPath\":\"/validate-infinispan-org-v2alpha1-backup\"},{\"generateName\":\"vbatch.kb.io\",\"type\":\"ValidatingAdmissionWebhook\",\"deploymentName\":\"infinispan-operator-controller-manager\",\"containerPort\":443,\"targetPort\":9443,\"rules\":[{\"operations\":[\"CREATE\",\"UPDATE\"],\"apiGroups\":[\"infinispan.org\"],\"apiVersions\":[\"v2alpha1\"],\"resources\":[\"batches\"]}],\"failurePolicy\":\"Fail\",\"sideEffects\":\"None\",\"admissionReviewVersions\":[\"v1\",\"v1beta1\"],\"webhookPath\":\"/validate-infinispan-org-v2alpha1-batch\"},{\"generateName\":\"vcache.kb.io\",\"type\":\"ValidatingAdmissionWebhook\",\"deploymentName\":\"infinispan-operator-controller-manager\",\"containerPort\":443,\"targetPort\":9443,\"rules\":[{\"operations\":[\"CREATE\",\"UPDATE\"],\"apiGroups\":[\"infinispan.org\"],\"apiVersions\":[\"v2alpha1\"],\"resources\":[\"caches\"]}],\"failurePolicy\":\"Fail\",\"sideEffects\":\"None\",\"admissionReviewVersions\":[\"v1\",\"v1beta1\"],\"webhookPath\":\"/validate-infinispan-org-v2alpha1-cache\"},{\"generateName\":\"vrestore.kb.io\",\"type\":\"ValidatingAdmissionWebhook\",\"deploymentName\":\"infinispan-operator-controller-manager\",\"containerPort\":443,\"targetPort\":9443,\"rules\":[{\"operations\":[\"CREATE\",\"UPDATE\"],\"apiGroups\":[\"infinispan.org\"],\"apiVersions\":[\"v2alpha1\"],\"resources\":[\"restores\"]}],\"failurePolicy\":\"Fail\",\"sideEffects\":\"None\",\"admissionReviewVersions\":[\"v1\",\"v1beta1\"],\"webhookPath\":\"/validate-infinispan-org-v2alpha1-restore\"},{\"generateName\":\"minfinispan.kb.io\",\"type\":\"MutatingAdmissionWebhook\",\"deploymentName\":\"infinispan-operator-controller-manager\",\"containerPort\":443,\"targetPort\":9443,\"rules\":[{\"operations\":[\"CREATE\",\"UPDATE\"],\"apiGroups\":[\"infinispan.org\"],\"apiVersions\":[\"v1\"],\"resources\":[\"infinispans\"]}],\"failurePolicy\":\"Fail\",\"sideEffects\":\"None\",\"admissionReviewVersions\":[\"v1\",\"v1beta1\"],\"webhookPath\":\"/mutate-infinispan-org-v1-infinispan\"},{\"generateName\":\"mbackup.kb.io\",\"type\":\"MutatingAdmissionWebhook\",\"deploymentName\":\"infinispan-operator-controller-manager\",\"containerPort\":443,\"targetPort\":9443,\"rules\":[{\"operations\":[\"CREATE\",\"UPDATE\"],\"apiGroups\":[\"infinispan.org\"],\"apiVersions\":[\"v2alpha1\"],\"resources\":[\"backups\"]}],\"failurePolicy\":\"Fail\",\"sideEffects\":\"None\",\"admissionReviewVersions\":[\"v1\",\"v1beta1\"],\"webhookPath\":\"/mutate-infinispan-org-v2alpha1-backup\"},{\"generateName\":\"mcache.kb.io\",\"type\":\"MutatingAdmissionWebhook\",\"deploymentName\":\"infinispan-operator-controller-manager\",\"containerPort\":443,\"targetPort\":9443,\"rules\":[{\"operations\":[\"CREATE\",\"UPDATE\"],\"apiGroups\":[\"infinispan.org\"],\"apiVersions\":[\"v2alpha1\"],\"resources\":[\"caches\"]}],\"failurePolicy\":\"Fail\",\"sideEffects\":\"None\",\"admissionReviewVersions\":[\"v1\",\"v1beta1\"],\"webhookPath\":\"/mutate-infinispan-org-v2alpha1-cache\"},{\"generateName\":\"mrestore.kb.io\",\"type\":\"MutatingAdmissionWebhook\",\"deploymentName\":\"infinispan-operator-controller-manager\",\"containerPort\":443,\"targetPort\":9443,\"rules\":[{\"operations\":[\"CREATE\",\"UPDATE\"],\"apiGroups\":[\"infinispan.org\"],\"apiVersions\":[\"v2alpha1\"],\"resources\":[\"restores\"]}],\"failurePolicy\":\"Fail\",\"sideEffects\":\"None\",\"admissionReviewVersions\":[\"v1\",\"v1beta1\"],\"webhookPath\":\"/mutate-infinispan-org-v2alpha1-restore\"}],\"minKubeVersion\":\"1.11.0\",\"displayName\":\"Data Grid\",\"description\":\"Red Hat Data Grid is a distributed, in-memory data store built from tried and trusted open-source technology.\\n\\n### Data Grid\\n* **Schemaless structure:** Store objects in key/value pairs.\
This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.