Skip to content

Kubernetes Service 实战培训教材

基于《Kubernetes Service 原理由浅入深》《Service 全链路深入解析》《port/targetPort/NodePort 关系解读》《NodeIP:NodePort vs VIP:NodePort》《Service 端口冲突答疑》等内部文档整合编写。

  • 培训对象:Kubernetes 运维、后端研发、DevOps、测试工程师
  • 培训时长:建议 1 天(6 小时:理论 4h + 实验 2h)
  • 前置知识:Linux 网络基础、容器基础、Pod 概念、YAML 基础
  • 教材版本:v1.0

目录

  1. 课程目标与学习地图
  2. Service 核心概念
  3. Service 四种类型
  4. 端口深度解析:port / targetPort / NodePort
  5. Service 全链路数据包流转
  6. kube-proxy 实现机制
  7. 外部访问与 VIP 设计
  8. 端口冲突与最佳实践
  9. 动手实验手册
  10. 故障排查演练
  11. 课程考核
  12. 附录:速查表与参考资料

第1章 课程目标与学习地图

1.1 学完本课程你能做什么

能力层级具体能力
理解解释 Service 的本质、四种类型、端口含义
应用正确编写 Service YAML,选择合适的 Service 类型
分析从 kube-proxy 规则层面分析流量走向
排障定位 Service 访问不通、端口冲突、源 IP 丢失等问题
设计为生产环境设计 NodePort、LoadBalancer、Ingress 入口方案

1.2 学习地图

┌─────────────────────────────────────────────────────────────┐
│                    Kubernetes Service                        │
├───────────────┬───────────────┬───────────────┬─────────────┤
│   概念层       │   端口层       │   实现层       │   入口层     │
├───────────────┼───────────────┼───────────────┼─────────────┤
│ ClusterIP     │ port          │ kube-proxy    │ NodePort    │
│ NodePort      │ targetPort    │ iptables      │ LoadBalancer│
│ LoadBalancer  │ nodePort      │ ipvs          │ Ingress     │
│ ExternalName  │ containerPort │ conntrack     │ VIP         │
│ Headless      │ hostPort      │ EndpointSlice │ MetalLB     │
└───────────────┴───────────────┴───────────────┴─────────────┘

第2章 Service 核心概念

2.1 为什么需要 Service

Pod 的特点:

  • 生命周期短暂
  • IP 不固定
  • 随时扩缩容

Service 的作用:

  • 为一组 Pod 提供稳定的虚拟 IP(ClusterIP)
  • 通过 Label Selector 动态关联 Pod
  • 提供服务发现、负载均衡

2.2 Service 的本质

Service 不是进程,不是网卡,而是 Kubernetes 中的一种抽象资源 + 一组转发规则

真正实现转发的是:

  • EndpointSlice:记录后端 Pod 的 IP:targetPort
  • kube-proxy:在每个节点上配置 iptables/ipvs 规则

2.3 核心对象关系

┌──────────────┐     selector      ┌─────────────┐
│   Service    │ ────────────────> │    Pod      │
│ ClusterIP:80 │                   │ 10.244.x.x  │
└──────┬───────┘                   └─────────────┘

       │ 自动生成

┌─────────────────┐
│  EndpointSlice  │
│  IP:targetPort  │
└─────────────────┘

       │ kube-proxy 监听并生成规则

┌─────────────────┐
│ iptables / ipvs │
└─────────────────┘

第3章 Service 四种类型

3.1 ClusterIP(默认)

  • 分配集群内部虚拟 IP
  • 仅集群内部可达
  • 用于微服务间调用
yaml
spec:
  type: ClusterIP
  selector:
    app: web
  ports:
    - port: 80
      targetPort: 8080

3.2 NodePort

  • 在 ClusterIP 基础上,在每个节点上开放一个端口
  • 外部通过 <NodeIP>:<NodePort> 访问
  • NodePort 默认范围 30000-32767
yaml
spec:
  type: NodePort
  ports:
    - port: 80
      targetPort: 8080
      nodePort: 30080   # 可选

