Kubernetes Service 类型详解:从 ClusterIP 到 LoadBalancer

一个 Pod 崩了重启之后 IP 就变了,那访问它的请求该怎么找到它?Service 就是解决这个问题的。


一、为什么需要 Service

Kubernetes 里的 Pod 是非常"不稳定"的------随时可能被重建、扩缩容、调度到另一个节点,每次重建 IP 都会变化。业务代码不可能直接写死 Pod IP,否则一旦 Pod 重启,上游就找不到它了。

Service 是 K8s 提供的稳定访问入口,它通过 Label Selector 动态绑定一组 Pod,对外暴露一个固定的 ClusterIP 或端口,不管后端 Pod 怎么飘,Service 的入口地址永远不变。

Service 的三大核心能力:

  1. 稳定虚拟 IP(ClusterIP)+ DNS 名称,屏蔽 Pod IP 变化
  2. 自动负载均衡,将请求分发给健康 Pod
  3. 支持多种暴露方式,适配集群内、集群外、云厂商 LB 等场景

二、Service 的五种类型

K8s 内置五种 Service 类型,适配不同的访问场景。

1. ClusterIP(默认类型)

定义: 为 Service 分配一个只在集群内部可路由的虚拟 IP(VIP),仅集群内的 Pod 和 Node 可访问,外部无法直接访问。

工作机制:

  • kube-proxy 在每个节点维护 iptables/IPVS 规则
  • 当请求命中 ClusterIP 时,被转发到 EndpointSlice 中的健康 Pod

适用场景: 微服务间内部调用(如 Web → DB、API → Cache)

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: my-svc
spec:
  type: ClusterIP          # 默认可省略
  selector:
    app: jczz_app
  ports:
    - port: 80             # Service 暴露的端口
      targetPort: 8080     # Pod 容器实际监听端口

记忆口诀: ClusterIP = 集群内专用,外网看不见。


2. NodePort

定义: 在 ClusterIP 基础上,额外在集群每个节点 上开放一个固定端口(范围 30000-32767),外部可通过 节点IP:NodePort 访问服务。

工作流程:

复制代码
外部请求 → 节点IP:NodePort → iptables/IPVS → ClusterIP:Port → 后端Pod

核心特点:

  • 每个节点都开同一个 NodePort,访问任意节点 IP 都能路由到后端 Pod
  • 端口范围固定(30000-32767),不够灵活
  • 无法做域名解析和 SSL 卸载,通常仅用于测试或小规模暴露
yaml 复制代码
spec:
  type: NodePort
  ports:
    - port: 80
      targetPort: 8080
      nodePort: 31000      # 可不填,K8s 自动分配

适用场景: 开发测试环境、临时对外暴露、无云厂商 LB 的裸金属环境(配合 MetalLB 使用)


3. LoadBalancer

定义: 在 NodePort 基础上,自动调用云厂商 API 创建外部四层负载均衡器,是生产环境外部流量接入的主流方式。

详见下文 三、LoadBalancer 工作原理


4. ExternalName

定义: 不绑定 Pod,而是将 Service 映射到一个集群外部的域名,相当于 DNS 层面的 CNAME。

适用场景:

  • 集群内 Pod 需要访问外部服务(如 RDS、第三方 API)
  • 将外部服务"纳入"K8s 服务发现体系,便于后续迁移
yaml 复制代码
spec:
  type: ExternalName
  externalName: db.example.com   # 外部 DNS 域名

注意: 不会创建 ClusterIP,也不会代理流量,纯粹是 DNS CNAME 映射。


5. Headless Service

定义:clusterIP 显式设为 None,不分配虚拟 IP,DNS 查询直接返回所有后端 Pod 的 IP 列表。

适用场景: StatefulSet(MySQL 主从、Kafka 集群),客户端需要直接感知每个 Pod 的 IP 和 hostname

yaml 复制代码
spec:
  clusterIP: None
  selector:
    app: mysql

DNS 解析:mysql-0.my-svc.default.svc.cluster.local → Pod 实际 IP


6. 五种类型对比速查

类型 集群内访问 外部访问 典型场景
ClusterIP 微服务内部调用
NodePort ✅(节点IP:端口) 开发测试
LoadBalancer ✅(云LB IP) 生产对外暴露
ExternalName ✅(DNS映射) 访问外部服务
Headless ✅(直连Pod) StatefulSet

三、LoadBalancer 工作原理

LoadBalancer 是 K8s 最常用的外部暴露方式,涉及云控制器管理器(CCM)、NodePort、kube-proxy 多个组件协同工作。

1. 完整流量链路

复制代码
外部用户
    │
    ▼
云厂商 LB(外部IP,四层转发)
    │  后端:集群所有节点IP + NodePort
    ▼
节点:NodePort
    │  kube-proxy iptables/IPVS 规则
    ▼
ClusterIP(虚拟IP)
    │
    ▼
健康 Pod

2.真实案例

这里是前端web的一个service案例:

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: yituweb-nginx-svc
  namespace: dx-test
spec:
  clusterIP: 172.29.13.104
  clusterIPs:
  - 172.29.13.104
  externalTrafficPolicy: Local
  ports:
  - name: yituweb-service
    nodePort: 30080
    port: 23343
    protocol: TCP
    targetPort: 23343
  selector:
    app: yituweb
  sessionAffinity: None
  type: LoadBalancer
status:
  loadBalancer:
    ingress:
    - ip: 10.49.49.66

