在Kubernetes中,Pod的IP地址是易变的。当Deployment进行滚动更新、节点故障或Pod被驱逐时,新的Pod会分配到不同的IP。如果客户端在配置文件中写死某一个Pod的IP,一旦Pod重建,访问就会失败。Service资源正是为了解决这一稳定性问题而引入的。它通过一个稳定的虚拟IP(ClusterIP)和一个DNS名称来抽象一组Pod,客户端只需要访问Service,而不需要关心具体由哪个Pod响应。

Service的核心机制:标签选择器与Endpoints
Service本身并不直接运行任何进程,它只是一个逻辑抽象。它通过selector字段定义一组标签选择条件,凡是带有匹配标签的Pod都会被纳入这个Service的后端集合。例如,一个Service的selector设置为app: nginx,那么所有带有该标签的Pod都会成为它的流量目标。当Pod因扩缩容或故障发生变化时,Kubernetes会自动更新Service对应的Endpoints对象,无需人工干预。
每个Service在创建后会获得一个固定的ClusterIP,这个IP在Service的生命周期内保持不变。集群内部的DNS服务(如CoreDNS)会为Service生成一条解析记录,格式通常为服务名.命名空间.svc.cluster.local。这样一来,集群内的其他应用就可以通过这个DNS名称来访问服务,而不必关心ClusterIP的具体数值。客户端发往ClusterIP的请求会被kube-proxy组件拦截,并根据一定规则转发到后端的某个Pod。
Service的四种主要类型及适用场景
Kubernetes提供了多种Service类型,最常见的是ClusterIP、NodePort、LoadBalancer和ExternalName。默认创建的Service类型是ClusterIP,它只允许集群内部通信。如果你希望服务能够被集群外部的用户访问,就需要选择NodePort、LoadBalancer或者结合Ingress来暴露服务。下面分别说明它们的工作方式和适用场景。
ClusterIP类型是基础。它只在一个集群内部IP上暴露服务,适合用于微服务架构中服务与服务之间的调用。例如,一个订单服务需要调用用户服务,订单服务只需要知道用户服务的DNS名称,而不需要让用户服务暴露到公网。ClusterIP的优势是安全、简单,缺点是只能内网访问。
NodePort类型会在所有Node上打开同一个端口,并把该端口映射到Service的端口。用户可以通过任意节点的IP加上该端口访问服务。例如,NodePort设置为30080,那么访问http://节点IP:30080即可到达Service。NodePort的优点是无需额外的外部负载均衡器即可实现外部访问,适合本地开发、测试环境或临时演示。缺点是端口范围有限(默认30000-32767),而且需要自行处理节点故障转移。
LoadBalancer类型是在NodePort的基础上,再向云厂商申请一个外部的负载均衡器。云厂商会自动创建负载均衡器并将流量转发到节点的NodePort端口。用户只需要访问负载均衡器的外部IP或域名即可。这种类型最适合生产环境,因为云负载均衡器可以提供高可用、TLS终结等能力。但缺点是会产生额外的成本,并且强依赖云平台。
ExternalName类型较为特殊,它不直接转发流量到Pod,而是为Service提供一个CNAME记录,将服务名映射到集群外部的某个DNS名称。例如,当集群内的应用需要访问一个外部数据库时,可以通过ExternalName将内部服务名指向该数据库的域名。这种类型没有ClusterIP,也没有端口转发,仅做DNS别名。
实战:创建Service公开应用
下面通过一个完整的示例来演示如何将一个Nginx应用通过Service公开。首先创建一个Deployment,确保Pod带有app: nginx标签。然后创建一个NodePort类型的Service,让外部流量可以通过节点端口访问。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
上面的Deployment会创建3个Nginx Pod副本,每个Pod都带有app: nginx标签。接下来定义Service,使用相同的selector来关联这些Pod,并将容器的80端口映射到Service的80端口。为了外部访问,设置type为NodePort。
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
type: NodePort
selector:
app: nginx
ports:
- port: 80
targetPort: 80
nodePort: 30080
在这个Service定义中,port是Service暴露的端口,其他服务或外部流量通过这个端口访问;targetPort是后端Pod上实际监听的端口,对应容器内的80端口;nodePort是每个节点上打开的端口,范围为30000到32767。如果省略nodePort,Kubernetes会自动分配一个。执行kubectl apply -f service.yaml后,可以使用kubectl get svc nginx-service查看Service的详细信息,其中会列出ClusterIP、NodePort和端口映射。
验证服务是否正常工作,可以在集群外通过任意节点的IP访问http://192.168.1.100:30080(假设节点IP为192.168.1.100)。如果浏览器显示Nginx欢迎页,说明Service已经成功将外部流量转发到了后端的某个Pod。此时即使你删除其中一个Pod,Deployment会重新创建一个新的Pod,Service仍然能够正常转发,因为标签匹配会自动更新Endpoints。
Service与Ingress的配合
虽然NodePort和LoadBalancer能够让服务被外部访问,但如果集群中运行了多个HTTP服务,每个服务都使用一个独立的NodePort或负载均衡器会带来管理上的负担。Ingress资源的作用是在七层(HTTP/HTTPS)上进行路由,它可以根据请求的域名和路径将流量分发到不同的Service。例如,api.ippipp.com的流量路由到API服务,web.ippipp.com路由到前端服务。
使用Ingress时,底层通常仍然需要一个LoadBalancer类型的Service来接收外部流量,或者使用Ingress Controller(如Nginx Ingress Controller)直接监听节点的端口。Ingress本身不直接取代Service,而是站在Service之上进行更精细的流量控制。在Ingress的规则中,通过backend.service.name引用目标Service的名称和端口。因此,创建Ingress之前,需要确保对应的Service已经是ClusterIP类型或NodePort类型,并且selector正确匹配Pod。
一个典型的Ingress规则如下所示,它将nginx.ippipp.com的请求转发到名为nginx-service的Service的80端口。注意,Ingress Controller需要根据实际环境进行部署,且域名解析需要指向Ingress Controller的入口地址。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-ingress
spec:
rules:
- host: nginx.ippipp.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx-service
port:
number: 80
排错指南:Service访问不通的常见原因
在实际使用中,Service无法正常转发流量是最常见的问题之一。排查时可以从以下几个方向入手。首先检查Service的selector是否与Pod的labels完全匹配。可以使用kubectl get endpoints 服务名查看Endpoints中是否列出了后端Pod的IP和端口。如果Endpoints为空,说明selector没有匹配到任何Pod,此时需要对比Service的selector和Pod的labels是否一致,包括键名和值的大小写。
其次,检查端口映射是否正确。port、targetPort和nodePort三者之间的关系容易被误解。如果Service的targetPort写错,即使Endpoints存在,转发也会失败。在Pod内部,可以使用kubectl exec进入容器,通过curl访问Service的ClusterIP和端口,快速验证Service的转发链路是否正常。
另外,网络策略(NetworkPolicy)也可能阻止流量到达Pod。默认情况下,Kubernetes集群内的网络策略是允许所有流量的,但如果集群管理员配置了默认拒绝规则,就需要显式放行相关流量。最后,如果使用的是NodePort类型,还要确认节点防火墙或安全组是否放行了对应的端口范围。在云环境中,LoadBalancer的配置错误也可能导致外部访问失败,此时应检查云控制台的负载均衡器状态。
Kubernetes Service服务发现负载均衡修改时间:2026-08-26 19:29:35