3.3 LoadBalancer

  • 请求云厂商或 MetalLB 创建外部负载均衡器
  • 分配外部 IP
  • 底层仍依赖 NodePort
yaml
spec:
  type: LoadBalancer
  ports:
    - port: 80
      targetPort: 8080

3.4 ExternalName

  • 没有 selector,不分配 ClusterIP
  • 将 Service 映射为外部域名的 CNAME
  • 用于平滑迁移或访问外部服务
yaml
spec:
  type: ExternalName
  externalName: db.example.com

3.5 四种类型对比

类型是否有 ClusterIP是否可被外部访问典型场景
ClusterIP微服务内部调用
NodePort✅(节点 IP)临时测试
LoadBalancer✅(外部 IP)生产公网入口
ExternalName间接外部服务映射

第4章 端口深度解析:port / targetPort / NodePort

4.1 一句话解释

字段绑定对象一句话解释
portServiceService 对外暴露的端口,调用方使用
targetPortPod 容器容器真实监听的端口,流量最终到达这里
nodePort节点网卡节点对外开放的端口,外部用户通过 <节点IP>:<NodePort> 访问

4.2 流量链

外部用户


<NodeIP>:30080          nodePort


Service:80              port (ClusterIP:port)


Pod:8080                targetPort

4.3 用快递物流类比

  • port = 公司总机号码
  • targetPort = 员工分机号码
  • nodePort = 园区门口公共收件窗口

4.4 不同场景下的端口配置

场景typeporttargetPortnodePort
内部微服务调用ClusterIP808080不写
临时外部测试NodePort80808030080
生产公网访问LoadBalancer808080不写
Ingress 后端ClusterIP808080不写

4.5 研发常见错误

  1. 只改容器端口,忘了改 targetPort

    • 现象:有 Endpoints,但请求无响应
    • 排查:telnet PodIP:targetPort 不通
  2. 调用方写死 Pod IP

    • Pod IP 会变化,应该通过 Service 域名访问
  3. 以为 port 必须等于 targetPort

    • 两者可以不同,且通常建议不同
  4. 多个 NodePort 服务硬编码相同端口

    • NodePort 是集群全局资源,会冲突

第5章 Service 全链路数据包流转

5.1 ClusterIP 全链路

Client Pod

    │ 目的: 10.96.123.45:80

┌─────────────────────────────┐
│ 本节点 kube-proxy 规则       │
│ (iptables / ipvs)            │
└─────────────┬───────────────┘
              │ DNAT

Backend Pod: 10.244.1.10:8080

核心认知:ClusterIP 不是真实网卡 IP,只是 iptables/ipvs 规则中的匹配条件。

5.2 NodePort 全链路

外部客户端


Node-1:30080


ClusterIP:80


Pod:8080

5.3 端口转换关系总结

外部:   <NodeIP>:30080      → nodePort
Service: 10.96.123.45:80    → port
Pod:     10.244.1.10:8080   → targetPort

5.4 返回包与 conntrack

请求包:
  源: Client-IP:random-port
  目的: 10.96.123.45:80

DNAT 后:
  源: Client-IP:random-port
  目的: 10.244.1.10:8080

Pod 回复:
  源: 10.244.1.10:8080
  目的: Client-IP:random-port

返回包经过 conntrack 反向 DNAT:
  源: 10.96.123.45:80
  目的: Client-IP:random-port

第6章 kube-proxy 实现机制

6.1 kube-proxy 三种模式

模式说明状态
userspacekube-proxy 用户态代理已废弃
iptables默认模式,内核态 DNAT广泛使用
ipvs内核态 IPVS 负载均衡大规模推荐

6.2 iptables 模式

kube-proxy 创建的核心链:

KUBE-SERVICES
  ├── KUBE-SVC-XXX   # 某个 Service
  │     ├── KUBE-SEP-XXX  # 后端 Pod 1,DNAT 到 Pod-1:targetPort
  │     └── KUBE-SEP-YYY  # 后端 Pod 2,DNAT 到 Pod-2:targetPort
  └── KUBE-NODEPORTS  # 匹配 NodePort

