升级Nginx Ingress Controller组件

在升级集群时,由于集群API版本的弃用,可能需要同步对Nginx Ingress Controller进行版本升级。此外,考虑到旧版本的组件可能存在稳定性风险以及功能缺失,推荐您及时将Nginx Ingress Controller升级到最新版本。Nginx Ingress Controller使用了分阶段升级的方式,需要您在升级过程中及时关注组件状态以及业务情况,保证业务流量不会受损。

升级流程

Nginx Ingress Controller作为数据面的关键组件,对稳定性有较高的要求。

由于新版本对Nginx Ingress Controller所做的自定义修改较多以及升级版本跨度较大,可能会导致部分配置不兼容。而且版本跨度大引起的配置不兼容,可能不会在升级后立即暴露出来,因此,一次性将组件升级到最新版本的风险较高。

为了确保升级Nginx Ingress Controller后组件以及业务的正常运行,升级将采用分阶段的形式进行。升级期间,可以对业务状况进行检查,有问题也能够及时回滚。

image

第一部分:前置检查

前置检查将会在组件升级开始之前自动进行,以检查组件当前状态是否满足升级条件。如果组件存在不满足升级条件的设置,或者处于不健康状态时,将无法通过健康检查,在完成问题的手动修复之前,无法继续进行升级。

第二部分:验证阶段

验证阶段会扩容出1个新版本组件的Pod,验证新版本组件的运行状态以及Ingress规则是否符合预期。扩容成功后,一部分流量将会进入该Pod,此时可以通过容器日志、SLS日志服务或阿里云Prometheus监控服务来查看流量是否有异常。

验证Pod扩容成功后,升级流程会被暂停。在确认组件和业务无异常后,即可手动确认继续进行下一阶段。若此时出现问题,也可以选择回滚,删除新版本Pod,终止升级流程。

该步是通过修改Deployment中的spec.minReadySecondsspec.strategy字段实现的。

第三部分:发布阶段

发布阶段将会进行完整的滚动升级流程,将旧版本组件完全替换为新版本。在所有Pod更新完成后,升级流程会暂停,此时可以对组件和业务做最终的确认。当确认无误后,升级结束。若此时出现问题,也可以选择回滚,将所有Pod重置回旧版本,并结束升级流程。

第四部分:回滚(可选)

在验证阶段或者发布阶段后的暂停过程中,如果发现组件或业务出现异常,可以通过回滚来将组件恢复到升级前的初始状态。

升级前须知

  • 在组件升级前,请确保拥有对业务流量的监控手段,以便及时发现问题。您可以通过SLS日志服务或阿里云Prometheus服务来查看业务流量状况。以上两种观测手段的配置,请参见Nginx Ingress访问日志分析与监控使用阿里云Prometheus监控

  • 请确认目前组件健康状态正常,Pod均为Ready状态,没有错误日志。

  • 请确认没有使用HPA等自动扩缩容规则。如存在,请提前删除,在升级完成后将其恢复。

  • 请确认LoadBalancer Service状态正常,没有异常事件透出。

  • 在组件升级过程中,请勿对组件以及Ingress规则进行任何修改。

  • 如果您的Nginx Ingress低于v0.44版本,在升级到高版本时,需要注意前缀匹配的差异,详细信息请参见升级注意事项

  • 组件升级将采用灰度升级的方式,首先会创建一个升级目标版本的Nginx Ingress Pod实例。在经过流量验证确认无误后,单击确认将触发滚动更新。请确保集群中有足够的可调度节点,以便Nginx Ingress Pod能够正常创建和调度。

