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

- 如创建Ingress过程中指定了host地址,将无法通过IP访问。
- 请检查集群的节点安全组,确认30000-32767范围内的业务端口在入方向对所有网段放开。
排查思路
本文提供了Ingress外部访问异常排查全景图,如图1所示,帮助您由浅入深地排查Ingress访问异常问题。
- 检查异常是否由Ingress引起。
首先需要确认问题是否由Ingress导致的,因此需要确保外部域名解析正常、安全组规则正确,且Ingress对应的Service和工作负载工作正常。
- 检查Ingress状态是否正常。
在Service和工作负载都正常的情况下,需要保证Ingress依赖的ELB状态正常。如果是Nginx型的Ingress,还需要保证nginx-ingress插件的状态是正常的。
- 检查Ingress配置是否正确。
如果以上排查结果都正常,说明可能是Ingress的配置出现问题。
- 检查对接ELB参数是否填写正确。
- 检查Service参数是否填写正确。
- 检查转发配置的参数是否填写正确。
- 检查证书问题。
如果Ingress开启了HTTPS访问,还需要排除证书配置错误的问题。您可使用相同ELB创建一个HTTP协议的Ingress访问,如HTTP协议下访问正常,则说明HTTPS协议证书可能存在问题。
- 如果以上排查均无效果,请进行抓包分析,或提交工单寻求帮助。
检查异常是否由Ingress引起
您需要确认访问异常是否由Ingress引起,当存在域名解析异常、安全组规则错误、Service异常或工作负载本身异常时,都可能会引起Ingress访问不通。
以下排查顺序遵从由外到内的规则:
- 检查域名解析或安全组规则是否正常,排除集群外部可能存在的问题。
- 执行以下命令检查域名在权威DNS的解析是否生效。
nslookup -qt=类型 域名 权威DNS地址
- 检查集群节点安全组规则,确认30000-32767范围内的业务端口在入方向对所有网段放开。如需对安全组进行加固,详情请参见集群安全组规则配置。
- 执行以下命令检查域名在权威DNS的解析是否生效。
- 检查Service是否可以正常访问容器内业务,检查集群内部可能存在的问题。
您可通过在集群中新建Pod并通过ClusterIP访问Service的方式进行检查,如您的服务为NodePort类型,也可通过EIP:Port使用互联网访问服务来验证。
- 通过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
- 创建一个Pod并登录到容器内。
kubectl run -i --tty --image nginx:alpine test --rm /bin/sh
- 使用curl命令访问Service的ClusterIP:Port,检验集群内服务是否可访问。
curl 10.247.138.227:80
如Service可正常访问,则说明后端工作负载状态正常,初步可认定异常由Ingress引起,请参照检查Ingress状态是否正常继续排查。
如Service访问异常,则需继续排查工作负载状态,确定异常原因。
- 通过kubectl连接集群,查询集群内服务。
- 检查工作负载状态是否正常。
如工作负载正常,但Service无法正常访问,则说明异常可能是由于Service引起。请检查Service的配置,例如容器端口是否正确填写为容器内业务开放端口。
如工作负载正常,但访问结果不符合预期,请排查容器内运行的业务代码。
检查Ingress状态是否正常
CCE支持两种类型的Ingress,其中Nginx类型的Ingress Controller由社区开源的插件提供,需要在集群中安装插件自行运维;而ELB型的Ingress Controller运行在master节点上,由专门的华为云团队负责运维,无需用户保证。
- 如果您使用Nginx类型的Ingress,需要在集群中安装nginx-ingress插件。如果您使用ELB型的Ingress,则无需检查此步骤。
前往“插件中心”查看nginx-ingress插件的状态为“运行中”。请保证集群下节点资源充足,若资源不足,插件实例将无法调度。
- 前往ELB控制台检查ELB的状态。
- ELB型Ingress
访问端口可自定义,请检查ELB侧创建的监听器和后端服务器组未被删除或修改。
建议您在创建ELB型Ingress时通过控制台选择自动创建ELB,并且不要对自动创建的ELB进行修改,能够有效避免ELB侧导致的Ingress异常。
- Nginx型Ingress
访问端口固定为80和443,不支持自定义端口。安装nginx-ingress插件将同时占用80和443端口,切勿删除,否则只能通过重装插件解决。
您也可以通过错误码来简单判断故障是否由于ELB引起,如下图页面所示,说明该异常大概率由ELB侧故障引起,需要重点排查。
- ELB型Ingress
检查Ingress配置是否正确
如果以上排查项都正常,需要考虑是否由于参数设置引起异常。由于使用kubectl创建时需要填写的参数较多易出错,建议您使用控制台创建,根据可视界面按需设置参数,自动过滤不符合要求的负载均衡及Service,能够有效避免出现关键参数格式错误或缺失的问题。
- 检查对接ELB参数是否正确
由于ELB通过annotations字段下的参数进行定义,但是K8s在创建资源时并不会对annotations字段参数进行校验,如果出现关键参数错误或缺失,Ingress资源也可被创建,但无法正常访问。
以下是出现频率较高的问题,供您参考:
- 对接的目标ELB未与集群处于同一VPC下。
- 添加ELB型Ingress时对接已有ELB,annotations中关键字段kubernetes.io/elb.id、kubernetes.io/elb.ip、kubernetes.io/ingress.class、kubernetes.io/elb.port缺失。
- 添加Nginx型Ingress时,未安装nginx-ingress插件导致无ELB连接。
- 添加Nginx型Ingress时,kubernetes.io/elb.port参数不支持自定义端口,使用HTTP协议固定为80,HTTPS协议固定为443。
- 检查Service配置是否正确
- 检查Ingress对接的Service类型是否正确,Ingress支持的Service如下。
表1 ELB Ingress支持的Service类型 集群类型
ELB类型
集群内访问(ClusterIP)
节点访问(NodePort)
CCE Standard集群
共享型负载均衡
不支持
支持
独享型负载均衡
不支持
支持
CCE Turbo集群
共享型负载均衡
不支持
支持
独享型负载均衡
支持
不支持
说明:CCE Turbo集群中的Pod实例单独绑定ENI网卡,ELB直接对接Pod,因此不支持使用节点访问方式。
表2 Nginx Ingress支持的Service类型 集群类型
ELB类型
集群内访问(ClusterIP)
节点访问(NodePort)
CCE Standard集群
共享型负载均衡
支持
支持
独享型负载均衡
支持
支持
CCE Turbo集群
共享型负载均衡
支持
支持
独享型负载均衡
支持
支持
- 检查Service的访问端口号是否正确,此处Service的访问端口号(port字段)需区别于容器端口号(targetPort字段)。
- 检查Ingress对接的Service类型是否正确,Ingress支持的Service如下。
- 检查转发配置的参数是否填写正确
- 添加的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访问。
- 添加的URL转发路径要求后端应用内存在相同的路径,否则转发无法生效。
检查证书问题
CCE的Ingress密钥证书类型为IngressTLS或kubernetes.io/tls,若证书类型不正确,创建的Ingress将无法在ELB侧建立监听器,导致Ingress访问异常。
- 首先去除YAML中关于HTTPS的参数,尝试创建HTTP类型的Ingress是否可正常访问。
如HTTP访问正常,则考虑HTTPS密钥证书是否存在问题。
- 排除密钥类型错误。检查密钥类型是否为IngressTLS或kubernetes.io/tls类型。
kubectl get secret
回显如下:
NAME TYPE DATA AGE ingress IngressTLS 2 36m
- 创建测试证书,排除证书问题。
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN={YOUR_HOST}/O={YOUR_HOST}"
- 使用测试的私钥证书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加密后的内容。