更新时间:2024-09-04 GMT+08:00

集群外部访问Ingress异常

Ingress基于七层的HTTP和HTTPS协议进行转发,是集群流量的入口,可以通过域名和路径对访问做到更细粒度的划分。集群在添加Ingress后,可能会出现无法正常访问的情况,本文提供添加Ingress失败或无法正常访问的通用排查思路,帮助您找到问题所在。在进行Ingress问题排查前,请您阅读以下几点须知,并进行自检。

  • 如创建Ingress过程中指定了host地址,将无法通过IP访问。
  • 请检查集群的节点安全组,确认30000-32767范围内的业务端口在入方向对所有网段放开。

排查思路

本文提供了Ingress外部访问异常排查全景图,如图1所示,帮助您由浅入深地排查Ingress访问异常问题。

图1 Ingress访问异常排查全景图
  1. 检查异常是否由Ingress引起

    首先需要确认问题是否由Ingress导致的,因此需要确保外部域名解析正常、安全组规则正确,且Ingress对应的Service和工作负载工作正常。

  2. 检查Ingress状态是否正常

    在Service和工作负载都正常的情况下,需要保证Ingress依赖的ELB状态正常。如果是Nginx型的Ingress,还需要保证nginx-ingress插件的状态是正常的。

  3. 检查Ingress配置是否正确
    如果以上排查结果都正常,说明可能是Ingress的配置出现问题。
    • 检查对接ELB参数是否填写正确。
    • 检查Service参数是否填写正确。
    • 检查转发配置的参数是否填写正确。
  4. 检查证书问题

    如果Ingress开启了HTTPS访问,还需要排除证书配置错误的问题。您可使用相同ELB创建一个HTTP协议的Ingress访问,如HTTP协议下访问正常,则说明HTTPS协议证书可能存在问题。

  5. 如果以上排查均无效果,请进行抓包分析,或提交工单寻求帮助。

检查异常是否由Ingress引起

您需要确认访问异常是否由Ingress引起,当存在域名解析异常、安全组规则错误、Service异常或工作负载本身异常时,都可能会引起Ingress访问不通。

以下排查顺序遵从由外到内的规则:

  1. 检查域名解析或安全组规则是否正常,排除集群外部可能存在的问题。

    1. 执行以下命令检查域名在权威DNS的解析是否生效。
      nslookup -qt=类型 域名 权威DNS地址
    2. 检查集群节点安全组规则,确认30000-32767范围内的业务端口在入方向对所有网段放开。如需对安全组进行加固,详情请参见集群安全组规则配置

  2. 检查Service是否可以正常访问容器内业务,检查集群内部可能存在的问题。

    您可通过在集群中新建Pod并通过ClusterIP访问Service的方式进行检查,如您的服务为NodePort类型,也可通过EIP:Port使用互联网访问服务来验证。
    1. 通过kubectl连接集群,查询集群内服务。
      # kubectl get svc
      NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
      kubernetes   ClusterIP   10.247.0.1       <none>        443/TCP        34m
      nginx        ClusterIP   10.247.138.227   <none>        80/TCP         30m
    2. 创建一个Pod并登录到容器内。
      kubectl run -i --tty --image nginx:alpine test --rm /bin/sh
    3. 使用curl命令访问Service的ClusterIP:Port,检验集群内服务是否可访问。
      curl 10.247.138.227:80

      如Service可正常访问,则说明后端工作负载状态正常,初步可认定异常由Ingress引起,请参照检查Ingress状态是否正常继续排查。

      如Service访问异常,则需继续排查工作负载状态,确定异常原因。

  3. 检查工作负载状态是否正常。

    如工作负载正常,但Service无法正常访问,则说明异常可能是由于Service引起。请检查Service的配置,例如容器端口是否正确填写为容器内业务开放端口。

    如工作负载正常,但访问结果不符合预期,请排查容器内运行的业务代码。

检查Ingress状态是否正常

CCE支持两种类型的Ingress,其中Nginx类型的Ingress Controller由社区开源的插件提供,需要在集群中安装插件自行运维;而ELB型的Ingress Controller运行在master节点上,由专门的华为云团队负责运维,无需用户保证。

  1. 如果您使用Nginx类型的Ingress,需要在集群中安装nginx-ingress插件。如果您使用ELB型的Ingress,则无需检查此步骤。

    前往“插件中心”查看nginx-ingress插件的状态为“运行中”。请保证集群下节点资源充足,若资源不足,插件实例将无法调度。

  2. 前往ELB控制台检查ELB的状态。

    • ELB型Ingress

      访问端口可自定义,请检查ELB侧创建的监听器和后端服务器组未被删除或修改。

      建议您在创建ELB型Ingress时通过控制台选择自动创建ELB,并且不要对自动创建的ELB进行修改,能够有效避免ELB侧导致的Ingress异常。

    • Nginx型Ingress

      访问端口固定为80和443,不支持自定义端口。安装nginx-ingress插件将同时占用80和443端口,切勿删除,否则只能通过重装插件解决。

    您也可以通过错误码来简单判断故障是否由于ELB引起,如下图页面所示,说明该异常大概率由ELB侧故障引起,需要重点排查。