操作步骤

  1. 登录容器服务管理控制台,在左侧导航栏选择集群

  2. 集群列表页面,单击目标集群名称,然后在左侧导航栏,选择运维管理 > 组件管理

  3. 组件管理页面,找到Nginx Ingress Controller组件,单击组件右下方的升级

  4. 在弹出的升级界面中,单击开始并确认,开始升级流程。

    说明

    您可以在升级过程中的任何时间点退出该页面,然后通过单击组件管理页面中的升级进度重新回到流程中。

  5. 流程的第一阶段需要进行前置检查。在完成前置检查后,流程会自动进入下一阶段。

    若前置检查不通过,可以通过前置检查下的查看详情跳转到检查报告页面。然后根据未通过的检查点排查问题,详细信息,请参见前置检查说明。问题解决后,可以单击重试以重新开始升级流程。

  6. 验证阶段完成后,升级流程进入暂停状态。此时,需要对组件运行状态和业务状态进行验证。关于验证方法,请参见验证阶段说明

    • 若出现扩容不成功的情况,请参见验证和发布阶段Pod扩容失败怎么办?。也可以在集群中查看Pod启动失败的具体原因,并在解决之后单击重试,重试该阶段。

    • 若验证业务出现问题,可以通过单击回滚进行回滚操作。回滚完成后,该升级流程将会结束,可以从组件管理中单击升级重新开始。

  7. 验证阶段确认一切正常后,单击继续进入发布阶段。发布阶段滚动更新完成后,升级流程进入暂停状态。此时,需要对组件和业务状态进行最后一次确认。若业务验证出现问题,可以通过单击回滚进行回滚操作。回滚完成后,升级流程将会结束,可以从组件管理中单击升级重新开始。

  8. 确认组件运行状态和业务状态均没有异常后,单击继续结束升级流程。

    说明

    请控制整个升级流程的总时间不要超过一周。

前置检查说明

前置检查表

检查项

检查内容

异常处理

Deployment存在

组件的Deployment(kube-system/nginx-ingress-controller)存在。

-

Deployment健康

组件的Deployment所控制的Pod全部处于Ready状态,且不处于滚动更新中等不稳定状态。

-

Pod错误日志

检查Pod中最近200条日志,其中不存在Error或者Fatal级别的错误日志。

如果有日志存在,说明组件近期可能因为配置错误等原因出现异常报错,需要在问题解决后重新进行升级流程。根据日志解决问题,请参见Nginx Ingress异常问题排查

LoadBalancer Service健康

首先检查Nginx Ingress Controller所对应的LoadBalancer Service(kube-system/nginx-ingress-lb)是否存在。如果存在,会进一步检查该Service是否存在任何错误事件。

请注意,Service不存在也会被认为该Service存在Warning事件。

当Service不存在时,请参考使用须知及高危风险操作说明文档中 “在安装Nginx Ingress Controller组件的情况下手动删除 kube-system命名空间下的nginx-ingress-lbService” 对应修复操作进行修复。

Service存在但被检查出异常事件时,可以根据事件内容寻找解决方案,详细信息,请参见Service异常事件及处理方式。当Service不为LoadBalancer时,该项检查会被跳过。

HPA

组件Deployment没有使用HPA。使用HPA时,在组件升级过程中,可能会因为HPA的自动扩缩容策略导致升级状态被打乱。

在升级过程中,需要将HPA资源从集群中删除,升级完成后,再重新启用。

Deployment模板

组件的Deployment模板只能存在兼容的修改。

您之前对Nginx Ingress Controller Deployment所做的某些自定义配置或修改,在升级过程中可能无法自动保留。

  • 以下字段会在升级后得到保留,作为自定义参数填入新的组件模板中:

    • 副本数(replicas)

    • Pod标签(template.metadata.labels)

    • 节点选择器(template.spec.nodeSelector)

    • 容忍(template.spec.tolerations)

    • Controller容器的资源限制(template.spec.containers[0].resources)

  • 以下字段不会影响到前置检查,但会在升级后被丢弃:

    • Pod annotation(template.metadata.annotations)中的redeploy-timestamp。

    • Pod annotation中的kubectl.kubernetes.io/restartedAt。

    • Pod annotation中的scheduler.alpha.kubernetes.io/critical-pod。

    • 镜像的imagePullPolicy。

    • template.spec.containers.securityContext.procMount为Default时,会被丢弃。

    • Webhook的相关配置(运行参数、挂载卷、端口)。

上述模板更改不会导致检查不通过。除此之外,无论是私自修改模板还是版本过旧、不符合升级条件,都会造成升级过程中的检查环节无法通过,进而影响升级的成功率。常见的检查不通过的原因如下:

  • 使用了EDAS等插件挂载了自定义的Volume。您需要在升级过程中暂时停用EDAS的相关功能,在升级完成后恢复。

  • podAntiAffinity与标准模板出现差异,可能是由于组件模板变动(例如由required改为preferred)导致的。您需要先手动将podAntiAffinity修改为与标准模板一致。

  • 在指定独占节点时使用了nodeAffinity,您需要更换为nodeSelector。

