能否为多个Kubernetes服务暴露同一外部IP地址?
问题描述
我有多个实现不同功能的镜像,目前通过以下命令部署并暴露服务:
kubectl create deployment work_deployment_1 --image=username/work_image_1:0.0.1-SNAPSHOT kubectl expose deployment work_deployment_1 --type=LoadBalancer --port=8000
随后执行:
kubectl create deployment work_deployment_2 --image=username/work_image_2:0.0.1-SNAPSHOT kubectl expose deployment work_deployment_2 --type=LoadBalancer --port=9000
部署并暴露完成后,执行kubectl get service查看,结果如下:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE work_deployment_1 LoadBalancer 10.245.197.226 159.65.210.104 8000:30798/TCP 30m work_deployment_2 LoadBalancer 10.245.168.156 159.65.129.201 9000:32105/TCP 51s
请问能否通过部署配置,让这些服务通过same_external-ip:8000和same_external-ip:9000暴露,而非当前的不同外部IP端口组合?
解决方案
完全可以实现,下面是两种常用的落地方法:
方法一:无Selector LoadBalancer + Endpoints(通用TCP/UDP场景)
这种方式适合所有TCP/UDP类型的服务,不需要依赖额外的Ingress组件:
- 先清理现有LoadBalancer服务,把两个服务转为ClusterIP类型(默认就是ClusterIP,无需额外指定):
kubectl delete service work_deployment_1 work_deployment_2 kubectl expose deployment work_deployment_1 --name=service1 --port=8000 kubectl expose deployment work_deployment_2 --name=service2 --port=9000
- 创建一个不带Pod选择器的LoadBalancer服务,定义需要暴露的两个端口:
新建文件unified-lb.yaml:
apiVersion: v1 kind: Service metadata: name: unified-lb spec: type: LoadBalancer ports: - name: service1-port port: 8000 protocol: TCP - name: service2-port port: 9000 protocol: TCP
执行创建:
kubectl apply -f unified-lb.yaml
- 创建Endpoints资源,手动将LoadBalancer的端口映射到对应的ClusterIP服务:
先执行kubectl get service service1 service2拿到两个服务的ClusterIP,然后新建unified-endpoints.yaml:
apiVersion: v1 kind: Endpoints metadata: name: unified-lb # 必须和上面的LoadBalancer服务同名 subsets: - addresses: - ip: <service1的ClusterIP> # 替换成实际的ClusterIP值 ports: - name: service1-port port: 8000 protocol: TCP - addresses: - ip: <service2的ClusterIP> # 替换成实际的ClusterIP值 ports: - name: service2-port port: 9000 protocol: TCP
执行创建:
kubectl apply -f unified-endpoints.yaml
完成后,unified-lb服务会分配一个唯一的外部IP,访问外部IP:8000会转发到service1,外部IP:9000转发到service2。
方法二:Ingress Controller(HTTP/HTTPS优先,部分支持TCP/UDP)
如果你的服务是HTTP/HTTPS类型,推荐用这种方式,这是Kubernetes统一暴露服务的标准方案:
前提:集群已部署Ingress Controller(比如NGINX Ingress)
- 同样先清理现有LoadBalancer服务,转为ClusterIP:
kubectl delete service work_deployment_1 work_deployment_2 kubectl expose deployment work_deployment_1 --name=service1 --port=8000 kubectl expose deployment work_deployment_2 --name=service2 --port=9000
针对HTTP服务:
新建unified-ingress.yaml:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: unified-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: / spec: ingressClassName: nginx # 匹配你的Ingress Controller的className rules: - http: paths: - path: /service1 pathType: Prefix backend: service: name: service1 port: number: 8000 - path: /service2 pathType: Prefix backend: service: name: service2 port: number: 9000
执行创建:
kubectl apply -f unified-ingress.yaml
此时访问Ingress Controller的外部IP,外部IP/service1会转发到service1,外部IP/service2转发到service2。如果想用域名访问,只需在rules里添加host字段即可。
针对TCP服务(以NGINX Ingress为例):
需要额外配置Ingress Controller的TCP端口映射:
- 新建TCP配置的ConfigMap:
apiVersion: v1 kind: ConfigMap metadata: name: nginx-ingress-tcp namespace: ingress-nginx # 替换成你的Ingress Controller所在命名空间 data: "8000": "default/service1:8000" # 格式:"外部端口": "服务命名空间/服务名:服务端口" "9000": "default/service2:9000"
执行创建:
kubectl apply -f nginx-tcp-config.yaml
- 修改Ingress Controller的Deployment,添加端口挂载:
找到Ingress Controller的Deployment(通常在ingress-nginx命名空间),在容器的ports部分添加:
- name: tcp-8000 containerPort: 8000 protocol: TCP - name: tcp-9000 containerPort: 9000 protocol: TCP
- 修改Ingress Controller的Service(LoadBalancer类型),添加端口映射:
在Service的ports部分添加:
- name: tcp-8000 port: 8000 targetPort: 8000 protocol: TCP - name: tcp-9000 port: 9000 targetPort: 9000 protocol: TCP
完成后,Ingress Controller的外部IP就可以通过外部IP:8000和外部IP:9000分别访问两个服务。
内容的提问来源于stack exchange,提问作者hlx
相关产品推荐
相关产品推荐

