当前位置: 首页 > news >正文

Kubernetes Service详解:实现服务发现与负载均衡

image

1. Service概念引入

  k8s之部署Deployment章节我们介绍RS以及Deployment,Deployment提供了pod的管理方式,以及通过副本控制器RC保证集群中pod的数量保持为指定数量。同时Deployment还提供了相关升级、回滚、更新速度、灰度发布等功能。那么pod之间怎么进行访问呢?在之前我们提过k8s之间的node网络是互通的,同时它里面的pod网络也是互通的,相关结构如下图所示(暂时可以不需要理解里面的service,看得懂通过curl ip即可):

graph TD%% 定义节点和 Podsubgraph NodeA["NodeA (192.168.1.10)"]direction TBPodA["PodAIP: 10.244.1.5Port: 8080"]PodX["PodxIP: 10.244.1.xPort: xx"] endsubgraph NodeB["NodeB (192.168.1.11)"]direction TBPodB["PodBIP: 10.244.2.8Listens: 8080"]end%% 定义 ServiceService["Service: podB-serviceClusterIP: 10.96.xx.xxPort: 80 → targetPort: 8080"]%% 正确通信路径 —— PodA → PodBPodA -->|✅直接访问 Pod IP<br>curl http://10.244.2.8:8080</br>| PodB%% 推荐路径 —— PodA → Service → PodBPodA -->|✅推荐:通过 Service<br>curl http://podB-service:80</br>| ServiceService -->|自动负载均衡| PodB%% 错误路径(虚线 + 红色风格)PodA -.->|❌通常无效<br>curl http://192.168.1.11:8080</br>| NodeBPodA -->|✅显式设置<br>curl http://192.168.1.11:8080</br>| NodeB%% 添加说明注释classDef node fill:#e0f7fa,stroke:#0097a7;classDef pod fill:#fff9c4,stroke:#fbc02d;classDef svc fill:#c8e6c9,stroke:#388e3c;classDef invalid stroke:#f44336,stroke-dasharray: 5 5;class NodeA,NodeB nodeclass PodA,PodB podclass Service svcclass NodeB invalid

  在集群中,pod可以通过指定podB的ip以及端口进行访问。比如说,应用A访问应用B,我们可以配置应用A中请求地址便可以进行访问,但是如果pod挂了呢?通过上一章节的介绍,我们知道pod挂了之后,会重新启动一个新的pod,但问题是ip也变了,这样便没法访问了。这时候,肯定会有人说,Java boy不惧怕任何事情,俺有nacos!!nacos可以进行自动负载均衡以及服务发现,不需要配置ip,只需要配置服务名。是的,如果是使用nacos,集群内部的访问便变得简单了(其实nacos的作用跟今天所介绍的service很相似),但问题又来了,如果别人的应用没有注册到nacos上面去呢?万一我是一个phper呢?又或者说,我集群内部的某个pod需要对外提供服务呢?这时候,便需要k8s中的Service来帮忙了。

2. 什么是Service

Kubernetes 中 Service 是 将运行在一个或一组 ​Pod​ 上的网络应用程序公开为网络服务的方法​[注]

  我们可以这样理解:Service 是 Kubernetes 中定义的一组 Pod 的稳定网络入口(抽象),用于实现服务发现与负载均衡。 在我们部署应用的时候,为了服务的高可用性,一般来说,我们会将应用X部署在多个pod上,例如podA,podB,podC,他们各自有自己的ip地址。k8s的service将这三个pod给包装起来了,包装为了一个服务(service),其他的应用需要访问应用X的时候,不再需要通过通过ip地址来访问,而是直接通过服务名来访问。例如,这个服务名叫做my-svc.my-ns.svc.cluster.local​,那么其他应用直接通过http://my-svc.my-ns.svc.cluster.local​便可以访问应用X了。这是因为当你请求这个域名的时候,k8会为你自动转发到对应的pod上去。

  通过上面可以解释我们可以知道,k8s的service主要有如下作用:

  1. 解耦服务消费者与提供者:客户端只需访问 Service 名称,无需知道后端 Pod IP(Pod 是临时的,IP 会变);
  2. 自动负载均衡:将流量分发到所有健康的后端 Pod;
  3. 提供稳定的网络端点:即使 Pod 重建、扩缩容,Service 的 ClusterIP 和 DNS 名称保持不变(这个之后解释)。