如果Deployment模板检查失败,您可以通过手动还原模板的方法解决该问题。具体操作,请参见Deployment模板检查不通过

Ingress配置

集群内的Ingress只存在兼容的特性。

如果集群内的Ingress中使用了不兼容的特性,升级后可能会导致业务无法正常转发流量,从而导致不可用的问题。确认及修改问题,请参见下方升级兼容性说明

组件配置

组件ConfigMap(kube-system/nginx-configuration)中存在不兼容的配置

如果集群内ConfigMap中使用了不兼容的特性,升级后可能会导致业务无法正常转发流量,从而导致不可用的问题。确认及修改问题,请参见下方升级兼容性说明

升级兼容性说明

在组件的开发和维护过程中,Nginx Ingress Controller组件的新版本可能会引入新的功能、改进现有功能或者修复安全问题,但同时也可能因为内部架构的调整、依赖库的变化等原因,导致与之前版本存在兼容性差异。关于Nginx Ingress Controller的变更记录,请参见Nginx Ingress Controller

snippet注解默认禁用

影响版本:v1.9.3-aliyun.1以下(不包括v1.9.3-aliyun.1)。

由于安全原因,自v1.9.3-aliyun.1版本起,Nginx Ingress Controller将默认禁用所有snippet注解,可能包括:

  • nginx.ingress.kubernetes.io/configuration-snippet

  • nginx.ingress.kubernetes.io/server-snippet

  • nginx.ingress.kubernetes.io/stream-snippet

  • nginx.ingress.kubernetes.io/auth-snippet

  • nginx.ingress.kubernetes.io/modsecurity-snippet

出于安全和稳定性风险的考虑,建议您优先使用相关注解或者设置项来实现所需功能。

如您仍需要使用snippet注解能力,请在充分评估风险后,通过在ConfigMapkube-system/nginx-configuration中添加allow-snippet-annotations: "true"手动开启注解功能。

不支持较低版本的TLS

影响版本:v1.7.0-aliyun.1以下(不包括v1.7.0-aliyun.1)。

由于TLS1.1及以下版本存在安全问题,Nginx Ingress Controller新版本不再默认支持TLS v1.1和TLS v1.0的加密方式。因此,在升级前,请确保您的业务不依赖v1.1及以下版本的TLS,并且在配置中将其移除。修改ConfigMap后会立即生效。

例如,若Nginx Ingress Controller组件的ConfigMap(kube-system/nginx-configuration)配置如下所示:

ssl-protocols: SSLv3 SSLv2 TLSv1 TLSv1.1 TLSv1.2 TLSv1.3

您需要在确认业务不受影响后,可直接将该行设置移除,使用默认选项;或者选择移除SSLv3、SSLv2、TLSv1、TLSv1.1四项,改为:

ssl-protocols: TLSv1.2 TLSv1.3

若您需要强制使用旧版本的TLS加密方式,请参见Ingress支持哪些SSL/TLS版本?进行配置。

nginx.ingress.kubernetes.io/rewrite-target用法不兼容

影响版本:0.22.0以下(不包括0.22.0)。

  • 0.22.0版本对nginx.ingress.kubernetes.io/rewrite-target注解的用法做了修改。在0.22.0及以上版本,使用rewrite-target时,需要显式指定捕获组的使用。

  • 0.22.0版本以下的rewrite-target特性和最新版本的rewrite-target特性不兼容,在组件升级前,可以使用configuration-snippet代替rewrite-target注解。

例如,在0.22.0以下版本,规则为:

展开查看完整YAML示例代码

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
  name: rewrite
  namespace: default
spec:
  rules:
  - host: rewrite.bar.com
    http:
      paths:
      - path: /something/
        pathType: Prefix
        backend:
          service:
            name: http-svc
            port:
              number: 80
      - path: /something123/
        pathType: Prefix
        backend:
          service:
            name: http-svc-1
            port:
              number: 80

需修改为:

展开查看完整YAML示例代码

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    # 使用rewrite指令,/something为path中路径(不包含尾部的斜杠)。
    # Ingress中包含多个路径,需要添加多条rewrite指令。
    nginx.ingress.kubernetes.io/configuration-snippet: |
      rewrite "(?i)/something(/|$)(.*)" /$2 break;
      rewrite "(?i)/something123(/|$)(.*)" /$2 break;
  name: rewrite
  namespace: default
