k8s服务发现之第二弹Service详解

news2025/3/10 17:53:56

创建 Service

Kubernetes Servies 是一个 RESTFul 接口对象,可通过 yaml 文件创建。

例如,假设您有一组 Pod:

  • 每个 Pod 都监听 9376 TCP 端口
  • 每个 Pod 都有标签 app=MyApp
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: MyApp
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376

上述 YAML 文件可用来创建一个 Service:

  • 名字为 my-service
  • 目标端口为 TCP 9376
  • 选取所有包含标签 app=MyApp 的 Pod

关于 Service,您还需要了解:

  • Kubernetes 将为该 Service 分配一个 IP 地址(ClusterIP 或 集群内 IP),供 Service Proxy 使用(参考虚拟 IP 和 Service proxy)
  • Kubernetes 将不断扫描符合该 selector 的 Pod,并将最新的结果更新到与 Service 同名 my-service 的 Endpoint 对象中。

Service 从自己的 IP 地址和 port 端口接收请求,并将请求映射到符合条件的 Pod 的 targetPort。为了方便,默认 targetPort 的取值 与 port 字段相同

  • Pod 的定义中,Port 可能被赋予了一个名字,您可以在 Service 的 targetPort 字段引用这些名字,而不是直接写端口号。这种做法可以使得您在将来修改后端程序监听的端口号,而无需影响到前端程序。
  • Service 的默认传输协议是 TCP,您也可以使用其他 支持的传输协议。
  • Kubernetes Service 中,可以定义多个端口,不同的端口可以使用相同或不同的传输协议。

创建 Service(无 label selector)

Service 通常用于提供对 Kubernetes Pod 的访问,但是您也可以将其用于任何其他形式的后端。例如:

  • 您想要在生产环境中使用一个 Kubernetes 外部的数据库集群,在测试环境中使用 Kubernetes 内部的 数据库
  • 您想要将 Service 指向另一个名称空间中的 Service,或者另一个 Kubernetes 集群中的 Service
  • 您正在将您的程序迁移到 Kubernetes,但是根据您的迁移路径,您只将一部分后端程序运行在 Kubernetes 中

在上述这些情况下,您可以定义一个没有 Pod Selector 的 Service。例如:

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376

因为该 Service 没有 selector,相应的 Endpoint 对象就无法自动创建。您可以手动创建一个 Endpoint 对象,以便将该 Service 映射到后端服务真实的 IP 地址和端口:

apiVersion: v1
kind: Endpoints
metadata:
  name: my-service
subsets:
  - addresses:
      - ip: 192.0.2.42
    ports:
      - port: 9376
  • Endpoint 中的 IP 地址不可以是 loopback(127.0.0.0/8 IPv4 或 ::1/128 IPv6),或 link-local(169.254.0.0/16 IPv4、224.0.0.0/24 IPv4 或 fe80::/64 IPv6)
  • Endpoint 中的 IP 地址不可以是集群中其他 Service 的 ClusterIP

对于 Service 的访问者来说,Service 是否有 label selector 都是一样的。在上述例子中,Service 将请求路由到 Endpoint 192.0.2.42:9376 (TCP)。

ExternalName Service 是一类特殊的没有 label selector 的 Service,该类 Service 使用 DNS 名字。

虚拟 IP 和服务代理

Kubernetes 集群中的每个节点都运行了一个 kube-proxy,负责为 Service(ExternalName 类型的除外)提供虚拟 IP 访问。

为何不使用 round-robin DNS

许多用户都对 Kubernetes 为何使用服务代理将接收到的请求转发给后端服务,而不是使用其他途径,例如:是否可以为 Service 配置一个 DNS 记录,将其解析到多个 A value(如果是 IPv6 则是 AAAA value),并依赖 round-robin(循环)解析?

Kubernetes 使用在 Service 中使用 proxy 的原因大致有如下几个:

  • 一直以来,DNS 软件都不确保严格检查 TTL(Time to live),并且在缓存的 dns 解析结果应该过期以后,仍然继续使用缓存中的记录
  • 某些应用程序只做一次 DNS 解析,并一直使用缓存下来的解析结果
  • 即使应用程序对 DNS 解析做了合适的处理,为 DNS 记录设置过短(或者 0)的 TTL 值,将给 DNS 服务器带来过大的负载

