Kubernetes不使用负载均衡时Ingress集群外访问异常
90%以上该场景下的空响应问题,是默认部署配置的externalTrafficPolicy: Local策略和externalIPs调度不匹配导致的:
DigitalOcean环境默认安装的NGINX Ingress Controller,对应的Service默认将externalTrafficPolicy设为Local,该模式下节点收到对应端口的外部流量后,只会转发给本节点本地运行的Ingress Controller Pod,不会做跨节点转发。给Service配置了单台虚拟机的IP作为externalIP后,只要Ingress Controller Pod没有被调度到这台虚拟机上,kube-proxy虽然会正常监听80端口让nc检测显示连通,但流量没有可用后端转发,会直接被丢弃,触发空响应错误。
调整Ingress Controller Service的流量策略
编辑ingress-nginx命名空间下的controller Service,将externalTrafficPolicy字段值改为Cluster,允许节点跨节点转发流量到Ingress Controller Pod:kubectl patch svc ingress-nginx-controller -n ingress-nginx -p '{"spec":{"externalTrafficPolicy":"Cluster"}}'如果不想改流量策略,也可以给Ingress Controller加节点亲和性规则,强制Pod调度到配置了公网IP的那台虚拟机上,两种方式选一种即可。
校验Ingress规则生效状态
执行以下命令查看Ingress资源的事件,确认规则被Ingress Controller正常加载:kubectl describe ingress <你创建的Ingress资源名>正常情况下Events栏不会出现报错,会显示规则被nginx控制器同步成功。如果提示找不到对应IngressClass,执行
kubectl get ingressclass确认集群中存在名为nginx的IngressClass资源,和Ingress里配置的ingressClassName: nginx匹配。临时关闭SSL强制跳转测试
部分版本的NGINX Ingress Controller默认开启全局HTTPS跳转,未配置443端口时可能触发异常响应,给Ingress资源添加如下注解关闭跳转:metadata: annotations: nginx.ingress.kubernetes.io/ssl-redirect: "false"节点侧连通性校验
登录到公网IP所属的虚拟机,直接在节点本地执行curl访问Ingress Controller的Pod端口:# 查询Ingress Controller Pod的http服务端口 kubectl get svc ingress-nginx-controller -n ingress-nginx -o jsonpath='{.spec.ports[?(@.name=="http")].targetPort}' # 本地访问测试,替换<端口>为上面查到的值 curl http://127.0.0.1:<端口>如果本地访问能正常返回NGINX欢迎页,说明Ingress服务本身正常,问题出在外部流量转发环节,检查虚拟机的防火墙、安全组规则,确认80端口的入站、转发规则已经放通。
配置完成后,在集群外的机器上执行curl http://<你的虚拟机公网IP>,即可正常返回后端NGINX的默认欢迎页面。
内容的提问来源于stack exchange,提问作者Ryan

