文章目录
- 1. 概述
- 2. 工作原理
-
- 2.1 分配虚拟 IP (CIDR)
- 2.2 流量转发(kube-proxy)
- 2.3 完整流量链路
- 2.4 外部网络访问限制
- 3. 演示案例
-
- 3.1 定义工作负载
- 3.2 定义 ClusterIP 服务
-
- 3.2.1 基本信息
- 3.2.2 标签选择器
- 3.2.3 端口映射
-
- 1)port
- 2)targetPort
- 3.2.4 其他可选配置
- 3.2.5 完整清单
- 3.3 验证测试
- 3.4 多端口 Service
1. 概述
在 Kubernetes 里,Pod 是临时性、可销毁的资源。Deployment 会根据副本数动态创建和销毁 Pod,滚动更新、扩缩容、节点故障都会导致 Pod IP 发生变化。
这就带来一个核心问题:
前端业务要调用后端服务,如果后端 Pod 的 IP 一直在变,前端该找谁?怎么保证不会因为 Pod 重建就调用失败?
Service 就是来解决这个问题的,可以把 Service 理解成「Pod 集群的统一入口 + 内部负载均衡器」:
- 它给一组 Pod 分配一个固定不变的虚拟 IP(集群 IP)
- 客户端只需要访问这个固定地址,流量会自动转发到健康的后端 Pod
- 后端 Pod 增减、重建、更新,对客户端完全透明,无需修改任何配置
Service 的核心设计目标是业务无侵入:无论你的应用是云原生新程序,还是老旧系统容器化改造,都不需要修改代码适配服务发现,直接用 Service 即可完成网络暴露。
Service 通过 type 字段指定暴露方式,共四种,能力逐层递进:
| ClusterIP | 仅集群内部 | 微服务内部调用、数据库、缓存等后端服务 |
| NodePort | 集群外通过节点IP+端口访问 | 测试环境、自建负载均衡、临时暴露 |
| LoadBalancer | 公网/私有网络通过云负载均衡访问 | 生产环境对外提供服务 |
| ExternalName | 集群内部 DNS 别名 | 映射外部服务到集群内部域名 |
ClusterIP 是 Service 的默认类型,仅分配一个集群内部可达的虚拟 IP,只能在集群内部访问。它是最基础、最常用的 Service 类型。
很多新手会混淆这三者:
- Service:四层(TCP/UDP)负载均衡,负责集群内 Pod 的网络抽象与访问
- Ingress:七层(HTTP/HTTPS)路由入口,负责把外部流量按域名/路径分发到不同 Service
- Gateway API:Ingress 的升级替代方案,功能更丰富、扩展性更强,通过 CRD 实现更灵活的流量治理
2. 工作原理
2.1 分配虚拟 IP (CIDR)
K8s 安装时会单独划分一段虚拟 IP 地址池,专门给 Service 使用,这个地址段就叫 Service CIDR,这段 IP 不会分配给任何服务器、容器 Pod,只用来做 Service 的虚拟入口。
新建 ClusterIP Service 时,集群控制平面(apiserver + etcd)会自动从这个池里挑一个没人用的 IP 绑定给当前 Service。这个 IP 不是真实网卡 IP ,是集群内部逻辑虚拟 IP ,外部网络路由表里不存在这条地址。
示例:集群 Service CIDR = 10.96.0.0/12 ,创建后端服务 Service ,自动分配虚拟 IP:10.96.12.34,这个 IP 只代表服务入口,不对应任何一台真实机器。
2.2 流量转发(kube-proxy)
每个 K8s 节点都会运行一个守护进程 kube-proxy,本身不直接转发数据包,负责实时监听所有 Service 和后端 Pod 变化,自动在节点内核生成转发规则。
底层基于 Linux 内核网络防火墙 / 流量过滤工具,比如:
- iptables:默认稳定模式
- ipvs:传统高性能模式
- nftables:新一代高性能模式
Service 资源创建后对象会保存到 etcd 中,每个节点的 kube-proxy 会持续长轮询监听 apiserver ,一旦检测到新增 / 修改 Service、后端 Pod 上下线,立刻触发规则更新。
比如,iptables 模式中,节点上的 kube-proxy 检测到新 Service 时,会创建一套以 KUBE- 开头的专属链,分层匹配:
- KUBE-SERVICES:全局总入口,匹配 ClusterIP 虚拟地址并跳转对应服务链。
- KUBE-SVC-xxx:单服务负载均衡链,按随机概率分流至不同后端 Pod 规则。
- KUBE-SEP-xxx:后端端点专属链,执行 DNAT(目标网络地址转换) 将虚拟 IP 替换为 Pod 真实 IP。
关键点:虚拟 IP 本身不接收、不存储数据,只是一个路由路标。
2.3 完整流量链路
标准 iptables 模式分步详细解析:
- 到达内核 nat 表的 KUBE-SERVICES 全局入口链;
- 匹配条件:目标 IP = 10.96.12.34、目标端口 = 8080;
- 匹配成功后,自动跳转当前服务专属链 KUBE-SVC-XXXX;
- kube-proxy 预先根据后端 3个 Pod 端点,生成概率随机分流规则,自动实现负载均衡;
- 按权重随机选择后端 Pod1 / Pod2 / Pod3;
- 流量进入对应 KUBE-SEP-XXX 端点链
- 将数据包目标地址 10.96.12.34:8080(虚拟 IP)替换为 后端真实 Pod 容器 IP
- 示例:10.96.12.34 → 10.244.x.x(真实 PodIP)
- 若后端 Pod 在当前节点:直接本机投递
- 若后端 Pod 在其他节点:通过集群 CNI 网络跨节点转发
- 最终流量精准抵达后端真实业务 Pod。

