【Kubernetes】(六)Service
目录
一、Service 的核心价值:为动态 Pod 提供 “稳定入口”
二、kube-proxy:Service 流量转发的 “执行者”
1. iptables 模式
2. IPVS 模式
三、不同类型的 Service:满足 “不同范围的访问需求”
1. ClusterIP 类型
2. NodePort 类型
3. Headless 类型
4. LoadBalancer 类型
5. Ingress 控制器(补充:七层流量管理)
四、四种控制器对比
五、Ingress 控制器 vs Service
六、几个服务的关系
1. 同一服务,多方式暴露: 比如一个 Web 服务,可同时通过:
2. 功能互补:
七、何时用什么?
八、Service 类型的设置规则
1. Service 类型的设置时机:创建时指定,后期不可直接修改类型
2. 如何将 Service 设置为特定类型?
方式 1:命令行创建时指定类型
方式 2:YAML 文件声明类型
3. 一个 Service 能否同时属于多个类型?
总结
一、Service 的核心价值:为动态 Pod 提供 “稳定入口”
Pod 是 Kubernetes 中最基础的运行单元,但 Pod 是 “临时性” 的(重启、扩容、更新都会导致 IP 变化)。如果前端 Pod 直接依赖后端 Pod 的 IP 通信,一旦后端 Pod 重建,前端就会 “连不上”。
Service 的作用:为一组功能相同的 Pod(通过标签选择器关联)绑定一个固定的访问地址(IP + 端口)。前端只需访问 Service 的地址,流量会自动转发到后端的某个 Pod,无需关心 Pod 的具体 IP。
二、kube-proxy:Service 流量转发的 “执行者”
kube-proxy 是每个节点上的核心组件,负责把 “访问 Service 的流量” 转发到后端 Pod。它支持两种代理模式,决定了流量的转发逻辑:
1. iptables 模式
- 工作逻辑:
kube-proxy 监听 Kubernetes API Server,同步 Service(服务对象)和 Endpoints(后端 Pod 列表及地址)的变化。
对每个 Service,kube-proxy 会在节点的 iptables(Linux 内核的包过滤工具)中添加规则链:当流量访问 Service 的 ClusterIP:端口 时,iptables 会捕获流量,并 “重定向” 到某一个后端 Pod 的 IP:端口。 - 转发策略:默认随机选择一个后端 Pod(也支持会话保持等策略)。
- 优缺点:
- 优点:流量由 Linux 内核 netfilter 处理,无需用户空间与内核空间的上下文切换,小规模集群性能足够。
- 缺点:当 Service/Endpoints 数量极多(如上千个),iptables 规则会变得极其庞大,同步规则时延迟高,甚至影响节点性能;高并发下可能出现 “流量倾斜”(部分 Pod 流量过多)。
2. IPVS 模式
- 工作逻辑:
IPVS(IP Virtual Server,Linux 内核负载均衡模块)是更专业的 “四层负载均衡” 工具。kube-proxy 开启 IPVS 模式后,通过 netlink 接口(内核与用户空间的高效通信方式)创建 IPVS 规则,将 Service 流量转发到后端 Pod。
同样会实时同步 Service 和 Endpoints 的变化,确保 IPVS 规则与集群状态一致。 - 转发策略:支持更丰富的策略(轮询、最少连接、目标哈希等)。
- 优缺点:
- 优点:基于哈希表组织规则,查找速度比 iptables 的 “线性规则链” 快几个数量级,适合大规模集群(成千上万个 Service);完全工作在内核空间,转发延迟更低,支持更高网络吞吐量。
- 缺点:需要 Linux 内核支持 IPVS 模块(现代 Linux 发行版一般已支持,若不支持需手动加载)。
三、不同类型的 Service:满足 “不同范围的访问需求”
Kubernetes 定义了多种 Service 类型,核心是让 “服务” 能被不同范围的对象访问(集群内、集群外、公网等):
1. ClusterIP 类型
- 特点:Service 会被分配一个仅在集群内部可访问的 IP(称为 ClusterIP)。
- 访问范围:只能被集群内的 Pod、其他 Service 访问,集群外部无法直接访问。
- 典型场景:集群内部的中间件服务(如数据库、消息队列),仅需被集群内应用调用。
2. NodePort 类型
- 特点:在 ClusterIP 基础上,为 Service 在集群的每个节点上绑定一个固定端口(范围 30000-32767)。
- 访问方式:外部可通过 「任意节点的 IP」:「NodePort 端口」 访问 Service。
- 典型场景:需要让集群外的临时客户端(如测试环境的本地机器)访问集群内服务。
3. Headless 类型
- 特点:没有固定的 ClusterIP。访问 Headless Service 时,DNS 会直接解析到后端所有 Pod 的 IP 列表(而非 Service 自己的 IP)。
- 访问方式:客户端需自行决定连接哪个 Pod 的 IP(如数据库主从集群,需直接连主库 IP)。
- 典型场景:有状态应用(如 MySQL 主从、ZooKeeper 集群),需要 “直接与特定 Pod 通信” 的场景。
4. LoadBalancer 类型
- 特点:结合云服务商的负载均衡器(如 AWS ELB、阿里云 SLB)使用。创建该类型 Service 时,云平台会自动分配一个公网负载均衡器,并将流量转发到集群内的 Service。
- 访问方式:外部通过负载均衡器的公网 IP 访问服务。
- 典型场景:需要暴露到公网的生产环境应用(如用户访问的 Web 服务)。
- MetalLB 是 Kubernetes(K8s)集群里的一个工具,专门用来解决 “非云环境下,K8s 如何为服务提供外部可访问的固定 IP” 的问题(因为默认 K8s 在自建集群 / 非云平台中,LoadBalancer 类型的 Service 无法自动获取公网 IP,MetalLB 填补了这个空缺)。
它的工作主要分两步:
①地址分配
当你创建一个 LoadBalancer 类型的 K8s Service 时,MetalLB 的 Controller(以 Deployment 方式运行,负责监听 Service 的变化)会从预先配置的 IP 地址池里,分配一个 IP 给这个 Service。等 Service 被删除,这个 IP 会 “归还” 到地址池,供后续其他 Service 使用。
② 对外广播
光有 IP 还不够,得让集群外部的网络知道这个 IP 能访问集群内的服务。这时候 MetalLB 的 Speaker(以 DaemonSet 方式运行,集群每个节点都会部署)会通过 “路由协议”(支持 Layer 2 或 BGP 两种模式),把分配的 IP “广播” 到整个网络里,这样外部流量就能正确路由到集群内的服务了。
简单说:MetalLB 就是给自建 K8s 集群 “模拟云厂商的负载均衡器能力”,让 LoadBalancer 类型的 Service 能像在云里一样,获得外部可访问的 IP 并对外提供服务。
5. Ingress 控制器(补充:七层流量管理)
- 定位:Ingress 不是 Service 的 “类型”,而是更高级的 “HTTP 层(七层)流量管理工具”,用于统一管理多个 Service 的 HTTP 访问。
- 作用:通过域名(如 api.example.com)或路径(如 example.com/api),将外部 HTTP/HTTPS 请求转发到集群内不同的 Service。
- 典型场景:集群内有多个 Web 服务(如订单服务、用户服务),希望通过 “一个域名 + 不同路径” 区分访问(无需为每个服务单独开 NodePort/LoadBalancer)。
四、四种控制器对比
关键细节补充
- ClusterIP:默认类型,分配集群内虚拟 IP(如 10.96.0.1),仅集群内 Pod 可通过 ClusterIP:Port 访问,适合服务间通信。
- NodePort:在 ClusterIP 基础上,为每个节点开放静态端口(如 30080),外部通过 节点IP:30080 访问。缺点:节点 IP 变化需维护,适合测试。
- LoadBalancer:依赖云厂商,自动创建公网负载均衡器(如 AWS ELB、阿里云 SLB),分配公网 IP,流量经 LB → 节点 NodePort → Pod。适合生产公网服务。
- Headless:通过 clusterIP: None 关闭虚拟 IP,DNS 直接解析Pod IP 列表(如 pod-0.app.default.svc.cluster.local 对应 Pod IP)。适合 StatefulSet(如数据库集群,需直接访问特定 Pod)。
五、Ingress 控制器 vs Service
Ingress 是 七层(HTTP/HTTPS) 流量管理方案,和四层 Service 的核心差异:
六、几个服务的关系
分层协作的关系:
1. 同一服务,多方式暴露:
比如一个 Web 服务,可同时通过:
ClusterIP 供集群内服务调用;
NodePort 供测试人员调试;
LoadBalancer 供公网用户访问;
Ingress 实现 www.example.com 域名路由(Ingress 后端指向该服务的 ClusterIP)。
2. 功能互补:
Service 解决 “Pod 怎么被找到”(四层转发);
Ingress 解决 “HTTP 流量怎么精细路由”(七层策略,如域名、路径、SSL)。
例如:Ingress 控制器本身需通过 LoadBalancer 或 NodePort 类型的 Service 暴露公网,才能接收外部 HTTP 请求。
七、何时用什么?
- 集群内通信 → ClusterIP(默认,简单稳定)。
- 临时外部访问 → NodePort(快速,无需额外资源)。
- 生产公网服务 → LoadBalancer(云厂商托管,高可用公网 IP)。
- StatefulSet 或自定义负载 → Headless(直接访问 Pod,灵活)。
- HTTP 精细路由(多域名、路径) → Ingress + Service(七层策略,配合四层转发)。
示例场景:
一个电商应用的 订单服务:
- 集群内的 库存服务 → 通过 ClusterIP 调用;
- 开发环境 → 通过 NodePort(192.168.1.10:30080)调试;
- 生产环境 → 通过 LoadBalancer 分配公网 IP,供 APP 后端调用;
- 前端 Web → 通过 Ingress 配置 /order 路径,路由到该服务的 ClusterIP,实现路径级转发;
- 若订单服务是 StatefulSet(如分库分表代理)→ 用 Headless Service 让客户端直接访问特定 Pod。
通过分层设计,不同组件各司其职,共同支撑复杂业务的访问需求。
八、Service 类型的设置规则
要理解 Kubernetes Service 类型的设置规则,需从 “创建时机、修改方式、类型互斥性” 三个维度分析:
1. Service 类型的设置时机:创建时指定,后期不可直接修改类型
Kubernetes 中,Service 的 type 字段属于 **“不可变(Immutable)” 属性 **—— 一旦创建,无法直接修改类型(如从 ClusterIP 改成 NodePort)。
- 原因:不同类型的 Service 对应完全不同的 “网络配置逻辑”(如 NodePort 需要在节点开端口,LoadBalancer 需要对接云厂商负载均衡器),动态修改会导致网络状态不一致。
- 解决方法:若需变更类型,需删除旧 Service,重新创建新 Service(需保证新 Service 的标签选择器与旧 Service 一致,避免后端 Pod 连接中断)。
2. 如何将 Service 设置为特定类型?
有两种方式:命令行快速创建或YAML 声明式创建。
方式 1:命令行创建时指定类型
用 kubectl create service 或 kubectl expose 命令,通过 --type 参数指定类型:
# 示例 1:创建 ClusterIP 类型的 Service(默认类型)
kubectl create service clusterip my-service \--tcp=80:80 # 容器端口 80 映射到 Service 端口 80# 示例 2:暴露 Deployment 为 NodePort 类型的 Service
kubectl expose deployment my-deployment \--type=NodePort \--port=8080 \--target-port=80# 示例 3:创建 LoadBalancer 类型的 Service(需云厂商支持)
kubectl create service loadbalancer my-lb-service \--tcp=443:8443
方式 2:YAML 文件声明类型
在 Service 的 YAML 中显式设置 spec.type 字段,再通过 kubectl apply 创建:
# service.yaml(NodePort 类型示例)
apiVersion: v1
kind: Service
metadata:name: my-service
spec:type: NodePort # 指定类型为 NodePortselector:app: my-app # 关联标签为 app=my-app 的 Podports:- port: 80 # Service 对外端口targetPort: 8080 # Pod 内容器端口nodePort: 30080 # 可选:指定 NodePort 端口(默认自动分配 30000-32767)
创建命令:
kubectl apply -f service.yaml
3. 一个 Service 能否同时属于多个类型?
不能。Service 的 type 是单一枚举值,只能是以下类型之一:
- ClusterIP(默认,集群内访问)
- NodePort(集群节点开放端口,外部可访问)
- LoadBalancer(对接云厂商负载均衡器,公网可访问)
- ExternalName(将 Service 映射为外部域名,如 example.com)
- Headless(特殊的 ClusterIP,clusterIP: None,直接解析 Pod IP)
补充:“多类型访问” 的替代方案
若需让一个服务同时支持 “集群内访问(ClusterIP)” 和 “外部访问(NodePort/LoadBalancer)”,不能直接给 Service 设多个类型,但可通过以下方式实现:
创建两个 Service:一个 ClusterIP 类型(集群内用),一个 NodePort/LoadBalancer 类型(外部用),但两个 Service 关联同一个后端 Pod(通过相同的标签选择器)。
用 Ingress 统一管理:将 ClusterIP 类型的 Service 通过 Ingress 暴露(Ingress 是七层 HTTP 路由,可同时处理内部和外部流量)。
总结
Service 解决 “Pod 动态 IP 导致的访问问题” → kube-proxy 负责 “Service 到 Pod 的流量转发”(iptables/IPVS 二选一) → 不同类型的 Service 解决 “服务该被谁访问” 的范围问题 → Ingress 则在 HTTP 层进一步统一管理多服务的外部访问。