Service 是 Kubernetes 微服务架构中实现稳定服务发现与流量调度的基础设施,合理设计可极大提升系统的可用性与可维护性。
在 Kubernetes 集群中,Pod 具有生命周期性,IP 地址并不总是稳定可靠。通过 ReplicaSet 或 Deployment 等控制器可以动态地创建和销毁 Pod。对于需要为其他 Pod 提供服务的一组后端 Pod,前端应用如何发现并连接这些后端 Pod,是微服务架构中的关键问题。
Kubernetes Service(服务)定义了一种抽象,将一组功能相同的 Pod 逻辑分组,并通过标签选择器(Label Selector)实现流量路由。Service 能够为后端 Pod 提供统一的访问入口,解耦前后端依赖,提升系统弹性。
例如,一个图像处理服务运行了多个副本,前端应用无需关心具体调用哪个 Pod,Service 负责将请求分发到后端所有可用副本。Pod 的变更(如重启、扩缩容)不会影响客户端访问,Service 抽象实现了这种解耦。
对于集群内应用,Kubernetes 提供 Endpoints API 自动更新后端地址。对于集群外访问,Service 通过虚拟 IP(VIP)实现统一入口,自动路由到后端 Pod。
Service 是 Kubernetes 的 REST 对象,可通过 YAML/JSON 配置并提交到 API Server 创建。
以下为典型 Service 配置示例:
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: MyApp
ports:
- protocol: TCP
port: 80
targetPort: 9376
该 Service 会将流量转发到所有带有 app=MyApp 标签的 Pod 的 9376 端口,并分配一个集群内部 IP(Cluster IP)。Service 的选择器持续评估,自动更新同名 Endpoints 对象。
targetPort 可为数字或字符串(引用容器端口名),便于后端升级时端口变更而不影响客户端调用。Service 支持 TCP、UDP、SCTP 协议,默认 TCP。
Service 也可用于代理集群外部服务或特殊场景(如跨 Namespace、混合部署),此时无需 selector:
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9376
需手动创建 Endpoints:
apiVersion: v1
kind: Endpoints
metadata:
name: my-service
subsets:
- addresses:
- ip: 1.2.3.4
ports:
- port: 9376
Endpoint IP 不能为回环、链路本地或多播地址。
Kubernetes 支持多种 ServiceType,满足不同访问需求。
| 类型 | 说明 | 典型场景 |
|---|---|---|
| ClusterIP | 仅集群内可访问(默认) | 内部微服务通信 |
| NodePort | 每个 Node 分配静态端口,外部可通过 <NodeIP>:<NodePort> 访问 |
开发测试、简单暴露 |
| LoadBalancer | 云厂商负载均衡器,自动分配外部 IP | 生产级外部访问 |
| ExternalName | 通过 CNAME 指向外部 DNS 名称 | 代理外部服务 |
仅集群内部可访问,适合微服务间通信。
每个 Node 分配静态端口,外部可通过 <NodeIP>:<NodePort> 访问。端口范围默认 30000-32767。
云平台自动创建负载均衡器,分配外部 IP,适合生产环境暴露服务。
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: MyApp
ports:
- protocol: TCP
port: 80
targetPort: 9376
type: LoadBalancer
status:
loadBalancer:
ingress:
- ip: 146.148.47.155
通过 CNAME 方式代理外部服务,无需代理流量。
apiVersion: v1
kind: Service
metadata:
name: my-service
namespace: prod
spec:
type: ExternalName
externalName: my.database.example.com
ExternalName 不能直接解析为 IP,推荐用于 DNS 名称代理。
每个 Node 运行 kube-proxy,负责实现 Service 虚拟 IP(VIP)代理。
kube-proxy 监控 Service/Endpoints 变化,自动生成 iptables 规则,将流量重定向到后端 Pod。支持基于客户端 IP 的会话亲和性(service.spec.sessionAffinity: ClientIP)。
{width=600 height=400}
基于内核 IPVS,性能优于 iptables,支持多种负载均衡算法(轮询、最少连接、哈希等),适合大规模集群。
Service 支持暴露多个端口,需为每个端口命名,避免歧义。
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: MyApp
ports:
- name: http
protocol: TCP
port: 80
targetPort: 9376
- name: https
protocol: TCP
port: 443
targetPort: 9377
可通过 spec.clusterIP 指定自定义集群 IP,需在 --service-cluster-ip-range 范围内。若无效,API Server 返回 422 错误。
Kubernetes 支持环境变量和 DNS 两种服务发现方式。
Pod 启动时,kubelet 为每个 Service 注入环境变量(如 REDIS_MASTER_SERVICE_HOST)。需注意 Service 必须先于 Pod 创建。
推荐方式。集群内 DNS 服务器为每个 Service 创建 DNS 记录,支持 A 记录和 SRV 记录。跨 Namespace 需使用全限定名(如 my-service.my-ns)。
如无需负载均衡和 VIP,可将 spec.clusterIP 设为 "None",实现 Headless Service。此时 DNS 直接返回所有后端 Pod 的 IP,适合自注册、状态同步等场景。
Service 可通过 externalIPs 字段暴露外部 IP,需由集群管理员保证路由可达。
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: MyApp
ports:
- name: http
protocol: TCP
port: 80
targetPort: 9376
externalIPs:
- 80.11.12.10
Kubernetes 为每个 Service 分配唯一 VIP,避免端口冲突。VIP 通过 iptables 或 IPVS 规则实现,客户端访问 VIP 时自动转发到后端 Pod。
Service 是 Kubernetes 顶级 REST 资源,详细字段见 Service API 对象。
Kubernetes Service 通过标签选择器、虚拟 IP、灵活的代理和服务发现机制,实现了微服务架构下的高可用、可扩展和易维护的服务访问。建议结合实际场景选择合适的 Service 类型和发现方式,提升系统健壮性。