负载均衡算法:随机(通过 statistic mode random probability 实现)

6.3 ipvs 模式

IP Virtual Server (VS) = ClusterIP:port
  ├── Real Server 1 = Pod-1:targetPort
  └── Real Server 2 = Pod-2:targetPort

支持调度算法:rrlcdhshsednq

默认转发模式:Masq(NAT)

6.4 iptables vs ipvs 对比

特性iptablesipvs
负载均衡层iptables 规则链IPVS virtual server
调度算法随机rr / lc / dh / sh / sed / nq
后端数量大时规则链膨胀结构稳定
性能较好更好
长连接重试较差较好
内核要求需要 ip_vs 模块

6.5 EndpointSlice

  • Kubernetes 1.21+ 默认使用
  • 将后端端点拆分为多个 Slice,每个最多 100 个端点
  • 支持拓扑信息(zone、nodeName)
  • 更高效地增量更新

第7章 外部访问与 VIP 设计

7.1 NodeIP:NodePort vs VIP:NodePort

对比项NodeIP:NodePortVIP:NodePort
可用性低,单节点故障即中断高,VIP 自动剔除故障节点
入口统一性差,多个 NodeIP好,一个 VIP
流量均衡较好
源 IP 保留看 externalTrafficPolicy看 externalTrafficPolicy
维护成本
生产推荐度❌ 不推荐✅ 推荐

7.2 externalTrafficPolicy

模式流量路径源 IP空节点风险适用场景
Cluster可能跨节点转发被 SNAT,丢失真实 IP追求均衡、容错
Local只转发到本节点 Pod保留真实客户端 IP需要源 IP、Pod 分布均匀

7.3 VIP 方案对比

方案类型工作层次复杂度负载均衡
MetalLB L2K8s 原生L2 (ARP/NDP)Failover
MetalLB BGPK8s 原生L3 (BGP/ECMP)多活 ECMP
kube-vipK8s 原生L2 / BGPFailover / ECMP
HAProxy + Keepalived外部独立L4 + VRRP主备
Calico BGPCNI 集成L3 (BGP)ECMP

7.4 生产入口设计建议

Internet


LoadBalancer / VIP


Ingress Controller (NodePort / LoadBalancer)


Service (ClusterIP)


Backend Pods
  • 业务 Service 使用 ClusterIP
  • 通过 Ingress 暴露七层 HTTP/HTTPS
  • 需要四层 TCP/UDP 时直接用 LoadBalancer
  • 裸金属集群使用 MetalLB 或 kube-vip 提供 VIP

第8章 端口冲突与最佳实践

8.1 端口冲突判断原则

端口是否冲突,不取决于数字本身,而取决于它绑定在哪个网络对象上。

场景是否冲突原因
不同 Service 都用 port: 8080每个 Service 有独立 ClusterIP
不同 Pod 都用 targetPort: 8080每个 Pod 有独立 IP
同一个 Service 内两个 port: 8080/TCP同 Service 内 port+protocol 必须唯一
同一个 Pod 内两个容器都监听 8080共享同一个网络命名空间
不同 Service 使用相同 nodePortNodePort 绑定节点,全局唯一
同一个节点上两个 Pod 使用相同 hostPort节点端口被占用

8.2 生产最佳实践

  1. 统一后端端口:让所有后端服务统一使用 port: 8080 / targetPort: 8080
  2. 给端口命名:便于 Ingress、监控、日志区分
  3. NodePort 自动分配:不要硬编码,避免冲突
  4. 优先使用 ClusterIP + Ingress:减少端口管理负担
  5. 配置 readinessProbe:只有就绪的 Pod 才会加入 EndpointSlice
  6. 使用 Topology Spread Constraints:保证 Pod 在节点间均匀分布
  7. 根据需求选择 externalTrafficPolicy
    • 需要保留源 IP → Local
    • 追求均衡和容错 → Cluster

第9章 动手实验手册

实验1:部署并访问 ClusterIP Service

