I have the following Ingress resource:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: main-ingress
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/force-ssl-redirect: "false"
nginx.ingress.kubernetes.io/proxy-read-timeout: "86400"
nginx.ingress.kubernetes.io/proxy-send-timeout: "86400"
spec:
tls:
- secretName: the-secret
hosts:
- sample.domain.com
- sample2.domain.com
- rabbit.domain.com
- hub.domain.com
- grafana.domain.com
rules:
- host: sample.domain.com
http:
paths:
- path: /
backend:
serviceName: fe-srvc
servicePort: 80
- path: /api
backend:
serviceName: be-srvc
servicePort: 80
- host: sample2.domain.com
http:
paths:
- path: /
backend:
serviceName: fe2-srvc
servicePort: 80
- path: /api
backend:
serviceName: be-srvc
servicePort: 80
## The Extra Services ###
- host: rabbit.domain.com
http:
paths:
- path: /
backend:
serviceName: rabbitmq-srvc
servicePort: 80
and I want to patch it after it is deployed.
So I use this, to try and replace the be-srvc
value with some-srvc
:
kubectl patch ing/main-ingress --patch '{ "spec" : { "rules": [{"http":{"paths":[ {"- path":"/"},{"backend":{"serviceName":"other-srvc"}},{"servicePort":"80"} ] }}]}}'
and I get this error:
The Ingress "main-ingress" is invalid:
* spec.rules[0].http.backend.serviceName: Required value
* spec.rules[0].http.backend.servicePort: Invalid value: 0: must be between 1 and 65535, inclusive
Any insight would be appreciated!
You have to download the current version of the resource spec, e.g., using kubectl get -o yaml , edit it, and then use kubectl replace to update the resource using the modified spec. If any changes have occurred between reading and replacing the resource, the replace will fail.
With the patch command, Kubernetes performs a merge, merging the JSON provided with the current definition of the deployment/versions object. Go ahead and reload the app in your browser, and then you should notice (after a few seconds) that the new version of the app becomes available.
Ingress exposes HTTP and HTTPS routes from outside the cluster to services within the cluster. Traffic routing is controlled by rules defined on the Ingress resource. An Ingress may be configured to give Services externally-reachable URLs, load balance traffic, terminate SSL / TLS, and offer name-based virtual hosting.
Your patch has a number of problems; for example "- path"
instead of "path"
but also incorrect referencing of object levels. However, even if you fixed the mistakes this would not work as intended. Let's see why.
kubectl patch
is a request for a strategic merge patch. When patching arrays, like the .spec.rules
and .spec.rules.http.paths
in this case, a strategic merge patch can use the defined patch type and merge patch merge key for the object to do The Right Thing. However, in case of the Ingress object no one bothered to define these. This means that any patch will overwrite the entire object; it will not be a nice merge that one is hoping for.
To accomplish the particular change referred to in the question you can do:
kubectl get ing/main-ingress -o json \
| jq '(.spec.rules[].http.paths[].backend.serviceName | select(. == "be-srvc")) |= "some-srvc"' \
| kubectl apply -f -
The above will change all occurrences of the be-srvc
Service to some-srvc
. Keep in mind that there is a short race condition here: if the Ingress is modified after kubectl get
ran the change will fail with the error Operation cannot be fulfilled on ingresses.extensions "xx": the object has been modified
; to handle that case you need implement a retry logic.
If the indexes are known in the arrays mentioned above you can accomplish the patch directly:
kubectl patch ing/main-ingress --type=json \
-p='[{"op": "replace", "path": "/spec/rules/0/http/paths/1/backend/serviceName", "value":"some-srvc"}]'
kubectl patch ing/main-ingress --type=json \
-p='[{"op": "replace", "path": "/spec/rules/1/http/paths/1/backend/serviceName", "value":"some-srvc"}]'
The two commands above will change the backends for sample.domain.com/api
and sample2.domain.com/api
to some-srvc
.
The two commands can also be combined like this:
kubectl patch ing/main-ingress --type=json \
-p='[{"op": "replace", "path": "/spec/rules/0/http/paths/1/backend/serviceName", "value":"some-srvc"}, {"op": "replace", "path": "/spec/rules/1/http/paths/1/backend/serviceName", "value":"some-srvc"}]'
This has the same effect and as an added bonus there is no race condition here; the patch guaranteed to be atomic.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With