版本兼容性

Kubernetes 支持三种 proxy mode(代理模式),他们的版本兼容性如下:

代理模式Kubernetes 版本是否默认
User space proxy modev1.0 +
Iptables proxy modev1.1 +默认
Ipvs proxy modev1.8 +

User space 代理模式

在 user space proxy mode 下:

  • kube-proxy 监听 kubernetes master 以获得添加和移除 Service / Endpoint 的事件
  • kube-proxy 在其所在的节点(每个节点都有 kube-proxy)上为每一个 Service 打开一个随机端口
  • kube-proxy 安装 iptables 规则,将发送到该 Service 的 ClusterIP(虚拟 IP)/ Port 的请求重定向到该随机端口
  • 任何发送到该随机端口的请求将被代理转发到该 Service 的后端 Pod 上(kube-proxy 从 Endpoint 信息中获得可用 Pod)
  • kube-proxy 在决定将请求转发到后端哪一个 Pod 时,默认使用 round-robin(轮询)算法,并会考虑到 Service 中的 SessionAffinity 的设定

image-20230713195521095

Iptables 代理模式

在 iptables proxy mode 下:

  • kube-proxy 监听 kubernetes master 以获得添加和移除 Service / Endpoint 的事件
  • kube-proxy 在其所在的节点(每个节点都有 kube-proxy)上为每一个 Service 安装 iptable 规则
  • iptables 将发送到 Service 的 ClusterIP / Port 的请求重定向到 Service 的后端 Pod 上
    • 对于 Service 中的每一个 Endpoint,kube-proxy 安装一个 iptable 规则
    • 默认情况下,kube-proxy 随机选择一个 Service 的后端 Pod

image-20230713195607625

iptables proxy mode 的优点:

  • 更低的系统开销:在 linux netfilter 处理请求,无需在 userspace 和 kernel space 之间切换
  • 更稳定

与 user space mode 的差异:

  • 使用 iptables mode 时,如果第一个 Pod 没有响应,则创建连接失败
  • 使用 user space mode 时,如果第一个 Pod 没有响应,kube-proxy 会自动尝试连接另外一个后端 Pod

您可以配置 Pod 就绪检查(readiness probe)确保后端 Pod 正常工作,此时,在 iptables 模式下 kube-proxy 将只使用健康的后端 Pod,从而避免了 kube-proxy 将请求转发到已经存在问题的 Pod 上。

IPVS 代理模式

在 IPVS proxy mode 下:

  • kube-proxy 监听 kubernetes master 以获得添加和移除 Service / Endpoint 的事件
  • kube-proxy 根据监听到的事件,调用 netlink 接口,创建 IPVS 规则;并且将 Service/Endpoint 的变化同步到 IPVS 规则中
  • 当访问一个 Service 时,IPVS 将请求重定向到后端 Pod

image-20230713195646811

IPVS 模式的优点

IPVS proxy mode 基于 netfilter 的 hook 功能,与 iptables 代理模式相似,但是 IPVS 代理模式使用 hash table 作为底层的数据结构,并在 kernel space 运作。这就意味着

  • IPVS 代理模式可以比 iptables 代理模式有更低的网络延迟,在同步代理规则时,也有更高的效率
  • 与 user space 代理模式 / iptables 代理模式相比,IPVS 模式可以支持更大的网络流量

IPVS 提供更多的负载均衡选项:

  • rr: round-robin
  • lc: least connection (最小打开的连接数)
  • dh: destination hashing
  • sh: source hashing
  • sed: shortest expected delay
  • nq: never queue
  • 如果要使用 IPVS 模式,您必须在启动 kube-proxy 前为节点的 linux 启用 IPVS
  • kube-proxy 以 IPVS 模式启动时,如果发现节点的 linux 未启用 IPVS,则退回到 iptables 模式

代理模式总结

在所有的代理模式中,发送到 Service 的 IP:Port 的请求将被转发到一个合适的后端 Pod,而无需调用者知道任何关于 Kubernetes/Service/Pods 的细节。