bash
# 创建 Deployment
kubectl create deployment nginx --image=nginx:alpine --replicas=2

# 创建 ClusterIP Service
kubectl expose deployment nginx --port=80 --target-port=80 --type=ClusterIP

# 验证
kubectl get svc nginx
kubectl get endpoints nginx

# 从集群内访问
kubectl run -it --rm debug --image=busybox --restart=Never -- wget -O- http://nginx

实验2:NodePort 访问与端口观察

bash
# 修改 Service 为 NodePort
kubectl patch svc nginx -p '{"spec":{"type":"NodePort"}}'

# 查看 NodePort
kubectl get svc nginx

# 从外部访问
NODE_IP=$(kubectl get nodes -o jsonpath='{.items[0].status.addresses[0].address}')
NODE_PORT=$(kubectl get svc nginx -o jsonpath='{.spec.ports[0].nodePort}')
curl http://$NODE_IP:$NODE_PORT

实验3:iptables 规则观察

bash
# 在节点上执行
iptables -t nat -L KUBE-SERVICES -n -v | grep nginx
iptables -t nat -L KUBE-NODEPORTS -n -v
iptables -t nat -L -n -v | grep KUBE-SEP

实验4:ipvs 模式观察(需启用 ipvs)

bash
# 加载 ipvs 模块
modprobe ip_vs

# 查看规则
ipvsadm -Ln

实验5:externalTrafficPolicy=Local 效果验证

bash
# 修改 externalTrafficPolicy
kubectl patch svc nginx -p '{"spec":{"externalTrafficPolicy":"Local"}}'

# 测试从有 Pod 的节点和无 Pod 的节点访问
# 观察:无 Pod 的节点是否会丢弃连接

实验6:端口冲突验证

bash
# 部署两个 Service,都使用 port: 8080
kubectl apply -f - <<EOF
apiVersion: v1
kind: Service
metadata:
  name: app-a
spec:
  selector:
    app: app-a
  ports:
    - port: 8080
      targetPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: app-b
spec:
  selector:
    app: app-b
  ports:
    - port: 8080
      targetPort: 8080
EOF

# 验证两个 Service 都能成功创建
kubectl get svc

第10章 故障排查演练

10.1 Service 访问不通排查清单

bash
# 1. 检查 Service 是否存在
kubectl get svc <svc-name>

# 2. 检查 Endpoints/EndpointSlice 是否有后端
kubectl get endpoints <svc-name>
kubectl get endpointslices -l kubernetes.io/service-name=<svc-name>

# 3. 检查 Pod 标签是否匹配 selector
kubectl get pods -l <selector> --show-labels

# 4. 检查 Pod 是否就绪
kubectl get pods -l <selector>

# 5. 检查容器是否监听 targetPort
kubectl exec -it <pod> -- netstat -tlnp | grep <targetPort>

# 6. 从 Pod 内访问 Service
kubectl run -it --rm debug --image=busybox --restart=Never -- wget -O- http://<svc-name>:<port>

# 7. 查看节点 iptables/ipvs 规则
iptables -t nat -L KUBE-SERVICES -n -v | grep <svc-name>
ipvsadm -Ln | grep <cluster-ip>

# 8. 查看 conntrack
conntrack -L | grep <cluster-ip>

# 9. 抓包
sudo tcpdump -i any -nn host <cluster-ip> or port <nodePort>

10.2 常见故障现象与原因

现象可能原因排查方向
Service 没有 EXTERNAL-IP云厂商 CCM 未安装或 MetalLB 未配置检查 CCM / MetalLB
有 Endpoints 但访问超时Pod 未真正监听 targetPorttelnet PodIP:targetPort
NodePort 访问不通防火墙/安全组拦截检查节点防火墙
源 IP 被改写externalTrafficPolicy=Cluster改为 Local 或前端代理加 XFF
流量不均衡Pod 分布不均 + Local 模式Topology Spread Constraints
滚动更新时 502长连接未断开 + 旧 Pod 已删除配置 preStop / terminationGracePeriod

