如何在Kubernetes上修补已部署的Ingress资源?

时间:2018-06-08 13:55:30

标签: kubernetes kubectl kubernetes-ingress

我有以下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-srvc替换some-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

任何见解都将受到赞赏!

1 个答案:

答案 0 :(得分:2)

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

kubectl patch是对 战略合并补丁 的请求。在修补数组时,如本例中的.spec.rules.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。请记住,此处存在短竞争条件:如果在kubectl get运行后修改了Ingress,则更改将失败并显示错误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"}]'

上述两个命令会将sample.domain.com/apisample2.domain.com/api的后端更改为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"}]'

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