3. Service的分类

  根据Service的作用不同,可以分为如下的4种Service。

3.1 ClusterIP

  ClusterIP的作用主要是在集群内部暴露服务,仅集群内可访问。举个列子,我用python写了一个算法服务,这个算法服务提供了一个http请求接口,然后我java应用想要调用这个算法服务,我便可以将这个算法服务包装为一个ClusterIP类型的Service,专门提供给java应用调用。那么,他的原理是怎样的呢?

  如下的代码,便是构建一个ClusterIP类型的service:

apiVersion: v1
kind: Service
metadata:name: backend-svc
spec:type: ClusterIPselector:app: backend  # 匹配的podports:- port: 80targetPort: 8080

  其中port=80代表这个service对外暴露的端口,也就是另一个pod需要访问backend这个后端pod服务,需要通过http://backend-svc:80来进行访问。targetPort=8080,代表service会将流量转移到后端pod的哪个端口。

  ClusterIP 类型的 Service 会被分配一个集群内部的专有且唯一的虚拟 IP 地址(由 Kubernetes 的控制平面从 --service-cluster-ip-range​ 指定的 CIDR 范围中分配)。这个 IP 不是真实网卡上的 IP,而是一个“虚拟 IP(ClusterIP)”。它只在 Kubernetes 集群内部可达,外部无法直接访问。然后k8s内置的dns服务会为该service创建一个dns记录,将例子中的backend-svc​解析为这个虚拟ip。这样集群中的pod都会在访问backend-svc​这个域名的时候就会自动解析到这个ClusterIP中。同时k8s的控制平面也会创建一个同名的Endpoints 对象,记录对应Service当前实际可用的后端pod IP地址和端口列表。

image

  在前面的知识中,我们知道,kube-proxy运行在每一个Node节点中,监听Service和Endpoints的变化。当他发现有一个clusterIP service变化的时候,就会用小本本记录下来,然后生成相关的ip映射规则(建立cluster IP和pod IP的映射规则)。这样,当节点中的某个pod访问Service的时候,节点中的Kube-Proxy就可以根据ip映射规则,将流量转发到对应的服务上去。当然,一个cluster IP会对应多个pod IP,具体访问哪一个,就根据kube-proxy设置的算法来进行执行。

@startuml
title Kubernetes Service 数据流转:Service → Endpoints → kube-proxy → Podactor "客户端 Pod" as client
participant "CoreDNS" as dns
participant "API Server" as apiserver
participant "Endpoints Controller" as controller
participant "kube-proxy" as kubeproxy
participant "后端 Pod" as podclient -> dns : 1. 解析 DNS 名称\nmy-svc.ns.svc.cluster.local
dns --> client : 2. 返回 ClusterIP\n(例如: 10.96.100.10)client -> kubeproxy : 3. 访问 10.96.100.10:80\n(通过节点网络栈)
activate kubeproxynote right of kubeproxykube-proxy 维护 iptables/IPVS 规则,将 ClusterIP 映射到后端 Pod IP,规则数据来源于 Endpoints。
end notekubeproxy -> pod : 4. 转发到 Pod IP:端口\n(例如: 10.244.1.5:80)
activate pod
pod --> kubeproxy : 5. 返回响应
deactivate pod
kubeproxy --> client : 6. 返回响应给客户端
deactivate kubeproxy== 后台:Endpoints 同步流程 ==pod -> apiserver : 7. Pod 创建成功\n(标签: app=web)
apiserver -> controller : 8. 监听事件:新 Pod 匹配\nService 的标签选择器
controller -> apiserver : 9. 创建/更新 Endpoints\n(my-svc,包含 Pod IP)
apiserver -> kubeproxy : 10. 推送 Endpoints 变更事件
kubeproxy -> kubeproxy : 11. 更新本地 iptables/IPVS 规则@enduml

  ‍

