为何GKE中创建每个Ingress都会分配不同的IP地址?
嘿,这个问题我熟!在GKE里用GCE Ingress的时候,默认每个Ingress都会触发创建一个独立的负载均衡器,所以每次都会分配新IP——你遇到的交替两个IP的情况,应该是项目的LB配额到顶了(默认HTTP(S) LB配额一般是2个),控制器只能在已有的两个LB里复用,才会出现这种情况。
要实现单个IP承载多应用的负载均衡,核心就是让所有Ingress共享同一个静态IP和同一个负载均衡器,下面给你两种实操方案,按需选:
方案1:复用静态IP+合并多Ingress到同一LB(推荐)
这个方案适合你跨命名空间维护多个Ingress的场景,不需要大改现有结构,只需要给Ingress加几个关键注解。
第一步:创建全局静态IP
GCE的HTTP(S)负载均衡是全局级别的,所以先创建一个全局静态IP:
gcloud compute addresses create shared-ingress-ip --global
查看并记录这个IP:
gcloud compute addresses describe shared-ingress-ip --global --format="value(address)"
第二步:修改所有Ingress配置
给每个命名空间的Ingress添加两个核心注解:
kubernetes.io/ingress.global-static-ip-name: "shared-ingress-ip":指定我们刚创建的静态IP名称kubernetes.io/ingress.lb-name: "shared-lb":给所有Ingress设置同一个LB名称,GCE控制器会自动把它们合并到同一个负载均衡器
同时,每个Ingress要配置不同的host规则(或路径),让LB能区分路由到对应服务。比如:
命名空间app1的Ingress:
apiVersion: extensions/v1beta1 kind: Ingress metadata: annotations: kubernetes.io/ingress.class: gce kubernetes.io/ingress.global-static-ip-name: "shared-ingress-ip" kubernetes.io/ingress.lb-name: "shared-lb" name: app1-ingress namespace: app1 spec: rules: - host: app1.yourdomain.com http: paths: - path: /* backend: serviceName: http-svc servicePort: 80
命名空间app2的Ingress:
apiVersion: extensions/v1beta1 kind: Ingress metadata: annotations: kubernetes.io/ingress.class: gce kubernetes.io/ingress.global-static-ip-name: "shared-ingress-ip" kubernetes.io/ingress.lb-name: "shared-lb" name: app2-ingress namespace: app2 spec: rules: - host: app2.yourdomain.com http: paths: - path: /* backend: serviceName: app2-svc servicePort: 80
注意事项
- 所有Ingress的
kubernetes.io/ingress.lb-name必须完全一致,否则控制器会创建新LB - 如果需要HTTPS,可创建GKE托管证书,然后给所有Ingress添加
networking.gke.io/managed-certificates: "your-cert-name"注解,证书会自动绑定到静态IP - 静态IP创建后不要随意删除,否则LB会丢失IP;更换IP时要先创建新IP、更新Ingress,等LB生效后再删除旧IP
方案2:用单个Ingress统一管理跨命名空间服务
如果你想简化Ingress维护,可在一个中心命名空间(比如default)创建单个Ingress,统一配置所有路由规则。但Kubernetes Ingress默认只能引用同命名空间服务,所以需要用Service Export/Import实现跨命名空间访问:
第一步:导出目标服务
在服务所在命名空间(比如app1)创建ServiceExport:
apiVersion: networking.x-k8s.io/v1alpha1 kind: ServiceExport metadata: name: http-svc namespace: app1
第二步:导入服务到中心命名空间
在中心命名空间(比如default)创建ServiceImport:
apiVersion: networking.x-k8s.io/v1alpha1 kind: ServiceImport metadata: name: app1-http-svc namespace: default spec: type: ClusterSetIP ports: - port: 80 protocol: TCP workloadSelectors: - namespace: app1 labels: app: http-svc
第三步:配置全局Ingress
在中心命名空间创建Ingress,引用所有导入的服务:
apiVersion: extensions/v1beta1 kind: Ingress metadata: annotations: kubernetes.io/ingress.class: gce kubernetes.io/ingress.global-static-ip-name: "shared-ingress-ip" name: global-ingress namespace: default spec: rules: - host: app1.yourdomain.com http: paths: - path: /* backend: serviceName: app1-http-svc servicePort: 80 - host: app2.yourdomain.com http: paths: - path: /* backend: serviceName: app2-http-svc servicePort: 80
这个方案适合统一管理路由,但需要维护Service Export/Import,相对方案1稍显繁琐。
内容的提问来源于stack exchange,提问作者Suhas Chikkanna