3. 创建流程(五步)

3.1 创建 Service

用户提交 type: LoadBalancer 的 Service YAML,K8s 自动为其分配 ClusterIP 和 NodePort。

3.2 CCM 监听并调用云 API

云控制器管理器(Cloud Controller Manager)监听到 Service 创建事件,调用云厂商 API(如阿里云 SLB、AWS ELB)创建四层负载均衡器实例。

3.3 LB 后端注册节点

CCM 将集群所有节点的 IP 和分配的 NodePort 注册为 LB 后端,并配置健康检查策略。

3.4 LB IP 写回 Service

云 LB 创建完成后,CCM 将 LB 的公网 IP 写回到 Service 的 status.loadBalancer.ingress[].ip 字段,kubectl get svc 就能看到 EXTERNAL-IP

3.5 流量进入集群

外部请求到达 LB,LB 按轮询等策略转发到节点的 NodePort,再由 kube-proxy 转发到后端 Pod。

4. 健康检查机制

LB 并非盲目转发,它会通过两层机制确保只转发到健康节点和健康 Pod:

4.1 节点级健康检查

LB 定期探测节点 IP:NodePort,无响应的节点会被自动踢出后端列表。

4.2 Pod 级过滤

kube-proxy 通过 EndpointSlice 维护健康 Pod 列表(通过 Readiness Probe 判断),未就绪的 Pod 不会出现在 Endpoints 里,LB 流量不会转到故障 Pod。

5. externalTrafficPolicy 参数

这是 LoadBalancer 里一个容易踩坑的关键参数:

行为 优缺点
Cluster(默认) 任意节点接收流量后,可能再转发到其他节点的 Pod 负载均匀,但会多一跳,源IP丢失
Local 只转发到当前节点上存在 Pod 的节点 保留源IP,减少网络跳数,但负载可能不均

生产建议: 对需要获取真实客户端 IP 的场景(如安全审计、限流),使用 Local;其他场景默认 Cluster

yaml 复制代码
spec:
  type: LoadBalancer
  externalTrafficPolicy: Local

5. 自建环境怎么用 LoadBalancer?

裸金属或自建 K8s 环境没有云厂商 API,用 MetalLB 替代:

  • MetalLB 分配 IP 池,监听 Service 创建
  • 通过 Layer2 或 BGP 模式宣告 IP 路由
  • 效果等同于云 LB,但依赖本地网络设备支持

四、Service 与 Ingress 的区别

很多人会混淆 Service LoadBalancer 和 Ingress,这里专门厘清:

维度 Service LoadBalancer Ingress
层级 四层(TCP/UDP) 七层(HTTP/HTTPS)
域名路由 ❌ 不支持 ✅ 支持
SSL 卸载
一个IP对多服务 ❌(每个Service一个LB)
依赖 云厂商LB Ingress Controller(如Nginx)

实际生产架构: 通常是 云LB → Ingress Controller Pod(NodePort/LoadBalancer)→ Ingress 规则 → 各业务 Service(ClusterIP)→ Pod,两者配合使用。


五、总结

1. 五种类型选型口诀

复制代码
集群内访问用 ClusterIP
测试对外用 NodePort
生产对外用 LoadBalancer
外部服务映射用 ExternalName
有状态应用直连用 Headless

2. LoadBalancer 核心记忆点

  • 创建链路: 提交Service → CCM调用云API → 创建外部LB → IP写回Service
  • 流量路径: 云LB → NodePort → iptables/IPVS → Pod
  • 健康保障: LB健康检查(节点级)+ EndpointSlice(Pod级)双重保险
  • 重要参数: externalTrafficPolicy: Local 保留源IP

3. 速查命令

bash 复制代码
# 查看 Service 状态和 EXTERNAL-IP
kubectl get svc -n <namespace>

# 查看 Service 详情(含 Endpoints)
kubectl describe svc <svc-name>

# 查看 EndpointSlice(健康Pod列表)
kubectl get endpointslice -n <namespace>

# 查看 kube-proxy 的 iptables 规则
iptables -t nat -L KUBE-SERVICES -n | grep <svc-name>

# 查看 IPVS 规则(如果使用 IPVS 模式)
ipvsadm -Ln | grep <clusterIP>
相关推荐
牟同學1 小时前
Hermes Agent Docker 离线部署完整指南
docker·容器·eureka·hermes
IT策士1 小时前
第27篇 k8s之控制器:DaemonSet、Job 与 CronJob
云原生·容器·kubernetes
蜀道山老天师1 小时前
Docker安装配置全教程(含银河麒麟服务器部署+镜像加速)
运维·docker·容器
EMTime10 小时前
Docker运行OpenWRT
运维·docker·容器
zyl8372113 小时前
Docker 使用手册
运维·docker·容器
Elastic 中国社区官方博客15 小时前
我们如何在 Elasticsearch Serverless 上将向量搜索吞吐量提升一倍
大数据·数据库·人工智能·elasticsearch·搜索引擎·云原生·serverless
maomao大哥闯天下16 小时前
K8s如何实现滚动更新、健康检查与探测机制
docker·容器·kubernetes
楼田莉子16 小时前
Docker学习:Docker介绍及其架构介绍
运维·后端·学习·docker·容器·架构
张忠琳18 小时前
【kubernetes v1.21】(一)Kubernetes 总览架构深度分析
云原生·架构·kubernetes