spec:
  rules:
  - host: rewrite.bar.com
    http:
      paths:
      - path: /something/ # 和旧版本Ingress资源的路径保持一致。
        pathType: Prefix
        backend:
          service:
            name: http-svc
            port:
              number: 80
      - path: /something123/ # 和旧版本Ingress资源的路径保持一致。
        pathType: Prefix
        backend:
          service:
            name: http-svc-1
            port:
              number: 80

修改为上述格式后,即可正常进行升级流程。升级完成后,将Ingress修改为新版的用法即可。

YAML

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    # 引用匹配的内容。
    nginx.ingress.kubernetes.io/rewrite-target: /$2
  name: rewrite
  namespace: default
spec:
  rules:
  - host: rewrite.bar.com
    http:
      paths:
      # 使用捕获组。
      - path: /something(/|$)(.*)
        pathType: Prefix
        backend:
          service:
            name: http-svc
            port:
              number: 80
      # 使用捕获组。
      - path: /something123(/|$)(.*)
        pathType: Prefix
        backend:
          service:
            name: http-svc-1
            port:
              number: 80

验证阶段说明

验证组件及业务状态

除自身所拥有的业务监控能力外,ACK也提供了SLS日志、阿里云Prometheus大盘和容器自身的日志来观测Nginx Ingress Controller的运行状态。开启上述服务,请参见Nginx Ingress访问日志分析与监控使用阿里云Prometheus监控

SLS日志服务

您可以在容器服务控制台查看通过SLS收集的日志。

  1. 登录容器服务管理控制台,在左侧导航栏单击集群

  2. 集群列表页面,单击目标集群名称,然后在左侧导航栏,选择运维管理 > 日志中心

  3. 选择应用日志页签,在日志库下拉框中选择nginx-ingress,单击选择日志库

    说明

    若您的日志库中没有nginx-ingress条目,请确认是否配置了组件的日志收集功能。详细信息,请参见Nginx Ingress访问日志分析与监控

在展示的日志中,可以看到应用的访问日志,也可以在查询语句中指定对应的Pod(如新版本组件的Pod)来只查看该Pod的访问日志。需要注意新Pod的请求成功率是否异常,以及请求数对比旧Pod是否一致。若数据差距较大,可选择回滚操作。

说明

当请求没有命中任何Ingress规则,返回404时,默认将不会记录访问日志。

10

阿里云Prometheus大盘

您可以通过阿里云Prometheus服务提供的大盘,来观测组件整体的请求情况。

  1. 登录容器服务管理控制台,在左侧导航栏单击集群

  2. 集群列表页面,单击目标集群名称,然后在左侧导航栏,选择运维管理 > Prometheus监控

  3. 单击网络监控页签,然后单击集群ingress流量监控

    说明

    若监控中没有集群ingress流量监控,请确认是否配置了组件的Prometheus Metrics搜集功能。详细信息,请参见使用阿里云Prometheus监控

在大盘中可以看到Ingress的各项运行指标,也可以通过选择对应的Pod来查看该Pod的指标。同样,需要注意的是新的Pod请求成功率是否有异常,以及请求数与旧Pod是否一致。若数据差距较大,可选择回滚操作。

说明

Ingress规则中没有指定Host(默认为通配符“*”)的规则默认不会记录Metrics。

Pod日志

您可以通过kubectl,以命令行的形式访问Pod日志,来查看是否存在错误。

  • 执行以下命令,查看Pod中Nginx的错误日志,包括warn、error和crit三个级别。

    kubectl logs -n kube-system <Pod名称> | grep -e warn -e error -e crit
  • 执行以下命令,查看Pod中Controller的错误日志。

    kubectl logs -n kube-system <Pod名称> | grep "^[EF]"

升级注意事项

在低版本的Nginx Ingress Controller升级到高版本时,由于高版本在前缀匹配逻辑上有所变化,需要关注路径path配置与实际请求URL的是否一致,否则可能会导致原本正常的请求出现404错误。

已知问题

在Nginx Ingress Controller的不同版本中,前缀匹配逻辑可能存在差异,这可能导致服务访问问题。

  • 在低版本(v0.44之前)的Nginx Ingress Controller中,前缀匹配的规则较为宽松,允许如/aaa/bbb的配置,可以匹配请求的URL/aaa/bbbbb

  • 升级到高版本后,前缀匹配的逻辑可能会变得更加严格,只匹配精确的请求路径,这可能导致原本应匹配的路径/aaa/bbbbb不再匹配,从而引发404错误。

