第六篇:《Service 与 Ingress:服务暴露与负载均衡》
Pod 的 IP 是动态的,不能直接作为稳定访问入口。Kubernetes 通过 Service 抽象为一组 Pod 提供固定的访问端点(IP/DNS),并实现负载均衡。而 Ingress 则提供七层路由(基于域名、路径),将外部流量路由到集群内的 Service。本文将详细讲解 Service 的四种类型(ClusterIP、NodePort、LoadBalancer、ExternalName)以及 Ingress 的工作原理和典型配置。
一、为什么需要 Service?
Pod 可能被重建,IP 变化。
多副本 Pod 需要负载均衡。
需要对内部服务发现提供稳定的 DNS 名称。
需要将外部流量引入集群。
Service 通过标签选择器匹配 Pod,并自动维护 Endpoints 列表(Pod IP + 端口)。
二、Service 的四种类型
2.1 ClusterIP(默认)
分配一个虚拟 IP(仅集群内部可访问)。
用于集群内部通信,例如后端服务调用数据库。
YAML 示例:
apiVersion:v1kind:Servicemetadata:name:nginx-svcspec:type:ClusterIPselector:app:nginxports:-protocol:TCPport:80# Service 暴露的端口targetPort:80# Pod 上的端口访问方式:nginx-svc.default.svc.cluster.local 或直接 nginx-svc(同命名空间下)。
2.2 NodePort
在 ClusterIP 基础上,在每个节点上打开一个端口(默认 30000-32767)。
外部可以通过 : 访问。
适合开发测试或不想用负载均衡器的场景。
YAML 示例:
apiVersion:v1kind:Servicemetadata:name:nginx-nodeportspec:type:NodePortselector:app:nginxports:-port:80targetPort:80nodePort:30080# 可选,不指定则自动分配访问:curl http://任意节点IP:30080
2.3 LoadBalancer
在 NodePort 基础上,自动向云厂商申请一个外部负载均衡器(如 AWS ELB、GCE LB、Azure LB)。
本地测试可使用 MetalLB 模拟。
适用于公有云生产环境。
YAML 示例:
apiVersion:v1kind:Servicemetadata:name:nginx-lbspec:type:LoadBalancerselector:app:nginxports:-port:80targetPort:80查看外部 IP:kubectl get svc nginx-lb 等待 EXTERNAL-IP 分配。
2.4 ExternalName
将 Service 映射到外部的 DNS 名称,不会创建任何代理或负载均衡。
用于集群内部访问外部服务(如数据库、第三方 API)。
YAML 示例:
apiVersion:v1kind:Servicemetadata:name:external-dbspec:type:ExternalNameexternalName:mydb.example.com集群内 Pod 可通过 external-db.default.svc.cluster.local 访问 mydb.example.com。
三、Service 的工作原理
kube-proxy 在每个节点上运行,监控 Service 和 Endpoints 的变化。
维护 iptables 或 IPVS 规则,将 Service 的虚拟 IP 流量负载均衡到后端 Pod。
默认使用轮询算法(iptables 随机选择,IPVS 支持更多调度算法)。
四、Headless Service
当 clusterIP: None 时,Service 不分配虚拟 IP,Kube-DNS 直接返回 Pod IP 列表。适用于 StatefulSet 或需要直接访问每个 Pod 的场景。
apiVersion:v1kind:Servicemetadata:name:mysql-headlessspec:clusterIP:Noneselector:app:mysqlports:-port:3306查询 DNS:nslookup mysql-headless 返回所有符合标签的 Pod IP。
五、Ingress:七层路由
Ingress 提供 HTTP/HTTPS 路由,根据域名和路径将外部流量转发到不同的 Service。需要部署 Ingress Controller(如 Nginx Ingress、Traefik、Contour)才能生效。
5.1 部署 Nginx Ingress Controller
kubectl apply-fhttps://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.1/deploy/static/provider/cloud/deploy.yaml5.2 Ingress YAML 示例
apiVersion:networking.k8s.io/v1kind:Ingressmetadata:name:web-ingressannotations:nginx.ingress.kubernetes.io/rewrite-target:/spec:rules:-host:www.example.comhttp:paths:-path:/apipathType:Prefixbackend:service:name:api-serviceport:number:8080-path:/pathType:Prefixbackend:service:name:web-serviceport:number:80tls:-hosts:-www.example.comsecretName:example-tlshost:可选,不指定则匹配所有域名。
pathType:Prefix(前缀匹配)、Exact(精确匹配)、ImplementationSpecific(由 Controller 决定)。
tls:引用包含证书的 Secret。
5.3 创建 TLS Secret
kubectl create secret tls example-tls--cert=path/to/tls.crt--key=path/to/tls.key5.4 查看 Ingress 地址
kubectl get ingress输出会显示 ADDRESS(通常是 LB 的 IP)。
六、访问测试与调试
测试 ClusterIP:kubectl run test --image=busybox -it --rm – sh,然后 wget -O- http://nginx-svc。
测试 NodePort:确保集群节点防火墙开放了 NodePort 端口,用浏览器访问 http://:。
测试 Ingress:配置本地 hosts 或真实域名,访问 http://www.example.com。
七、常见问题与解决
八、最佳实践
内部通信使用 ClusterIP,避免不必要的节点端口暴露。
外部访问优先使用 Ingress(七层),而非直接 NodePort,以获得域名、TLS、路径路由能力。
为 LoadBalancer Service 设置 externalTrafficPolicy: Local,保留客户端真实 IP。
对于 TCP/UDP 服务(如数据库、消息队列),可使用 NodePort 或 LoadBalancer,因为 Ingress 主要支持 HTTP/HTTPS。
使用 NetworkPolicy 控制 Service 访问权限(后续文章介绍)。
九、小结
Service 解决了 Pod 动态 IP 和负载均衡问题,Ingress 提供了灵活的七层路由。理解这几种资源,你可以设计出安全、可伸缩的服务暴露方案。