核心总结:
2.4 外部网络访问限制
两层网络隔离限制:
- 服务器宿主机、机房外网网关、公网路由器,都没有配置 Service CIDR(10.96.0.0/12)这段地址的路由规则。
- 外网机器发请求到 10.96.x.x,数据包一出节点就直接丢弃,找不到转发路径。
场景区分:
-
✅ 能访问:集群内任意 Pod、集群任意节点服务器 ssh 登录后 curl
-
❌ 不能访问:本机电脑、公网服务器、集群外其他机器
3. 演示案例
理论落地必须结合实操,通过 原生 YAML 从零编写 的方式,完成工作负载定义、单端口 ClusterIP 服务搭建、服务核心配置解析、多端口 Service 实战。全程采用 Nginx 官方镜像,兼容性极强、适配 x86/ARM 所有架构、无启动报错、无需特殊启动参数,是 Kubernetes 入门实验最稳定通用的业务镜像。
3.1 定义工作负载
Service 是一组 Pod 的统一访问入口与负载均衡抽象,所有流量转发、服务发现的前提是存在一组可被绑定的业务 Pod 集群。
我们创建 nginx-deploy.yaml,定义 3 副本 Deployment 模拟业务集群,Nginx 默认监听 80 端口,同时配合 Service 实现单端口、多端口流量转发实战。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx–web
namespace: default
spec:
# 启动3个Pod副本,用于负载均衡演示
replicas: 3
selector:
matchLabels:
app: nginx–web
template:
metadata:
labels:
# 核心标签:用于Service标签选择器精准匹配绑定
app: nginx–web
spec:
containers:
– name: nginx
# 官方轻量镜像,兼容x86/ARM架构,稳定不崩溃
image: nginx:latest
ports:
# Nginx默认业务监听端口
– containerPort: 80
执行部署命令,快速拉起 Nginx 业务集群,等待所有 Pod 就绪:
# 部署Nginx工作负载集群
kubectl apply -f nginx-deploy.yaml
# 查看Pod运行状态,确保全部就绪Ready
kubectl get pods -o wide
正常输出可看到 3 个状态为 Running 的 Nginx Pod,每个 Pod 拥有独立内网 IP,且统一携带标签 app: nginx-web,为后续 Service 动态绑定、负载均衡提供核心匹配依据。
nginx-web-55ff4cbb5c-4pwpn 1/1 Running 0 29s 100.99.1.177 iz2ze60mcbemirrld91q6rz <none> <none>
nginx-web-55ff4cbb5c-rl647 1/1 Running 0 31s 100.84.1.200 iz2ze60mcbemirrld91q6sz <none> <none>
nginx-web-55ff4cbb5c-sbjl8 1/1 Running 0 19s 100.84.1.203 iz2ze60mcbemirrld91q6sz <none> <none>
3.2 定义 ClusterIP 服务
基于已部署的 Nginx Pod 集群,我们创建默认类型的 ClusterIP Service,为动态可变的 Pod 提供固定虚拟 IP、四层负载均衡能力。下面拆解 Service 所有核心配置项,逐一讲解字段作用。
3.2.1 基本信息
基础元数据用于标识资源身份,包含资源类型、服务名称、命名空间,是集群资源管理、DNS 自动解析的基础。
创建 nginx-svc.yaml,基础配置如下:
apiVersion: v1
kind: Service
metadata:
name: nginx–svc
namespace: default
核心特性:Service 名称会自动注册到集群 CoreDNS,集群内所有 Pod 可通过固定域名 nginx-svc.default.svc.cluster.local 访问服务,无需感知 Pod 真实 IP 和 ClusterIP。
3.2.2 标签选择器
标签选择器是 Service 与 Pod 关联的 核心唯一规则,Service 不绑定固定 Pod IP,而是通过标签动态匹配后端 Pod 集群。
spec:
selector:
app: nginx–web
工作机制:每个节点的 kube-proxy 持续监听集群资源变化,只要 Pod 带有 app: nginx-web 标签,会自动加入当前 Service 的后端端点池;Pod 扩缩容、重建、删除时,转发规则自动更新,业务访问完全无感知。
3.2.3 端口映射
端口映射定义 Service 虚拟端口与后端 Pod 真实端口的转发规则,是流量通信的核心,包含三个核心字段:
ports:
– name: http–web
port: 8080
targetPort: 80
protocol: TCP
字段详解:
-
port:Service 对外暴露的虚拟端口,集群内客户端通过 ClusterIP:port 访问服务
-
targetPort:后端 Pod 容器真实监听端口,Nginx 默认监听 80 端口
-
protocol:传输层协议,默认 TCP,支持 UDP、SCTP 等
1)port
是 Service 这个「虚拟负载均衡器」对外暴露的端口,是集群内部访问服务的唯一入口。只要 Service 不删除、不修改,这个端口就永远不变,和后端 Pod 怎么变化无关。
访问方式:集群内的客户端 Pod 通过 服务名:port 或者 ClusterIP:port 访问服务。例如:curl http://my-service:80,这里的 80 就是 port。
关键特性:
- 纯虚拟概念,不存在真实的进程监听这个端口,由 kube-proxy 通过 iptables/ipvs 规则实现转发;
- 不同 Service 可以使用相同的 port,互不影响,因为每个 Service 有独立的 ClusterIP;
- 是四种 Service 类型都具备的基础字段。
新手常见误区:误以为 port 必须和后端容器端口一致。实际上两者完全解耦,比如 Service 用 80 端口,后端容器可以用 9376、8080 等任意端口。
2)targetPort
核心作用:流量最终要送达的容器端口,也就是你业务代码、中间件实际启动时监听的端口。Service 收到流量后,最终会转发到 Pod 的这个端口上。
两种写法:
关键特性:
- 必须和容器内程序真实监听的端口完全一致,否则会出现连接超时、连接拒绝,服务不通;
- 一组后端 Pod 可以有不同的容器端口,只要端口名称一致,Service 就能统一适配,非常适合多版本灰度、业务迭代场景。
新手常见误区:漏写 targetPort。如果不写,K8s 默认让 targetPort 和 port 取值相同;如果容器端口和 port 不一致,会直接导致服务不可用。
3.2.4 其他可选配置
ClusterIP 支持拓展配置,可实现会话保持等进阶能力,适配特殊业务场景:
type: ClusterIP
# 基于客户端IP实现会话保持
sessionAffinity: ClientIP
# 会话保持超时时间
sessionAffinityConfig:
clientIP:
timeoutSeconds: 3600
适用场景:需要会话粘性的业务,保证同一客户端流量始终转发至同一个后端 Pod。普通无状态微服务无需开启。
3.2.5 完整清单
整合所有配置,完整可直接运行的单端口 ClusterIP 服务 YAML:
apiVersion: v1
kind: Service
metadata:
name: nginx–svc
namespace: default
spec:
type: ClusterIP
selector:
app: nginx–web
ports:
– name: http–web
port: 8080
targetPort: 80
protocol: TCP
sessionAffinity: ClientIP
sessionAffinityConfig:
clientIP:
timeoutSeconds: 3600
部署服务:
kubectl apply -f nginx-svc.yaml
3.3 验证测试
查看 Service 虚拟 IP 与端口:
kubectl get svc nginx-svc
输出示例:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-svc ClusterIP 10.98.17.136 <none> 8080/TCP 7s
查看后端绑定的 Pod 端点,验证匹配成功:
kubectl get endpoints nginx-svc
正常输出会展示 3 个后端 Pod 真实 IP,证明 Service 已成功关联全部业务副本:
NAME ENDPOINTS AGE
nginx-svc 100.84.42.200:80,100.84.42.203:80,100.99.87.177:80 2m19s
在集群内部,通过虚拟 IP:port 正常访问到真实服务:
[root@iZ2ze60mcbemirrld91q6qZ td]# curl 10.98.17.136:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
3.4 多端口 Service
很多应用需要同时暴露多个端口(比如 HTTP + HTTPS、业务端口 + 监控端口),Service 支持多端口配置,每个端口必须指定名称避免歧义:
apiVersion: v1
kind: Service
metadata:
name: my–service
spec:
selector:
app.kubernetes.io/name: MyApp
ports:
– name: http
protocol: TCP
port: 8080
targetPort: 80
– name: https
protocol: TCP
port: 443
targetPort: 443
命名规范:端口名只能包含小写字母、数字和横杠,且必须以字母数字开头和结尾。例如 123-abc、web 合法,123_abc、-web 不合法。