Service 中额外字段的作用:

  • service.spec.sessionAffinity
    
    • 默认值为 “None”
    • 如果设定为 “ClientIP”,则同一个客户端的连接将始终被转发到同一个 Pod
  • service.spec.sessionAffinityConfig.clientIP.timeoutSeconds
    
    • 默认值为 10800 (3 小时)
    • 设定会话保持的持续时间

多端口的Service

Kubernetes 中,您可以在一个 Service 对象中定义多个端口,此时,您必须为每个端口定义一个名字。如下所示:

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: MyApp
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 9376
    - name: https
      protocol: TCP
      port: 443
      targetPort: 9377

端口的名字必须符合 Kubernetes 的命名规则,且,端口的名字只能包含小写字母、数字、-,并且必须以数字或字母作为开头及结尾。

例如:

合法的 Port 名称:123-abcweb

非法的 Port 名称:123_abc-web

使用自定义的 IP 地址

创建 Service 时,如果指定 .spec.clusterIP 字段,可以使用自定义的 Cluster IP 地址。该 IP 地址必须是 APIServer 中配置字段 service-cluster-ip-range CIDR 范围内的合法 IPv4 或 IPv6 地址,否则不能创建成功。

可能用到自定义 IP 地址的场景:

  • 想要重用某个已经存在的 DNS 条目
  • 遗留系统是通过 IP 地址寻址,且很难改造

服务发现

Kubernetes 支持两种主要的服务发现模式:

  • 环境变量
  • DNS

环境变量

kubelet 查找有效的 Service,并针对每一个 Service,向其所在节点上的 Pod 注入一组环境变量。支持的环境变量有:

  • Docker links 兼容的环境变量
  • {SVCNAME}_SERVICE_HOST 和 {SVCNAME}_SERVICE_PORT
    • Service name 被转换为大写
    • 小数点 . 被转换为下划线 _

例如,Service redis-master 暴露 TCP 端口 6379,其 Cluster IP 为 10.0.0.11,对应的环境变量如下所示:

REDIS_MASTER_SERVICE_HOST=10.0.0.11
REDIS_MASTER_SERVICE_PORT=6379
REDIS_MASTER_PORT=tcp://10.0.0.11:6379
REDIS_MASTER_PORT_6379_TCP=tcp://10.0.0.11:6379
REDIS_MASTER_PORT_6379_TCP_PROTO=tcp
REDIS_MASTER_PORT_6379_TCP_PORT=6379
REDIS_MASTER_PORT_6379_TCP_ADDR=10.0.0.11

如果要在 Pod 中使用基于环境变量的服务发现方式,必须先创建 Service,再创建调用 Service 的 Pod。否则,Pod 中不会有该 Service 对应的环境变量。

如果使用基于 DNS 的服务发现,您无需担心这个创建顺序的问题

DNS

oreDNS 监听 Kubernetes API 上创建和删除 Service 的事件,并为每一个 Service 创建一条 DNS 记录。集群中所有的 Pod 都可以使用 DNS Name 解析到 Service 的 IP 地址。

例如,名称空间 my-ns 中的 Service my-service,将对应一条 DNS 记录 my-service.my-ns。 名称空间 my-ns 中的Pod可以直接 nslookup my-servicemy-service.my-ns 也可以)。其他名称空间的 Pod 必须使用 my-service.my-nsmy-servicemy-service.my-ns 都将被解析到 Service 的 Cluster IP。

Kubernetes 同样支持 DNS SRV(Service)记录,用于查找一个命名的端口。假设 my-service.my-ns Service 有一个 TCP 端口名为 http,则,您可以 nslookup _http._tcp.my-service.my-ns 以发现该Service 的 IP 地址及端口 http

对于 ExternalName 类型的 Service,只能通过 DNS 的方式进行服务发现

Headless Services

“Headless” Service 不提供负载均衡的特性,也没有自己的 IP 地址。创建 “headless” Service 时,只需要指定 .spec.clusterIP 为 “None”。

“Headless” Service 可以用于对接其他形式的服务发现机制,而无需与 Kubernetes 的实现绑定。

