第六篇:《Service 与 Ingress:服务暴露与负载均衡》
Pod 的 IP 是动态的不能直接作为稳定访问入口。Kubernetes 通过 Service 抽象为一组 Pod 提供固定的访问端点IP/DNS并实现负载均衡。而 Ingress 则提供七层路由基于域名、路径将外部流量路由到集群内的 Service。本文将详细讲解 Service 的四种类型ClusterIP、NodePort、LoadBalancer、ExternalName以及 Ingress 的工作原理和典型配置。一、为什么需要 ServicePod 可能被重建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:300802.3 LoadBalancer在 NodePort 基础上自动向云厂商申请一个外部负载均衡器如 AWS ELB、GCE LB、Azure LB。本地测试可使用 MetalLB 模拟。适用于公有云生产环境。YAML 示例apiVersion:v1kind:Servicemetadata:name:nginx-lbspec:type:LoadBalancerselector:app:nginxports:-port:80targetPort:80查看外部 IPkubectl 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 不分配虚拟 IPKube-DNS 直接返回 Pod IP 列表。适用于 StatefulSet 或需要直接访问每个 Pod 的场景。apiVersion:v1kind:Servicemetadata:name:mysql-headlessspec:clusterIP:Noneselector:app:mysqlports:-port:3306查询 DNSnslookup mysql-headless 返回所有符合标签的 Pod IP。五、Ingress七层路由Ingress 提供 HTTP/HTTPS 路由根据域名和路径将外部流量转发到不同的 Service。需要部署 Ingress Controller如 Nginx Ingress、Traefik、Contour才能生效。5.1 部署 Nginx Ingress Controllerkubectl 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可选不指定则匹配所有域名。pathTypePrefix前缀匹配、Exact精确匹配、ImplementationSpecific由 Controller 决定。tls引用包含证书的 Secret。5.3 创建 TLS Secretkubectl create secret tls example-tls--certpath/to/tls.crt--keypath/to/tls.key5.4 查看 Ingress 地址kubectl get ingress输出会显示 ADDRESS通常是 LB 的 IP。六、访问测试与调试测试 ClusterIPkubectl run test --imagebusybox -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 提供了灵活的七层路由。理解这几种资源你可以设计出安全、可伸缩的服务暴露方案。