问题现象
在集群内部(节点上或容器中),无法使用Service的ELB地址访问负载。
问题场景一:Service设置了服务亲和为节点级别
问题原因
当Service设置了服务亲和为节点级别,即externalTrafficPolicy取值为Local时,在使用中可能会碰到从集群内部(节点上或容器中)访问不通的情况,回显类似如下内容:
upstream connect error or disconnect/reset before headers. reset reason: connection failure
或:
curl: (7) Failed to connect to **.**.**.** port 900: Connection refused
或:
curl: (28) Failed to connect to **.**.**.** port 1122: Connection timed out
当externalTrafficPolicy的取值为Local时,在不同容器网络模型和服务转发模式下访问不通的场景如下:
- 多实例的工作负载需要保证所有实例均可正常访问,否则可能出现概率性访问不通的情况。
- 表格中仅列举了可能存在访问不通的场景,其他不在表格中的场景即表示可以正常访问。
- 使用IPVS转发模式的集群,Service亲和级别支持配置为节点级别(即externalTrafficPolicy的取值为Local)的场景,其中未开启Dataplane V2的CCE Turbo集群仅当Service的后端对接使用主机网络(HostNetwork)的Pod时,亲和级别支持配置为节点级别。
-
| 服务端发布服务类型 | 访问类型 | 客户端请求发起位置 | 容器隧道网络集群 | VPC网络集群(未开启Dataplane V2,开启Dataplane V2后的场景请参见开启Dataplane V2的集群) | CCE Turbo集群(未开启Dataplane V2,开启Dataplane V2后的场景请参见开启Dataplane V2的集群) |
| 节点访问类型Service | 公网/私网 | 与服务Pod同节点 | 访问服务端所在节点IP+NodePort — 正常访问 访问非服务端所在节点IP+NodePort — 无法访问 | 访问服务端所在节点IP+NodePort — 正常访问 访问非服务端所在节点IP+NodePort — 无法访问 | 正常访问 |
| 与服务Pod不同节点 | 访问服务端所在节点IP+NodePort — 正常访问 访问其他节点IP+NodePort — 无法访问 | 访问服务端所在节点IP+NodePort — 正常访问 访问客户端所在节点私网IP+NodePort — 正常访问 访问客户端所在节点公网IP+NodePort — 无法访问 访问其他节点IP+NodePort ——无法访问 | 正常访问 |
| 与服务Pod同节点的其他容器 | 访问服务端所在节点IP+NodePort — 正常访问 访问非服务端所在节点IP+NodePort — 无法访问 | 访问服务端所在节点公网IP+NodePort — 正常访问 访问服务端所在节点私网IP+NodePort — 无法访问 访问非服务端所在节点IP+NodePort — 无法访问 | 正常访问 |
| 与服务Pod不同节点的其他容器 | 访问服务端所在节点IP+NodePort — 正常访问 访问客户端所在节点私网IP+NodePort — 正常访问 访问其他节点IP+NodePort ——无法访问 | 访问服务端所在节点IP+NodePort — 正常访问 访问客户端所在节点私网IP+NodePort — 正常访问 访问其他节点IP+NodePort ——无法访问 | 正常访问 |
| 独享型负载均衡类型Service | 私网 | 与服务Pod同节点 | 无法访问 | 无法访问 | 正常访问 |
| 与服务Pod同节点的其他容器 | 无法访问 | 无法访问 | 正常访问 |
- 使用IPTABLES转发模式的集群,Service亲和级别支持配置为节点级别(即externalTrafficPolicy的取值为Local)的场景,其中未开启Dataplane V2的CCE Turbo集群仅当Service的后端对接使用主机网络(HostNetwork)的Pod时,亲和级别支持配置为节点级别。
-
| 服务端发布服务类型 | 访问类型 | 客户端请求发起位置 | 容器隧道集群 | VPC集群(未开启Dataplane V2,开启Dataplane V2后的场景请参见开启Dataplane V2的集群) | CCE Turbo集群(未开启Dataplane V2,开启Dataplane V2后的场景请参见开启Dataplane V2的集群) |
| 节点访问类型Service | 公网/私网 | 与服务Pod同节点 | 访问服务端所在节点IP+NodePort — 正常访问 访问非服务端所在节点IP+NodePort — 无法访问 | 访问服务端所在节点IP+NodePort — 正常访问 访问非服务端所在节点IP+NodePort — 无法访问 | 正常访问 |
| 与服务Pod不同节点 | 访问服务端所在节点IP+NodePort — 正常访问 访问客户端所在节点私网IP+NodePort — 正常访问 访问客户端所在节点公网IP+NodePort — 无法访问 访问其他节点IP+NodePort ——无法访问 | 访问服务端所在节点IP+NodePort — 正常访问 访问客户端所在节点私网IP+NodePort — 正常访问 访问客户端所在节点公网IP+NodePort — 无法访问 访问其他节点IP+NodePort ——无法访问 | 正常访问 |
| 与服务Pod同节点的其他容器 | 访问服务端所在节点IP+NodePort — 正常访问 访问非服务端所在节点IP+NodePort — 无法访问 | 访问服务端所在节点公网IP+NodePort — 正常访问 访问服务端所在节点私网IP+NodePort — 无法访问 访问非服务端所在节点IP+NodePort — 无法访问 | 正常访问 |
| 与服务Pod不同节点的其他容器 | 访问服务端所在节点IP+NodePort — 正常访问 访问非服务端所在节点IP+NodePort — 无法访问 | 访问服务端所在节点IP+NodePort — 正常访问 访问非服务端所在节点IP+NodePort — 无法访问 | 正常访问 |
| 独享型负载均衡类型Service | 私网 | 与服务Pod同节点 | 无法访问 | 无法访问 | 正常访问 |
| 与服务Pod同节点的其他容器 | 无法访问 | 无法访问 | 正常访问 |
- 开启Dataplane V2的集群,Service亲和级别支持配置为节点级别(即externalTrafficPolicy的取值为Local)的场景。
仅VPC集群和CCE Turbo集群支持开启Dataplane V2,开启后集群内不再使用kube-proxy,无需选择服务转发模式。详情请参见DataPlane V2网络加速说明。
-
| 服务端发布服务类型 | 访问类型 | 客户端请求发起位置 | VPC集群(开启DataPlane V2替换kube-proxy) | CCE Turbo集群(开启DataPlane V2替换kube-proxy) |
| 节点访问类型Service | 公网/私网 | 与服务Pod同节点 | 访问服务端所在节点IP+NodePort — 正常访问 访问非服务端所在节点私网IP+NodePort — 正常访问 访问非服务端所在节点公网IP+NodePort — 无法访问 | 访问服务端所在节点IP+NodePort — 正常访问 访问非服务端所在节点私网IP+NodePort — 正常访问 访问非服务端所在节点公网IP+NodePort — 无法访问 |
| 与服务Pod不同节点 | 访问服务端所在节点IP+NodePort — 正常访问 访问非服务端所在节点私网IP+NodePort — 正常访问 访问非服务端所在节点公网IP+NodePort — 无法访问 | 访问服务端所在节点IP+NodePort — 正常访问 访问非服务端所在节点私网IP+NodePort — 正常访问 访问非服务端所在节点公网IP+NodePort — 无法访问 |
| 与服务Pod同节点的其他容器 | 访问服务端所在节点IP+NodePort — 正常访问 访问其他节点IP+NodePort — 无法访问 | 访问服务端所在节点IP+NodePort — 正常访问 访问其他节点IP+NodePort — 无法访问 |
| 与服务Pod不同节点的其他容器 | 访问服务端所在节点IP+NodePort — 正常访问 访问客户端所在节点私网IP+NodePort — 正常访问 访问其他节点IP+NodePort ——无法访问 | 访问服务端所在节点IP+NodePort — 正常访问 访问客户端所在节点私网IP+NodePort — 正常访问 访问其他节点IP+NodePort ——无法访问 |
| 独享型负载均衡类型Service | 私网 | 与服务Pod同节点 | 无法访问 | 无法访问 |
| 与服务Pod同节点的其他容器 | 无法访问 | 正常访问 |
解决办法
解决这个问题通常有如下办法:
- (推荐)在集群内部访问使用Service的ClusterIP或服务域名访问。
- 将Service的externalTrafficPolicy设置为Cluster,即集群级别服务亲和。不过需要注意这会影响源地址保持,因为集群会进行网络地址转换,后端应用将无法获取客户端的真实IP。
apiVersion: v1
kind: Service
metadata:
annotations:
kubernetes.io/elb.class: union
kubernetes.io/elb.autocreate: '{"type":"public","bandwidth_name":"cce-bandwidth","bandwidth_chargemode":"traffic","bandwidth_size":5,"bandwidth_sharetype":"PER","eip_type":"5_bgp","name":"james"}'
labels:
app: nginx
name: nginx
spec:
externalTrafficPolicy: Cluster
ports:
- name: service0
port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx
type: LoadBalancer - 使用Service的pass-through特性,使用ELB地址访问时绕过kube-proxy,先访问ELB,经过ELB再访问到负载。详情请参见为负载均衡类型的Service配置pass-through能力。
- 在CCE Standard集群中,当使用独享型负载均衡配置pass-through后,从工作负载Pod所在节点或同节点的其他容器中访问ELB的私网IP地址,会出现无法访问的问题。
- v1.19及以上集群版本支持。
- IPVS网络模式下,对接同一个ELB的Service需保持pass-through设置情况一致。
- 使用节点级别(Local)的服务亲和的场景下,会自动设置kubernetes.io/elb.pass-through为onlyLocal,开启pass-through能力。
apiVersion: v1
kind: Service
metadata:
annotations:
kubernetes.io/elb.pass-through: "true"
kubernetes.io/elb.class: union
kubernetes.io/elb.autocreate: '{"type":"public","bandwidth_name":"cce-bandwidth","bandwidth_chargemode":"traffic","bandwidth_size":5,"bandwidth_sharetype":"PER","eip_type":"5_bgp","name":"james"}'
labels:
app: nginx
name: nginx
spec:
externalTrafficPolicy: Local
ports:
- name: service0
port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx
type: LoadBalancer
问题场景二:IPVS转发模式的集群中ELB实例复用
问题原因
IPVS转发模式的集群中,存在以下两种场景可能导致ELB地址访问不通:
- ELB Ingress和Service关联使用相同的ELB实例,集群内访问Ingress时会被ipvs-0网桥劫持到Service地址,导致无法访问。
- 本集群的Service和其他集群的Service关联使用相同的ELB实例,集群内访问其他集群的Service时会被ipvs-0网桥劫持到本集群内的Service地址,导致无法访问。
问题场景三:IPVS转发模式的集群中负载均衡类Service使用区间端口
问题原因
Service的“区间端口监听”支持通过ELB实现范围端口的监听能力(例如端口范围为30000-30005),但集群内访问仅支持spec.ports中配置的port端口(30000),其余端口(30001-30005)会因为ipvs-0网桥劫持访问失败。