对于 “Headless” Service 而言:

  • 没有 Cluster IP
  • kube-proxy 不处理这类 Service
  • Kubernetes不提供负载均衡或代理支持

DNS 的配置方式取决于该 Service 是否配置了 selector:

  • 配置了 Selector

    Endpoints Controller 创建 Endpoints 记录,并修改 DNS 配置,使其直接返回指向 selector 选取的 Pod 的 IP 地址

  • 没有配置 Selector

    Endpoints Controller 不创建 Endpoints 记录。DNS服务返回如下结果中的一种:

    • 对 ExternalName 类型的 Service,返回 CNAME 记录
    • 对于其他类型的 Service,返回与 Service 同名的 Endpoints 的 A 记录

虚拟 IP 的实现

避免冲突

Kubernetes 的一个设计哲学是:尽量避免非人为错误产生的可能性。就设计 Service 而言,Kubernetes 应该将您选择的端口号与其他人选择的端口号隔离开。为此,Kubernetes 为每一个 Service 分配一个该 Service 专属的 IP 地址。

为了确保每个 Service 都有一个唯一的 IP 地址,kubernetes 在创建 Service 之前,先更新 etcd 中的一个全局分配表,如果更新失败(例如 IP 地址已被其他 Service 占用),则 Service 不能成功创建。

Kubernetes 使用一个后台控制器检查该全局分配表中的 IP 地址的分配是否仍然有效,并且自动清理不再被 Service 使用的 IP 地址。

Service 的 IP 地址

Pod 的 IP 地址路由到一个确定的目标,然而 Service 的 IP 地址则不同,通常背后并不对应一个唯一的目标。 kube-proxy 使用 iptables (Linux 中的报文处理逻辑)来定义虚拟 IP 地址。当客户端连接到该虚拟 IP 地址时,它们的网络请求将自动发送到一个合适的 Endpoint。Service 对应的环境变量和 DNS 实际上反应的是 Service 的虚拟 IP 地址(和端口)。

Userspace

以上面提到的图像处理程序为例。当后端 Service 被创建时,Kubernetes master 为其分配一个虚拟 IP 地址(假设是 10.0.0.1),并假设 Service 的端口是 1234。集群中所有的 kube-proxy 都实时监听者 Service 的创建和删除。Service 创建后,kube-proxy 将打开一个新的随机端口,并设定 iptables 的转发规则(以便将该 Service 虚拟 IP 的网络请求全都转发到这个新的随机端口上),并且 kube-proxy 将开始接受该端口上的连接。

当一个客户端连接到该 Service 的虚拟 IP 地址时,iptables 的规则被触发,并且将网络报文重定向到 kube-proxy 自己的随机端口上。kube-proxy 接收到请求后,选择一个后端 Pod,再将请求以代理的形式转发到该后端 Pod。

这意味着 Service 可以选择任意端口号,而无需担心端口冲突。客户端可以直接连接到一个 IP:port,无需关心最终在使用哪个 Pod 提供服务。

iptables

仍然以上面提到的图像处理程序为例。当后端 Service 被创建时,Kubernetes master 为其分配一个虚拟 IP 地址(假设是 10.0.0.1),并假设 Service 的端口是 1234。集群中所有的 kube-proxy 都实时监听者 Service 的创建和删除。Service 创建后,kube-proxy 设定了一系列的 iptables 规则(这些规则可将虚拟 IP 地址映射到 per-Service 的规则)。per-Service 规则进一步链接到 per-Endpoint 规则,并最终将网络请求重定向(使用 destination-NAT)到后端 Pod。

当一个客户端连接到该 Service 的虚拟 IP 地址时,iptables 的规则被触发。一个后端 Pod 将被选中(基于 session affinity 或者随机选择),且网络报文被重定向到该后端 Pod。与 userspace proxy 不同,网络报文不再被复制到 userspace,kube-proxy 也无需处理这些报文,且报文被直接转发到后端 Pod。

在使用 node-port 或 load-balancer 类型的 Service 时,以上的代理处理过程是相同的。

IPVS

