Kubernetes 系列【16】服务:ClusterIP 核心原理与演示案例

发布时间:2026/7/14 12:26:07
Kubernetes 系列【16】服务:ClusterIP 核心原理与演示案例 文章目录1. 概述2. 工作原理2.1 分配虚拟 IP CIDR2.2 流量转发kube-proxy2.3 完整流量链路2.4 外部网络访问限制3. 演示案例3.1 定义工作负载3.2 定义 ClusterIP 服务3.2.1 基本信息3.2.2 标签选择器3.2.3 端口映射1port2targetPort3.2.4 其他可选配置3.2.5 完整清单3.3 验证测试3.4 多端口 Service1. 概述在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路由入口负责把外部流量按域名/路径分发到不同ServiceGateway APIIngress的升级替代方案功能更丰富、扩展性更强通过CRD实现更灵活的流量治理2. 工作原理2.1 分配虚拟 IP CIDRK8s安装时会单独划分一段虚拟 IP 地址池专门给Service使用这个地址段就叫Service CIDR这段IP不会分配给任何服务器、容器Pod只用来做Service的虚拟入口。新建ClusterIP Service时集群控制平面apiserveretcd会自动从这个池里挑一个没人用的IP绑定给当前Service。这个IP不是真实网卡IP是集群内部逻辑虚拟IP外部网络路由表里不存在这条地址。示例集群Service CIDR10.96.0.0/12创建后端服务Service自动分配虚拟IP10.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模式分步详细解析集群节点NodeA上的客户端Pod业务进程发起访问请求curl 10.96.12.34:8080ClusterIP流量进入NodeA本机内核被iptables规则拦截到达内核nat表的KUBE-SERVICES全局入口链匹配条件目标IP10.96.12.34、目标端口 8080匹配成功后自动跳转当前服务专属链KUBE-SVC-XXXX进入KUBE-SVC-XXXX服务负载均衡链kube-proxy预先根据后端3个Pod端点生成概率随机分流规则自动实现负载均衡按权重随机选择后端Pod1/Pod2/Pod3流量进入对应KUBE-SEP-XXX端点链KUBE-SEP链执行DNAT地址转换将数据包目标地址10.96.12.34:8080虚拟IP替换为 后端真实Pod容器IP示例10.96.12.34→10.244.x.x真实PodIPDNAT改写完成后内核重新根据最新目标IP路由若后端Pod在当前节点直接本机投递若后端Pod在其他节点通过集群CNI网络跨节点转发最终流量精准抵达后端真实业务Pod。核心总结ClusterIP只是逻辑入口无网卡、无实体仅存在于iptables规则中所有转发决策在请求发起节点完成负载均衡 DNAT全部在本地执行三层链分工明确KUBE-SERVICES匹配VIP→KUBE-SVC负载均衡→KUBE-SEPDNAT真实IP客户端全程无感后端真实Pod实现服务透明、弹性扩容、无感切换。2.4 外部网络访问限制两层网络隔离限制路由层面隔离服务器宿主机、机房外网网关、公网路由器都没有配置Service CIDR10.96.0.0/12这段地址的路由规则。外网机器发请求到10.96.x.x数据包一出节点就直接丢弃找不到转发路径。转发规则仅集群内生效iptables/ipvs转发规则只作用于集群内部网卡流量容器网桥、节点内部互通网卡节点物理网卡接收的外部流量不会触发这套转发规则。场景区分✅ 能访问集群内任意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/v1kind:Deploymentmetadata:name:nginx-webnamespace:defaultspec:# 启动3个Pod副本用于负载均衡演示replicas:3selector:matchLabels:app:nginx-webtemplate:metadata:labels:# 核心标签用于Service标签选择器精准匹配绑定app:nginx-webspec:containers:-name:nginx# 官方轻量镜像兼容x86/ARM架构稳定不崩溃image:nginx:latestports:# Nginx默认业务监听端口-containerPort:80执行部署命令快速拉起Nginx业务集群等待所有Pod就绪# 部署Nginx工作负载集群kubectl apply-fnginx-deploy.yaml# 查看Pod运行状态确保全部就绪Readykubectl get pods-owide正常输出可看到3个状态为Running的Nginx Pod每个Pod拥有独立内网IP且统一携带标签app: nginx-web为后续Service动态绑定、负载均衡提供核心匹配依据。nginx-web-55ff4cbb5c-4pwpn1/1 Running029s100.99.1.177 iz2ze60mcbemirrld91q6rznonenonenginx-web-55ff4cbb5c-rl6471/1 Running031s100.84.1.200 iz2ze60mcbemirrld91q6sznonenonenginx-web-55ff4cbb5c-sbjl81/1 Running019s100.84.1.203 iz2ze60mcbemirrld91q6sznonenone3.2 定义 ClusterIP 服务基于已部署的Nginx Pod集群我们创建默认类型的ClusterIP Service为动态可变的Pod提供固定虚拟IP、四层负载均衡能力。下面拆解Service所有核心配置项逐一讲解字段作用。3.2.1 基本信息基础元数据用于标识资源身份包含资源类型、服务名称、命名空间是集群资源管理、DNS自动解析的基础。创建nginx-svc.yaml基础配置如下apiVersion:v1kind:Servicemetadata:name:nginx-svcnamespace: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-webport:8080targetPort:80protocol:TCP字段详解portService对外暴露的虚拟端口集群内客户端通过ClusterIP:port访问服务targetPort后端Pod容器真实监听端口Nginx默认监听80端口protocol传输层协议默认TCP支持UDP、SCTP等1port是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等任意端口。2targetPort核心作用流量最终要送达的容器端口也就是你业务代码、中间件实际启动时监听的端口。Service收到流量后最终会转发到Pod的这个端口上。两种写法写具体端口号targetPort: 9376直接指定容器端口写端口名称targetPort: http-web-svc引用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服务YAMLapiVersion:v1kind:Servicemetadata:name:nginx-svcnamespace:defaultspec:type:ClusterIPselector:app:nginx-webports:-name:http-webport:8080targetPort:80protocol:TCPsessionAffinity:ClientIPsessionAffinityConfig:clientIP:timeoutSeconds:3600部署服务kubectl apply-fnginx-svc.yaml3.3 验证测试查看Service虚拟IP与端口kubectl get svc nginx-svc输出示例NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)AGE nginx-svc ClusterIP10.98.17.136none8080/TCP 7s查看后端绑定的Pod端点验证匹配成功kubectl get endpoints nginx-svc正常输出会展示3个后端Pod真实IP证明Service已成功关联全部业务副本NAME ENDPOINTS AGE nginx-svc100.84.42.200:80,100.84.42.203:80,100.99.87.177:80 2m19s在集群内部通过虚拟IP:port正常访问到真实服务[rootiZ2ze60mcbemirrld91q6qZ td]# curl 10.98.17.136:8080!DOCTYPE htmlhtmlheadtitleWelcome to nginx!/titlestylehtml{color-scheme: light dark;}body{width: 35em;margin:0auto;font-family: Tahoma, Verdana, Arial, sans-serif;}/style/headbodyh1Welcome to nginx!/h1pIf you see this page, the nginx web server is successfully installed and working. Further configuration is required./ppFor online documentation and support please refer toahrefhttp://nginx.org/nginx.org/a.br/Commercial support is available atahrefhttp://nginx.com/nginx.com/a./ppemThank youforusing nginx./em/p/body/html3.4 多端口 Service很多应用需要同时暴露多个端口比如HTTPHTTPS、业务端口 监控端口Service支持多端口配置每个端口必须指定名称避免歧义apiVersion:v1kind:Servicemetadata:name:my-servicespec:selector:app.kubernetes.io/name:MyAppports:-name:httpprotocol:TCPport:8080targetPort:80-name:httpsprotocol:TCPport:443targetPort:443命名规范端口名只能包含小写字母、数字和横杠且必须以字母数字开头和结尾。例如123-abc、web合法123_abc、-web不合法。