3.2 NodePort

  在每个节点的 IP 上开放一个固定端口,外部可通过 <NodeIP>:<NodePort>​ 访问服务,NodePort 范围默认为 30000-32767​。什么意思呢?在Cluster IP类型的service中,集群内部访问当然没问题,但是如果是集群外部呢?集群外部如何访问集群内部的服务呢?这时候我们就需要创建一个NodePort类型的service了。当创建一个 type: NodePort 的 Service 时,Kubernetes 实际上做了两件事:

  1. 创建一个ClusterIP的Service(比如 ClusterIP是10.96.123.45
  2. 在每个节点上监听一个端口(比如 31234)。

  当外部流量通过 <NodeIP>:31234​ 进入节点时,kube-proxy 会将该流量转发到 Service 的 ClusterIP,然后再由 ClusterIP 的规则转发到后端 Pod。

外部请求 → NodeIP:NodePort → (kube-proxy 转发) → ClusterIP → 后端 Pod

  这个时候,我们再看k8s官网的这句话,应该就能理解了吧。

通过每个节点上的 IP 和静态端口(NodePort​)公开 Service。 为了让 Service 可通过节点端口访问,Kubernetes 会为 Service 配置集群 IP 地址, 相当于你请求了 type: ClusterIP 的 Service。

3.3 LoadBalancer

  前面的NodePort类型的service解决了集群外部访问集群内部服务的问题,那么又有一个问题来了,我要是公网想访问集群内部的服务呢?在k8s集群中,node的节点ip都是分配的内网ip,我们肯定是无法在公网上使用node ip来访问对应的服务。这时候就需要借助LoadBalancer Service了。

  ​LoadBalancer​ 是 k8s中最“面向外部”的 Service 类型之一,它建立在 NodePort ClusterIP之上,专为云环境设计,用于自动创建一个外部负载均衡器,将流量从互联网直接导入你的服务。也就是说,当创建一个LoadBalancer的service时:

  1. Kubernetes 会:

    • 自动分配一个 ​ClusterIP(内部使用)
    • 自动分配一个 ​NodePort(每个节点开放该端口)
  2. 云控制器管理器(cloud-controller-manager) 会检测到这个 Service,​自动向云平台 API 请求创建一个外部负载均衡器

  3. 该负载均衡器会被配置为:

    • 前端​:分配一个公网 IP(或 DNS 名称)
    • 后端:将流量转发到所有节点的 NodePort
@startuml
skinparam componentStyle rectangle
skinparam defaultTextAlignment centerpackage "Kubernetes 集群" {[节点 1\n(192.168.1.10)] as node1[节点 2\n(192.168.1.11)] as node2[节点 3\n(192.168.1.12)] as node3package "Pod 实例" {[Pod A\n(app: web)] as podA[Pod B\n(app: web)] as podB}
}cloud "外部网络" {[用户 / 客户端] as client[云负载均衡器\n(公网IP: 203.0.113.10)] as lb
}node "Service 抽象层" {[ClusterIP\n10.96.45.67:80] as clusteripnote right of clusterip集群内部虚拟 IP仅可在集群内访问end note
}' 连接关系
client --> lb : 访问服务\n(203.0.113.10:80)
lb --> node1 : 转发流量\n到 NodePort 31234
lb --> node2 : 转发流量\n到 NodePort 31234
lb --> node3 : 转发流量\n到 NodePort 31234node1 --> clusterip : kube-proxy\n将流量 DNAT 到 ClusterIP
node2 --> clusterip : kube-proxy\n将流量 DNAT 到 ClusterIP
node3 --> clusterip : kube-proxy\n将流量 DNAT 到 ClusterIPclusterip --> podA : 通过 iptables/IPVS\n负载均衡到 Pod
clusterip --> podB : 通过 iptables/IPVS\n负载均衡到 Pod' Service 类型说明
note top of lb<b>LoadBalancer 类型</b>• 云平台自动创建外部负载均衡器• 底层依赖 NodePort
end notenote bottom of node1<b>NodePort 类型</b>• 在每个节点开放端口(30000-32767)• 可通过 <节点IP>:<NodePort> 访问
end notenote right of clusterip<b>ClusterIP 类型</b>• 默认 Service 类型• 仅限集群内部访问
end note@enduml

3.4 ExternalName

  前面介绍的几种Service都是将自己暴露出去,将pod的服务以更加便捷形式提供给外界使用。那么反过来呢,如何让外界服务更加便捷给内部使用呢?那么便是ExternalName Service提供的功能了。

  ExternalName Service 会在集群内部创建一个 DNS 别名(CNAME),指向你指定的外部服务地址(如 api.example.com),让 Pod 可以像访问内部服务一样访问外部服务。本质上来说,就是给外部服务取了一个DNS层面的别名。

4. 参考

[注]

服务(Service) | Kubernetes

http://www.hskmm.com/?act=detail&tid=27094

相关文章:

  • Jmeter批量调用不同值参数的CSV
  • 【一步步开发AI运动APP】十二、自定义扩展新运动项目2
  • 2025 年最新真石漆厂家排行榜:别墅外墙 / 专业仿砖 / 天然涂料优质厂家最新推荐指南
  • if 和 else 的用法
  • The 4th Universal Cup
  • 18、更改公司电脑wifi密码
  • 有难度哦/Qt基于通用地图组件实现航迹规划和模拟/动态标注轨迹线/带序号和方向箭头指示
  • 【GitHub每日速递 251009】AI时代必备!Stagehand浏览器自动化框架解锁高效新玩法
  • iOS应用商店遭遇首次大规模恶意软件攻击
  • VMware ESXi 9.0.1.0 macOS Unlocker OEM BIOS 2.7 集成网卡驱动和 NVMe 驱动 (集成驱动版)
  • vue3使用ts传参教程
  • 解密prompt系列61. 手搓代码沙箱与FastAPI-MCP实战
  • MySQL 高可用构建方案详解
  • VMware ESXi 9.0.1.0 macOS Unlocker OEM BIOS 2.7 标准版和厂商定制版
  • 多机器人协同首现基础模型技术突破
  • PHP 图像处理实战 GD/Imagick 从入门到精通,构建高性能图像服务
  • 2025氧化镁厂家、活性氧化镁厂家、肥料级氧化镁厂家最新推荐榜:实力生产与优质供应之选
  • 2025学校家具定制厂家/书包柜厂家推荐榜:专业设计与安全品质首选
  • 2025农机带厂家最新推荐榜:质量可靠与耐用性能兼备之选
  • 2025深圳电源适配器厂家最新推荐榜:高效耐用与安全认证深度解析
  • 2025试验机厂家最新推荐榜:精准测量与高效检测口碑之选
  • 2025喷砂厂家 / 热喷锌厂家 / 热喷铝厂家 / 油漆涂装厂家 / 热喷耐磨材料厂家 / 防腐工程厂家最新推荐榜:高效作业与优质工艺口碑之选
  • 2025上海经济纠纷律师/民事纠纷律所最新推荐榜:专业辩护与胜诉保障口碑之选
  • Semantic Kernel + AutoGen = 开源 Microsoft Agent Framework
  • 读技术之外:社会联结中的人工智能04数据
  • Potplayer Official Download LINK
  • 二廿计划(25.10.09 - 25.10.29)
  • 生成式AI与计算教育融合研究
  • 博科SAN switch 所有端口的led闪橙色
  • 251008