检查Ingress配置是否正确

如果以上排查项都正常,需要考虑是否由于参数设置引起异常。由于使用kubectl创建时需要填写的参数较多易出错,建议您使用控制台创建,根据可视界面按需设置参数,自动过滤不符合要求的负载均衡及Service,能够有效避免出现关键参数格式错误或缺失的问题。

请您根据以下思路进行逐一排查Ingress配置:
  • 检查对接ELB参数是否正确

    由于ELB通过annotations字段下的参数进行定义,但是K8s在创建资源时并不会对annotations字段参数进行校验,如果出现关键参数错误或缺失,Ingress资源也可被创建,但无法正常访问。

    以下是出现频率较高的问题,供您参考:

    • 对接的目标ELB未与集群处于同一VPC下。
    • 添加ELB型Ingress时对接已有ELB,annotations中关键字段kubernetes.io/elb.idkubernetes.io/elb.ipkubernetes.io/ingress.classkubernetes.io/elb.port缺失。
    • 添加Nginx型Ingress时,未安装nginx-ingress插件导致无ELB连接。
    • 添加Nginx型Ingress时,annotations中关键字段kubernetes.io/ingress.classkubernetes.io/elb.port缺失。
    • 添加Nginx型Ingress时,kubernetes.io/elb.port参数不支持自定义端口,使用HTTP协议固定为80,HTTPS协议固定为443。
  • 检查Service配置是否正确
    • 检查Ingress对接的Service类型是否正确,Ingress支持的Service如下。
      表1 ELB Ingress支持的Service类型

      集群类型

      ELB类型

      集群内访问(ClusterIP)

      节点访问(NodePort)

      CCE Standard集群

      共享型负载均衡

      不支持

      支持

      独享型负载均衡

      不支持(集群内访问服务关联实例未绑定eni网卡,独享型负载均衡无法对接

      支持

      CCE Turbo集群

      共享型负载均衡

      不支持

      支持

      独享型负载均衡

      支持

      不支持(节点访问服务关联实例已绑定eni网卡,独享型负载均衡无法对接

      表2 Nginx Ingress支持的Service类型

      集群类型

      ELB类型

      集群内访问(ClusterIP)

      节点访问(NodePort)

      CCE Standard集群

      共享型负载均衡

      支持

      支持

      独享型负载均衡

      支持

      支持

      CCE Turbo集群

      共享型负载均衡

      支持

      支持

      独享型负载均衡

      支持

      支持

    • 检查Service的访问端口号是否正确,此处Service的访问端口号(port字段)需区别于容器端口号(targetPort字段)。
  • 检查转发配置的参数是否填写正确
    • 添加的URL转发路径要求后端应用内存在相同的路径,否则转发无法生效。

      例如,Nginx应用默认的Web访问路径为“/usr/share/nginx/html”,在为Ingress转发策略添加“/test”路径时,需要应用的Web访问路径下也包含相同路径,即“/usr/share/nginx/html/test”,否则将返回404。

      使用Nginx型的Ingress Controller时,您可通过在annotations字段添加rewrite注释进行重定向,将业务内不存在的path路径进行重写,避免访问路径不存在的错误,详情请参见Rewrite

    • 创建Ingress时指定了域名(host),将无法通过IP访问。

检查证书问题

CCE的Ingress密钥证书类型为IngressTLS或kubernetes.io/tls,若证书类型不正确,创建的Ingress将无法在ELB侧建立监听器,导致Ingress访问异常。

  1. 首先去除YAML中关于HTTPS的参数,尝试创建HTTP类型的Ingress是否可正常访问。

    如HTTP访问正常,则考虑HTTPS密钥证书是否存在问题。

  2. 排除密钥类型错误。检查密钥类型是否为IngressTLS或kubernetes.io/tls类型

    # kubectl get secret
    NAME                  TYPE                                  DATA   AGE
    ingress               IngressTLS                            2      36m

  3. 创建测试证书,排除证书问题。

    # openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN={YOUR_HOST}/O={YOUR_HOST}"

  4. 使用测试的私钥证书tls.key和tls.crt创建正确类型的密钥,并重新创建HTTPS类型的Ingress测试是否可以正常访问。本文以创建IngressTLS类型密钥为例。

    通过kubectl方式创建时,创建IngressTLS类型密钥的示例如下:

    kind: Secret
    apiVersion: v1
    type: IngressTLS
    metadata:
      name: ingress
      namespace: default
    data:
      tls.crt: LS0tLS1CRU*****FURS0tLS0t
      tls.key: LS0tLS1CRU*****VZLS0tLS0=

    此处tls.crt和tls.key为示例,请获取真实密钥进行替换。tls.crt和tls.key的值为Base64加密后的内容。