# 为什么NGINX Ingress控制器所在节点无法通过ELB私网地址访问Ingress？
#### 问题现象
在CCE集群中使用NGINX Ingress控制器插件对接ELB时，插件控制器Pod（名为cceaddon-nginx-ingress-controller）所在节点以及该节点上的其他业务容器，通过ELB的私网地址访问Ingress时出现访问不通或超时的现象。
#### 问题根因
该问题的根因是ELB开启"获取客户端IP"（源IP透传）功能后导致的流量回环。
当ELB开启"获取客户端IP"功能（即源IP透传）后，ELB在向后端服务器转发请求时，会保留客户端的真实源IP，而不做SNAT（源地址转换）。
具体流程如下：
1. 节点A上的业务Pod通过ELB私网地址发起访问请求，此时源IP为节点A的IP。
2. ELB收到请求后，将流量转发给后端服务器组中的NGINX Ingress控制器Pod（该Pod也位于节点A）。
3. 由于ELB开启了源IP透传，转发给后端的报文中源IP仍为节点A的IP。
4. 此时报文的源IP（节点A）与目的IP（节点A）相同，形成回环，内核协议栈无法正常处理该报文，导致访问不通。
 
#### 受影响场景
该问题**仅影响CCE Standard集群**，且与ELB类型和"获取客户端IP"功能的开启状态直接相关：
| 集群类型          | ELB类型  | 获取客户端IP状态       | 是否受影响 | 说明                        |
|:---|:---|:---|:---|:---|
| CCE Standard   | 独享型ELB   | 默认开启         | 是       | 独享型ELB默认开启源IP透传，必然受此限制影响   |
| CCE Standard | 共享型ELB   | 手动开启"获取客户端IP" | 是     | 手动开启后，与独享型ELB表现一致，会受此限制影响 |
| CCE Standard   | 共享型ELB  | 未开启"获取客户端IP" | 否       | ELB做SNAT，源地址与目的地址不同         |
| CCE Turbo      | 独享型/共享型 | 任意              | 否     | ENI网络模型，流量不经节点协议栈，无回环问题     |
   
#### 解决方案
#### 方案一：避免业务Pod与Ingress控制器Pod调度到同一节点（推荐）
通过配置Pod反亲和性（Pod Anti-Affinity），确保业务Pod不会调度到cceaddon-nginx-ingress-controller所在的节点上，从根源上避免源地址与目的地址相同的情况。
在业务工作负载的YAML中添加反亲和性配置，示例如下：
```
spec:
  template:
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - nginx-ingress
            topologyKey: kubernetes.io/hostname
```
上述示例中app: nginx-ingress为NGINX Ingress控制器Pod的标签。您可通过**kubectl get pods -n \<namespace\> --show-labels**查看控制器Pod的标签。
如果集群节点资源有限，使用requiredDuringSchedulingIgnoredDuringExecution（硬策略）可能导致Pod无法调度，可改为preferredDuringSchedulingIgnoredDuringExecution（软策略）。
#### 方案二：共享型ELB关闭"获取客户端IP"功能
如果使用的是共享型ELB，且业务上不需要在应用层获取客户端真实源IP，可以在ELB控制台关闭"获取客户端IP"功能。
关闭后，ELB会对转发流量做SNAT（源地址转换），源地址变为ELB的内网IP，与目的地址不同，从而避免回环问题。
![](https://support.huaweicloud.com/cce_faq/public_sys-resources/caution_3.0-zh-cn.png)
关闭"获取客户端IP"后，后端应用将无法获取客户端的真实源IP，请确认业务无此需求后再操作。
#### 方案三：使用ELB公网地址或域名访问
如果ELB已配置公网IP或域名，业务Pod可通过ELB的公网地址或域名访问Ingress，而非私网地址。
公网访问的流量路径与私网不同，流量经过公网网络转发后，源IP会经过NAT转换，不会与目的地址相同，从而避免回环问题。
![](https://support.huaweicloud.com/cce_faq/public_sys-resources/caution_3.0-zh-cn.png)
此方案要求ELB已配置公网IP，且业务Pod所在节点可访问公网。公网访问可能产生公网流量费用，且延迟可能略高于私网访问。
#### 方案四：直接访问后端Service
如果业务Pod仅需集群内部互相访问，可不经过Ingress，直接通过后端Service的ClusterIP或Service名称进行访问，绕过ELB。
```
# 通过ClusterIP访问
curl <service-clusterip>:<port>
# 通过Service名称访问（集群内DNS解析）
curl <service-name>.<namespace>.svc.cluster.local:<port>
```
![](https://support.huaweicloud.com/cce_faq/public_sys-resources/note_3.0-zh-cn.png)
此方案绕过了Ingress的转发规则和域名匹配逻辑，仅适用于集群内部简单访问场景。