影响范围

受影响的版本为Nginx Ingress版本低于v0.44。关于Nginx Ingress Controller版本记录,请参见Nginx Ingress Controller。相关PR信息请参见kubernetes/ingress-nginx #6443

示例配置

您可以根据以下的YAML配置比较低版本(如v0.22.0.5-552e0db-aliyun)和高版本(如v1.2.1-aliyun.1+)渲染出Nginx配置之间的差异。

  apiVersion: extensions/v1beta1
  kind: Ingress
  metadata:
    labels:
      ingress-controller: nginx
    name: test
    namespace: default
  spec:
    ingressClassName: nginx
    rules:
    - host: www.example.com
      http:
        paths:
        - backend:
            service:
              name: api-resources-svc
              port:
                number: 8080
          path: /api/resource
  • 低版本行为

    在低版本Nginx Ingress(如v0.22.0.5-552e0db-aliyun)中,对应的Nginx配置:

    Location /api/resource   ## 没有结尾的 "/"

    在上面的配置中,使用的路径/api/resource在低版本Nginx中允许通过http://www.example.com/api/resources进行访问。

    说明

    实际访问路径是resources而不是resource。

  • 高版本行为

    若将Nginx Ingress Controller升级到高版本(如v1.2.1-aliyun.1+),对应的Nginx配置:

    Location /api/resource/  # 增加了结尾的 "/"
    {
    }
    ...
    Location = /api/resource  # 增加了一个 Location 进行精确匹配
    {
    }

    访问http://www.example.com/api/resources将返回404错误。

常见问题

Nginx Ingress Controller是否支持升级至指定的版本?升级成功后,还能回退到之前的某个版本吗?

Nginx Ingress Controller组件不支持升级到指定版本,采用分阶段的形式进行升级,直至将组件升级到最新的版本。升级成功后无法回退。

验证和发布阶段Pod扩容失败怎么办?

问题原因

解决方案

新版本Pod启动时出现错误(如配置加载失败等),导致一直处于crash状态。

根据上方Pod日志部分提供的方法,查看对应Pod错误日志。定位及解决问题,请参见Nginx Ingress异常问题排查

常见于使用专属节点部署Nginx Ingress Controller的情况。当新的Pod扩容时,会因为所配置的资源限制和节点选择器,导致无可用节点能够调度新的Pod。

临时扩容节点,或在业务低峰期缩容Nginx Ingress Controller再进行升级,使得在升级时Pod能够正常调度。

Deployment模板检查不通过怎么办?

如果在前置检查过程中,您的Deployment模板检查不通过,请单击异常原因右侧的链接,进入组件差异展示页面,查看检查不通过的字段。

  1. Nginx Ingress Controller 组件升级页面的前置检查下方,单击查看详情

  2. 检查报告页面的集群组件检查结果区域,单击①处的红色方框查看检查结果,然后在检查结果页面单击Deployment 模板,最后单击②处异常原因右侧的链接。

    image..png

  3. 进入组件差异展示页面,查看检查不通过的字段。

    在组件差异页面,会展示出该版本组件的标准模板(左侧)和当前集群中的组件模板(右侧)的对比展示。组件差异页面会标出两者之间的全部差异,包括兼容和不兼容的字段,并在差异展示的下方标出集群中组件是否通过差异检查,以及不兼容的差异字段的具体路径。

    如下图所示,下方提示存在一处差异,差异字段为.spec.template.spec.containers.(nginx-ingress-controller).args(括号中的内容为数组中元素的name字段)。通过组件差异对比,发现args中--v=2被修改为了--v=3,需要在升级前进行修正。

    image..png

  4. 修改差异字段。

    选择工作负载>无状态,找到Nginx Ingress Controller组件,单击更多>查看YAML,在编辑YAML页面中将args字段中的--v=3修改为--v=2

  5. 将差异字段修改后,您也可以重新进入或刷新组件差异展示页面,查看最新的对比结果。当页面底部提示组件可通过差异检测时,即可通过Deployment模板检查点。

    说明

    修改集群内Deployment过程中,Nginx Ingress Controller Pod会重启,建议您在业务低峰期进行相关操作。

    image..png

相关文档