在一个大型集群中(例如,存在 10000 个 Service)iptables 的操作将显著变慢。IPVS 的设计是基于 in-kernel hash table 执行负载均衡。因此,使用 IPVS 的 kube-proxy 在 Service 数量较多的情况下仍然能够保持好的性能。同时,基于 IPVS 的 kube-proxy 可以使用更复杂的负载均衡算法(最少连接数、基于地址的、基于权重的等)

支持的传输协议

TCP

默认值。任何类型的 Service 都支持 TCP 协议。

UDP

大多数 Service 都支持 UDP 协议。对于 LoadBalancer 类型的 Service,是否支持 UDP 取决于云供应商是否支持该特性。

HTTP

如果您的云服务商支持,您可以使用 LoadBalancer 类型的 Service 设定一个 Kubernetes 外部的 HTTP/HTTPS 反向代理,将请求转发到 Service 的 Endpoints。

使用 Ingress

Proxy Protocol

如果您的云服务上支持(例如 AWS),您可以使用 LoadBalancer 类型的 Service 设定一个 Kubernetes 外部的负载均衡器,并将连接已 PROXY 协议转发到 Service 的 Endpoints。

负载均衡器将先发送描述该 incoming 连接的字节串,如下所示:

PROXY TCP4 192.0.2.202 10.0.42.7 12345 7\r\n

然后在发送来自于客户端的数据

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/762160.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

创建users子应用

1.创建:(venv) xxxx>python manage.py startapp users 2.移动到apps里面; 3.在settings里面注册子应用; # 注册子应用 apps/users apps/users/apps name apps.users 这个路径是什么就写什么 INSTALLED_APPS [ # 用[../namage.py st…

架构训练营学习笔记:4-3存储架构模式之分片架构和分区架构

分片架构的本质: 分片架构能提升写性能和存储性能,对应的主备架构的本质是备份,主从架构本质提升读性能。 分片架构的两个关键点:分片规则跟路由规则 分片规则: 选择基数比较大的某个数据键值,让数据均匀…

第七章 集成学习

文章目录 第七章 集成学习7.1个体和集成7.2Boosting和AdaBoost7.3Bagging和随机森林7.3.1Bagging7.3.2随机森林 7.4结合策略7.4.1平均法7.4.2投票法7.4.3学习法 7.6实验:Adaboost 第七章 集成学习 7.1个体和集成 集成学习通过构建并结合多个学习器来完成学习任务&…

TS报错Cannot find module ‘xxx‘ or its corresponding type declarations

最近使用 vite vue3 ts 开发一个文本标注的 web 平台,在项目中使用了一个 js-mark 的 npm 包,但是在 import 导入后出现了 TS 报错:TS2307: Cannot find module js-mark or its corresponding type declarations.、无法解析模块 js-mark 的…

Safe Policy Optimization 复现

复现结果 在 PointGoal1、CarGoal1、Velocity-Walker2d 三个任务上测试了 RCPO,CRPO 以及 Safe-Policy-Optimization 中实现的 CPO,PPO-Lag 算法。 CarGoal PointGoal PointGoal1 和 CarGoal1 任务相对比较困难,在探索初期就很容易违反约束…

Dart语言(01)环境安装基础语法总结

0 说明: 说明:该系列教程主要是为有一定语言基础 C/C的程序员,快速学习一门新语言所采用的方法,属于在C/C基础上扩展新语言只是体系的方式。 1 Dart语言简介 Dart亮相于2011年10月10日至12日在丹麦奥尔胡斯举行的GOTO大会&…

【动手学深度学习】--09.PyTorch神经网络基础

文章目录 PyTorch神经网络基础1.层和块1.1自定义块1.2顺序块1.3在前向传播函数中执行代码 2.参数管理2.1参数访问2.1.1目标参数2.1.2一次性访问所有参数2.1.3从嵌套块收集参数 2.2参数初始化2.2.1内置初始化2.2.2自定义初始化 2.3参数绑定 3.自定义层3.1不带参数的层3.2带参数的…

Python爬虫学习笔记:1688商品详情API 开发API接口文档

