Kubernetes Service类型详解
约 1388 字大约 5 分钟
kubernetesservice
2025-06-10
Service 是 Kubernetes 中实现服务发现和负载均衡的核心抽象。它为一组 Pod 提供稳定的网络端点,屏蔽了 Pod IP 的动态变化。本文将深入讲解各种 Service 类型及其底层实现。
Service 架构总览
ClusterIP(默认类型)
ClusterIP 分配一个集群内部虚拟 IP,只能在集群内部访问:
apiVersion: v1
kind: Service
metadata:
name: backend-service
spec:
type: ClusterIP # 默认值,可省略
selector:
app: backend
ports:
- name: http
protocol: TCP
port: 80 # Service 端口
targetPort: 8080 # Pod 端口
- name: grpc
protocol: TCP
port: 9090
targetPort: 9090# 集群内通过 DNS 访问
curl http://backend-service.default.svc.cluster.local:80
# 同命名空间可简写
curl http://backend-service:80手动指定 ClusterIP
spec:
type: ClusterIP
clusterIP: 10.96.100.50 # 手动指定,必须在 service-cluster-ip-range 范围内NodePort
NodePort 在每个节点上暴露一个端口(30000-32767),将外部流量路由到 Service:
apiVersion: v1
kind: Service
metadata:
name: frontend-nodeport
spec:
type: NodePort
selector:
app: frontend
ports:
- port: 80
targetPort: 3000
nodePort: 31080 # 可选,不指定则自动分配
externalTrafficPolicy: Local # 保留客户端源 IPexternalTrafficPolicy 的两种模式:
- Cluster(默认):流量可能跨节点转发,负载均匀但丢失源 IP,增加一跳延迟
- Local:仅转发到本节点 Pod,保留源 IP,但如果本节点无 Pod 则连接失败
LoadBalancer
LoadBalancer 依赖云厂商提供外部负载均衡器,自动创建并关联到 Service:
apiVersion: v1
kind: Service
metadata:
name: web-lb
annotations:
# AWS 特定注解
service.beta.kubernetes.io/aws-load-balancer-type: nlb
service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"
spec:
type: LoadBalancer
selector:
app: web
ports:
- port: 443
targetPort: 8443
protocol: TCP
loadBalancerSourceRanges: # 限制访问来源
- 10.0.0.0/8
- 203.0.113.0/24在裸金属环境中可使用 MetalLB 实现 LoadBalancer 功能:
# MetalLB IP 地址池配置
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: production-pool
namespace: metallb-system
spec:
addresses:
- 192.168.1.200-192.168.1.250
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: l2-advert
namespace: metallb-system
spec:
ipAddressPools:
- production-poolExternalName
ExternalName 通过返回 CNAME 记录将 Service 映射到外部域名,不使用代理或转发:
apiVersion: v1
kind: Service
metadata:
name: external-db
spec:
type: ExternalName
externalName: db.prod.example.com # 外部数据库域名
# 注意:不需要 selector 和 ports# 集群内访问 external-db 会解析到 db.prod.example.com
nslookup external-db.default.svc.cluster.local
# 返回 CNAME db.prod.example.com典型用途:将外部数据库、SaaS 服务抽象为集群内部 Service,方便后续迁移。
Headless Service
设置 clusterIP: None 创建 Headless Service,不分配虚拟 IP,DNS 直接返回 Pod IP:
apiVersion: v1
kind: Service
metadata:
name: mysql-headless
spec:
clusterIP: None # Headless Service
selector:
app: mysql
ports:
- port: 3306
targetPort: 3306# DNS 查询返回所有 Pod IP
nslookup mysql-headless.default.svc.cluster.local
# 返回:
# 10.244.1.5
# 10.244.2.8
# 10.244.3.12Headless Service 配合 StatefulSet 提供稳定的 Pod DNS:
# StatefulSet Pod 的 DNS 格式
# <pod-name>.<headless-service>.<namespace>.svc.cluster.local
mysql-0.mysql-headless.default.svc.cluster.local
mysql-1.mysql-headless.default.svc.cluster.localEndpoints 与 EndpointSlice
Endpoints
Endpoints 对象记录了 Service 后端的实际 Pod IP 和端口:
kubectl get endpoints backend-service
# NAME ENDPOINTS AGE
# backend-service 10.244.1.5:8080,10.244.2.8:8080,10.244.3.12:8080 2d手动定义 Endpoints(无 selector 的 Service):
apiVersion: v1
kind: Service
metadata:
name: external-service
spec:
ports:
- port: 80
targetPort: 80
---
apiVersion: v1
kind: Endpoints
metadata:
name: external-service # 必须与 Service 同名
subsets:
- addresses:
- ip: 192.168.1.100
- ip: 192.168.1.101
ports:
- port: 80EndpointSlice
EndpointSlice 是 Endpoints 的改进版本,每个 Slice 最多包含 100 个端点,解决大规模集群中 Endpoints 对象过大的问题:
kubectl get endpointslice -l kubernetes.io/service-name=backend-servicekube-proxy 工作模式
kube-proxy 负责在节点上实现 Service 的流量转发规则:
iptables 模式
# 查看 iptables 规则
iptables -t nat -L KUBE-SERVICES -n
# 每个 Service 对应一条链,每个 Endpoint 一条 DNAT 规则IPVS 模式
启用 IPVS 模式:
# kube-proxy ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: kube-proxy
namespace: kube-system
data:
config.conf: |
mode: "ipvs"
ipvs:
scheduler: "rr" # 轮询。可选: rr, lc, dh, sh, sed, nq
strictARP: true # MetalLB 需要IPVS 支持的负载均衡算法:
- rr:轮询(Round Robin)
- lc:最小连接数(Least Connection)
- dh:目标地址哈希(Destination Hashing)
- sh:源地址哈希(Source Hashing)
- sed:最短期望延迟(Shortest Expected Delay)
- nq:永不排队(Never Queue)
Service Topology 与拓扑感知路由
通过拓扑感知路由,流量优先发送到同一区域的 Pod,减少跨区域延迟和成本:
apiVersion: v1
kind: Service
metadata:
name: topology-aware-svc
annotations:
service.kubernetes.io/topology-mode: Auto
spec:
selector:
app: my-app
ports:
- port: 80
targetPort: 8080topology-mode: Auto 会根据以下条件自动选择路由策略:
- 如果某个区域的端点足够服务本区域流量,则流量保持在区域内
- 否则回退到全集群范围负载均衡
总结
选择合适的 Service 类型取决于访问模式和部署环境:
| Service 类型 | 访问范围 | 适用场景 |
|---|---|---|
| ClusterIP | 集群内部 | 微服务间通信 |
| NodePort | 集群外部 | 开发测试、小规模部署 |
| LoadBalancer | 集群外部 | 生产环境公网服务 |
| ExternalName | 集群内部 | 引用外部服务 |
| Headless | 集群内部 | StatefulSet、自定义服务发现 |
对于大规模集群(超过 1000 个 Service),建议启用 IPVS 模式以获得更好的性能。同时配合拓扑感知路由降低跨区域流量成本。
贡献者
更新日志
9f6c2-feat: organize wiki content and refresh site setup于