Kubernetes旧版本Ingress Host自动追加命名空间问题咨询
问题场景
在Kubernetes v1.16.15中创建指向外部服务的Ingress资源,清单中指定的Host为mytest.internalurl.env-N.intranet,但创建后通过kubectl get ingress查看时,Host被自动追加了命名空间test-ns,变为mytest.test-ns.internalurl.env-N.intranet。
相关资源清单:
apiVersion: v1 kind: Endpoints metadata: name: mytest-service namespace: test-ns subsets: - addresses: - ip: X.X.X.X #External service IP ports: - name: port443 port: 9443 protocol: TCP --- apiVersion: v1 kind: Service metadata: name: mytest-service namespace: test-ns spec: ports: - name: port443 port: 443 protocol: TCP targetPort: 443 type: ClusterIP clusterIP: None --- apiVersion: extensions/v1beta1 kind: Ingress metadata: annotations: nginx.ingress.kubernetes.io/secure-backends: "true" nginx.ingress.kubernetes.io/ssl-passthrough: "false" nginx.ingress.kubernetes.io/ssl-redirect: "true" name: mytest-ingress namespace: test-ns spec: rules: - host: mytest.internalurl.env-N.intranet http: paths: - backend: serviceName: mytest-service servicePort: 443 path: /
Ingress创建后的查询结果:
kubectl get ingress mytest-ingress -n test-ns NAME HOSTS ADDRESS PORTS AGE mytest-ingress mytest.test-ns.internalurl.env-N.intranet IP1,IP2 80 10m
补充:集群内存在多个直接使用根域名internalurl.env-N.intranet的Ingress资源:
kubectl get ingress -A | grep ' internalurl.env-N.intranet' kube-system kube-system.manager internalurl.env-N.intranet IP1,IP2 80 539d otherNS usermanagement internalurl.env-N.intranet IP1,IP2 80 539d otherNS component1 internalurl.env-N.intranet IP1,IP2 80 539d otherNS componentN internalurl.env-N.intranet IP1,IP2 80 539d
原因分析
这是NGINX Ingress Controller的自动冲突规避机制导致的,核心逻辑是保证集群内Ingress的Host规则唯一,避免请求路由混乱:
根域名Ingress的冲突触发:当集群中存在多个Ingress直接绑定同一个根域名(
internalurl.env-N.intranet),而你的Ingress使用了该根域名的子域名(mytest.internalurl.env-N.intranet)时,Ingress Controller可能判定存在潜在路由冲突——根域名的Ingress规则会匹配所有未被子域名规则覆盖的请求,这可能导致子域名请求被错误路由到根域名的后端。为了避免这种情况,Controller会自动给子域名Ingress的Host添加命名空间前缀,强制生成唯一的Host规则。其他子域名Ingress未受影响的原因:如果集群中其他带自定义子域名的Ingress没有被添加命名空间,说明这些子域名的Host在集群内是唯一的,或者它们的子域名规则与根域名规则不存在冲突风险,因此Controller没有触发自动修正。
Controller配置参数的影响:旧版本的NGINX Ingress Controller(对应K8s v1.16的版本通常是0.20.x系列)可能通过
--hostname-template启动参数或ConfigMap中的hostname-template配置项开启了自动命名空间注入,该参数的格式通常为{{.Name}}.{{.Namespace}}.{{.Domain}},会自动生成包含命名空间的Host。
解决方案
1. 检查并调整Ingress Controller配置
查看Ingress Controller的启动参数或对应的ConfigMap(通常位于kube-system命名空间,名称为nginx-configuration),确认是否存在hostname-template配置:
- 如果存在该配置且不需要自动添加命名空间,可以删除或修改该配置项,然后重启Ingress Controller。
- 同时检查是否有
enable-mergeable-ingress等与Ingress规则合并相关的配置,这类配置也可能影响Host规则的生成。
2. 确保Ingress Host的唯一性
修改你的Ingress清单,指定一个在集群内完全唯一的Host,比如使用更具辨识度的子域名(如mytest-test-ns.internalurl.env-N.intranet),明确与其他Ingress的Host规则区分开,这样Controller就不会触发自动添加命名空间的逻辑。
3. 调整根域名Ingress的规则
如果根域名的Ingress不需要处理所有子域名的请求,可以给根域名Ingress添加nginx.ingress.kubernetes.io/server-snippet注解,明确限制其仅匹配无任何子域名的请求:
metadata: annotations: nginx.ingress.kubernetes.io/server-snippet: | if ($host != 'internalurl.env-N.intranet') { return 404; }
这样可以消除子域名Ingress与根域名Ingress的冲突风险,Controller就不会自动修改子域名Ingress的Host。
内容的提问来源于stack exchange,提问作者Rph