1688API接口是阿里巴巴集团推出的一种开放平台,提供了丰富的数据接口、转换工具以及开发资源,为开发者提供了通用的应用接口及大量数据资源,支持开发者在1688上进行商品搜索、订单管理、交易报表及物流等方面的操作。 1688API接口主要包含以…

解密成功之道!加湿制冷设备企业如何借助CRM系统降低经营成本?

如何降低企业经营成本的同时提高效率是加湿制冷设备企业关注的重要问题。在这篇软文中,我们将探讨如何通过CRM系统来实现这一目标。企业可以借助CRM系统提高客户关系管理水平,优化销售流程,提升售后服务,从而降低成本,…

价格监测的作用有哪些

随着品牌的发展,销售渠道也会逐步增多,渠道中的问题也会逐渐显现,比如低价、乱价、窜货、假货,所以品牌一般都会进行控价治理,控价最重要的一步便是价格监测,监测出来的价格高低,能直接反应渠道…

抑郁症缓解方法:从心理到行为,全方位提升生活质量

抑郁症是一种常见的心理疾病,不仅仅是心情低落,它还伴随着一系列的身体和心理症状。在应对抑郁症时,除了积极寻求医学专业人士的帮助之外,以下这些招数也可以帮助你缓解抑郁症。 1.保持规律的生活习惯:抑郁症患者往往会…

小程序地图个性化样式组件要收费了!

地图个性化样式组件 自2023年6月29日0点起,该能力需要先购买再使用。若未购买,届时将无法使用该能力。具体购买方式见付费管理。自2023年6月29日0时起,个性化地图配置界面的入口统一为微信公众平台-付费管理,请从此入口进入&#…

STUN/TURN/ICE

RFC 5389 - Session Traversal Utilities for NAT (STUN) https://www.cnblogs.com/pannengzhi/p/5041546.html https://www.cnblogs.com/pannengzhi/p/5048965.html STUN : Session Traversal Utilities for NAT, 一个协助穿越NAT的工具,运行在UDP和TCP之上。 NA…

yolov5(v7.0)网络修改实践一:集成YOLOX的backbone(CSPDarknet和Pafpn)到yolov5(v7.0)框架中

yolov5太好用了,无论是实际做工程还是学习研究,yolov5都比较好上手,而且现在工业界yolov5也应用广泛。但是,作为学习研究,有不少在yolov5之后提出的涨点算法,还是有价值进行研究的,也便于跟进当…

高效管理物流:利用批量查询申通物流信息的技巧

随着电子商务的飞速发展,快递已经成为了现代人生活中不可或缺的一部分。作为国内一家领先的快递公司,申通快递服务广泛,覆盖全国各地。在使用申通快递服务时,我们通过申通快递单号可以方便地查询物流信息。然而,许多人…

python开发项目基于语音识别的智能垃圾分类系统的设计与实现

博主介绍:擅长Java、微信小程序、Python、Android等,专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇🏻 不然下次找不到哟 Java项目精品实战案例…

Ae 效果:CC Mr. Smoothie

风格化/CC Mr. Smoothie Stylize/CC Mr. Smoothie CC Mr. Smoothie(平滑先生)效果可以从一个图层上的两个点进行颜色采样,并将这个两点之间的颜色重映射到另一个图层上,可通过控制重映射的平滑度从而创建迷幻的外观效果。 ◆ ◆ …

图像处理之高斯滤波

文章目录 高斯函数1.一维高斯函数2. 二维高斯函数 高斯滤波1.高斯核生成2.滤波过程 高斯函数 高斯函数广泛应用于统计学领域,用于表述正态分布,在信号处理领域,用于定义高斯滤波器,在图像处理领域,二维高斯核函数常用…

创建一个类Person的简单实例

创建一个类Person的简单实例 创建一个类Person,包含以下属性:姓名(name)、年龄(age)、朋友(friends数组)、问候(sayhi方法,输出问候语,例如&#…

将TXT转化为PDF的软件,分享两个简单的方法!

在数字化时代,文档的传递和共享已经成为我们日常工作中的一部分。然而,有时我们可能需要将文本文件(如TXT格式)转换为PDF格式,以便更方便地共享、打印或存档。PDF格式的文件具有普遍的兼容性,可以在不同的设…