第11章 课程考核

11.1 选择题

1. Service 的 port 是指?

A. 容器实际监听的端口
B. 节点上暴露的端口
C. Service 对外暴露的端口
D. Pod 内进程监听的端口

答案:C

2. 以下哪种 Service 类型不会分配 ClusterIP?

A. ClusterIP
B. NodePort
C. LoadBalancer
D. ExternalName

答案:D

3. iptables 模式下,kube-proxy 使用的负载均衡算法是?

A. 轮询
B. 最少连接
C. 随机
D. 加权轮询

答案:C

4. externalTrafficPolicy=Local 的主要作用是?

A. 提高负载均衡效果
B. 保留真实客户端源 IP
C. 减少 iptables 规则数量
D. 自动分配 NodePort

答案:B

11.2 实操题

  1. 创建一个 Deployment(2 个副本)和 ClusterIP Service,从集群内验证访问。
  2. 将 Service 改为 NodePort,从集群外通过 <NodeIP>:<NodePort> 访问。
  3. 在节点上找到该 Service 对应的 iptables 规则链。
  4. 配置 externalTrafficPolicy=Local,测试源 IP 保留效果。
  5. 部署两个都使用 port: 8080 的 Service,验证不会冲突。

11.3 设计题

某公司有一个裸金属 Kubernetes 集群,需要:

  • 为 20 个微服务提供内部调用入口
  • 为 5 个 Web 应用提供公网 HTTPS 入口
  • 为 2 个 TCP 长连接服务提供四层入口
  • 需要保留真实客户端源 IP

请设计 Service + Ingress + VIP 方案,并说明:

  • 每种服务使用什么 Service 类型
  • 外部 VIP 如何提供
  • externalTrafficPolicy 如何选择
  • 端口如何规划

第12章 附录:速查表与参考资料

12.1 Service YAML 速查

yaml
apiVersion: v1
kind: Service
metadata:
  name: example
spec:
  type: ClusterIP          # 或 NodePort / LoadBalancer / ExternalName
  selector:
    app: example
  ports:
    - name: http
      port: 80             # Service 端口
      targetPort: 8080     # Pod 端口
      nodePort: 30080      # 仅 NodePort/LoadBalancer 有效
  sessionAffinity: None    # 或 ClientIP
  externalTrafficPolicy: Cluster  # 或 Local

12.2 关键命令速查

bash
# Service 与后端
kubectl get svc -o wide
kubectl get endpoints <svc>
kubectl get endpointslices -l kubernetes.io/service-name=<svc>

# Pod 标签与就绪
kubectl get pods -l app=<app> --show-labels
kubectl describe pod <pod>

# 网络规则
iptables -t nat -L KUBE-SERVICES -n -v
iptables -t nat -L KUBE-NODEPORTS -n -v
ipvsadm -Ln
conntrack -L | grep <ip>

# DNS 测试
kubectl run -it --rm debug --image=busybox --restart=Never -- nslookup <svc>.<namespace>

# 抓包
sudo tcpdump -i any -nn host <cluster-ip> or port <nodePort>

12.3 参考资料

  • 内部文档:《Kubernetes Service 原理由浅入深》
  • 内部文档:《Kubernetes Service 全链路深入解析》
  • 内部文档:《port / targetPort / NodePort 关系解读》
  • 内部文档:《NodeIP:NodePort vs VIP:NodePort 访问方式深度解析》
  • 内部文档:《所有后端 Service 都用 8080 端口,会冲突吗?》
  • 官方文档:https://kubernetes.io/docs/concepts/services-networking/service/
  • MetalLB 官方文档:https://metallb.universe.tf/

结语

掌握 Kubernetes Service 是理解集群网络通信的基础。本教材从概念、端口、实现、入口、排障五个层面系统讲解了 Service 的核心知识。建议学员在学习理论后,务必完成动手实验,并在实际工作中多观察 kubectl get endpointsiptables -Lipvsadm -Ln 等输出,形成对 Service 流量走向的直观理解。


教材生成时间:2026-07-18