首页 > 解决方案 > 如何修补 Kubernetes 上已部署的 Ingress 资源?

问题描述

我有以下入口资源:

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

我想在部署后对其进行修补。

所以我使用它来尝试用以下值替换该be-srvcsome-srvc

kubectl patch ing/main-ingress --patch '{ "spec" : { "rules": [{"http":{"paths":[ {"- path":"/"},{"backend":{"serviceName":"other-srvc"}},{"servicePort":"80"} ] }}]}}'

我得到这个错误:

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

任何见解将不胜感激!

标签: kuberneteskubectlkubernetes-ingress

解决方案


你的补丁有很多问题;例如"- path",而不是"path"对象级别的不正确引用。但是,即使您修复了错误,这也不会按预期工作。让我们看看为什么。

kubectl patch是一个战略合并补丁的请求。在修补数组时,例如.spec.rulesand.spec.rules.http.paths在这种情况下,战略合并补丁可以使用定义的补丁类型合并补丁合并键,以便对象执行正确的操作。然而,对于 Ingress 对象,没有人会费心去定义这些。这意味着任何补丁都会覆盖整个对象;这不会是人们希望的一个很好的合并。

要完成问题中提到的特定更改,您可以执行以下操作:

kubectl get ing/main-ingress -o json \ 
  | jq '(.spec.rules[].http.paths[].backend.serviceName | select(. == "be-srvc")) |= "some-srvc"' \
  | kubectl apply -f -

以上内容会将所有出现的be-srvc服务更改为some-srvc. 请记住,这里有一个短暂的竞争条件:如果 Ingress 在kubectl get运行后被修改,则更改将失败并出现错误Operation cannot be fulfilled on ingresses.extensions "xx": the object has been modified;要处理这种情况,您需要实现重试逻辑。

如果上面提到的数组中的索引是已知的,您可以直接完成补丁:

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"}]'

上面的两个命令将更改后端 forsample.domain.com/apisample2.domain.com/apito some-srvc

这两个命令也可以像这样组合:

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"}]'

这具有相同的效果,并且作为额外的好处,这里没有竞争条件;补丁保证是原子的。


推荐阅读