k8s 中的 service 如何找到绑定的 Pod 及实现 Pod 负载均衡的方法

目录
  • k8s 中的 service 如何找到绑定的 Pod 以及如何实现 Pod 负载均衡
    • 前言
    • endpoint
    • kube-proxy
    • userspace 模式
    • iptables
    • ipvs
    • kernelspace
    • 服务发现
    • 环境变量
    • DNS
    • 总结
    • 参考

k8s 中的 service 如何找到绑定的 Pod 以及如何实现 Pod 负载均衡

前言

Service 资源主要用于为 Pod 对象提供一个固定、统一的访问接口及负载均衡的能力。

service 是一组具有相同 label pod 集合的抽象,集群内外的各个服务可以通过 service 进行互相通信。

当创建一个 service 对象时也会对应创建一个 endpoint 对象,endpoint 是用来做容器发现的,service 只是将多个 pod 进行关联,实际的路由转发都是由 kubernetes 中的 kube-proxy 组件来实现,因此,service 必须结合 kube-proxy 使用,kube-proxy 组件可以运行在 kubernetes 集群中的每一个节点上也可以只运行在单独的几个节点上,其会根据 service 和 endpoints 的变动来改变节点上 iptables 或者 ipvs 中保存的路由规则。

endpoint

endpoint 是 k8s 集群中的一个资源对象,存储在 etcd 中,用来记录一个 service 对应的所有 pod 的访问地址。

service 通过 selector 和 pod 建立关联。k8s 会根据 service 关联到 pod 的 podIP 信息组合成一个 endpoint。

如果 service 没有 selector 字段,当一个 service 被创建的时候,endpoint controller 不会自动创建 endpoint。

$ kubectl get svc -n study-k8s
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
go-web-svc   ClusterIP   10.233.55.112   <none>        8000/TCP   9d

$ kubectl get endpoints -n study-k8s
NAME         ENDPOINTS                                                                AGE
go-web-svc   10.233.111.171:8000,10.233.111.172:8000,10.233.72.153:8000 + 2 more...   9d

栗如

上面的 service go-web-svc,就有一个对应的 endpoint,ENDPOINTS 里面展示的就是 service 关联的 pod 的 ip 地址和端口。

其中 endpoint controller 负载维护 endpoint 对象,主要的功能有下面几种

1、负责生成和维护所有endpoint对象的控制器;

2、负责监听 service 和对应 pod 的变化;

3、监听到 service 被删除,则删除和该 service 同名的 endpoint 对象;

4、监听到新的 service 被创建,则根据新建 service 信息获取相关 pod 列表,然后创建对应 endpoint 对象;

5、监听到 service 被更新,则根据更新后的 service 信息获取相关 pod 列表,然后更新对应 endpoint 对象;

6、监听到 pod 事件,则更新对应的 service 的 endpoint 对象,将 podIp 记录到 endpoint中;

kube-proxy

kube-proxy 是 Kubernetes 的核心组件,部署在每个 Node 节点上,它是实现 Kubernetes Service 的通信与负载均衡机制的重要组件; kube-proxy 负责为 Pod 创建代理服务,从 apiserver 获取所有 server 信息,并根据 server 信息创建代理服务,实现server到Pod的请求路由和转发,从而实现K8s层级的虚拟转发网络。

在 k8s 中提供相同服务的一组 pod 可以抽象成一个 service,通过 service 提供统一的服务对外提供服务,kube-proxy 存在于各个 node 节点上,负责为 service 提供 cluster 内部的服务发现和负载均衡,负责 Pod 的网络代理,它会定时从 etcd 中获取 service 信息来做相应的策略,维护网络规则和四层负载均衡工作。k8s 中集群内部的负载均衡就是由 kube-proxy 实现的,它是 k8s 中内部的负载均衡器,也是一个分布式代理服务器,可以在每个节点中部署一个,部署的节点越多,提供负载均衡能力的 Kube-proxy 就越多,高可用节点就越多。

简单点讲就是 k8s 内部的 pod 要访问 service ,kube-proxy 会将请求转发到 service 所代表的一个具体 pod,也就是 service 关联的 Pod。

同理对于外部访问 service 的请求,不论是 Cluster IP+TargetPort 的方式;还是用 Node 节点 IP+NodePort 的方式,都被 Node 节点的 Iptables 规则重定向到 Kube-proxy 监听 Service 服务代理端口。kube-proxy 接收到 Service 的访问请求后,根据负载策略,转发到后端的 Pod。

kube-proxy 的路由转发规则是通过其后端的代理模块实现的,其中 kube-proxy 的代理模块目前有四种实现方案,userspace、iptables、ipvs、kernelspace 。

userspace 模式

userspace 模式在 k8s v1.2 后就已经被淘汰了,userspace 的作用就是在 proxy 的用户空间监听一个端口,所有的 svc 都转到这个端口,然后 proxy 内部应用层对其进行转发。proxy 会为每一个 svc 随机监听一个端口,并增加一个 iptables 规则。

从客户端到 ClusterIP:Port 的报文都会通过 iptables 规则被重定向到 Proxy Port,Kube-Proxy 收到报文后,然后分发给对应的 Pod。

userspace 模式下,流量的转发主要是在用户空间下完成的,上面提到了客户端的请求需要借助于 iptables 规则找到对应的 Proxy Port,因为 iptables 是在内核空间,这里就会请求就会有一次从用户态到内核态再返回到用户态的传递过程, 一定程度降低了服务性能。所以就会认为这种方式会有一定的性能损耗。

默认情况下,用户空间模式下的 kube-proxy 通过轮转算法选择后端。

iptables

首先来简单了解下 iptables:

iptables 是 Linux 中最常用的一种防火墙工具,除了防火墙它还可以用作 IP 转发和简单的负载均衡功能。基于 Linux 中的 netfilter 内核模块实现。 Netfilter 在协议中添加了一些钩子,它允许内核模块通过这些钩子注册回调函数,这样经过钩子的所有数据都会被注册在响应钩子上的函数处理,包括修改数据包内容、给数据包打标记或者丢掉数据包等。iptables 是运行在用户态的一个程序,通过 netlink 和内核的 netfilter 框架打交道,具有足够的灵活性来处理各种常见的数据包操作和过滤需求。它允许将灵活的规则序列附加到内核的数据包处理管道中的各种钩子上。

Netfilter 是 Linux 2.4.x 引入的一个子系统,它作为一个通用的、抽象的框架,提供一整套的 hook 函数的管理机制,使得诸如数据包过滤、网络地址转换(NAT)和基于协议类型的连接跟踪成为了可能。

在 kubernetes v1.2 之后 iptables 成为默认代理模式,这种模式下,kube-proxy 会监视 Kubernetes master 对 Service 对象和 Endpoints 对象的添加和移除。 对每个 Service,它会安装 iptables 规则,从而捕获到达该 Service 的 clusterIP(虚拟 IP)和端口的请求,进而将请求重定向到 Service 的一组 backend 中的某个上面。因为流量转发都是在内核进行的,所以性能更高更加可靠。

可以看到该模式下 iptables 来做用户态的入口,kube-proxy 只是持续监听 Service 以及 Endpoints 对象的变化, iptables 通过设置的转发策略,直接将对 VIP 的请求转发给后端 Pod,iptables 使用 DNAT 来完成转发,其采用了随机数实现负载均衡。

如果 kube-proxy 在 iptables 模式下运行,并且所选的第一个 Pod 没有响应,则连接失败。 这与用户空间模式不同:在这种情况下,kube-proxy 将检测到与第一个 Pod 的连接已失败, 并会自动使用其他后端 Pod 重试。

该模式相比 userspace 模式,克服了请求在用户态-内核态反复传递的问题,性能上有所提升,但使用 iptables NAT 来完成转发,存在不可忽视的性能损耗,iptables 模式最主要的问题是在 service 数量大的时候会产生太多的 iptables 规则,使用非增量式更新会引入一定的时延,大规模情况下有明显的性能问题。

ipvs

当集群的规模比较大时,iptables 规则刷新就会很慢,难以支撑大规模的集群。因为 iptables 的底层实现是链表,对路由规则的增删查改都需要遍历一次链表。

在 kubernetes v1.2 之后 ipvs 成为kube-proxy的默认代理模式。ipvs 正是解决这一问题的,ipvs 是 LVS 的负载均衡模块,与 iptables 比较像的是,ipvs 的实现虽然也基于 netfilter 的钩子函数,但是它却使用哈希表作为底层的数据结构并且工作在内核态,也就是说 ipvs 在重定向流量和同步代理规则有着更好的性能,几乎允许无限的规模扩张。

ipvs 支持三种负载均衡模式:

1、DR模式(Direct Routing);

2、NAT 模式(Network Address Translation);

3、Tunneling(也称 ipip 模式)。

三种模式中只有 NAT 支持端口映射,所以 ipvs 使用 NAT 模式。linux 内核原生的 ipvs 只支持 DNAT,当在数据包过滤,SNAT 和支持 NodePort 类型的服务这几个场景中ipvs 还是会使用 iptables。

ipvs 也支持更多的负载均衡算法:

  • rr:round-robin/轮询;
  • lc:least connection/最少连接;
  • dh:destination hashing/目标哈希;
  • sh:source hashing/源哈希;
  • sed:shortest expected delay/预计延迟时间最短;
  • nq:never queue/从不排队

kernelspace

kernelspace 模式是 windows 上的代理模式,这里不展开讨论了

服务发现

service 的 endpoints 解决了容器发现问题,但是不提前知道 service 的 Cluster IP,就无法知道 service 服务了。Kubernetes 支持两种基本的服务发现模式 —— 环境变量和 DNS。

环境变量

当一个 pod 创建完成之后,kubelet 会在该 pod 中注册该集群已经创建的所有 service 相关的环境变量,但是需要注意的是,在 service 创建之前的所有 pod 是不会注册该环境变量的,所以在平时使用时,建议通过 DNS 的方式进行 service 之间的服务发现。

举个例子,一个名称为 redis-primary 的 Service 暴露了 TCP 端口 6379, 同时给它分配了 Cluster IP 地址 10.0.0.11,这个 Service 生成了如下环境变量:

REDIS_PRIMARY_SERVICE_HOST=10.0.0.11
REDIS_PRIMARY_SERVICE_PORT=6379
REDIS_PRIMARY_PORT=tcp://10.0.0.11:6379
REDIS_PRIMARY_PORT_6379_TCP=tcp://10.0.0.11:6379
REDIS_PRIMARY_PORT_6379_TCP_PROTO=tcp
REDIS_PRIMARY_PORT_6379_TCP_PORT=6379
REDIS_PRIMARY_PORT_6379_TCP_ADDR=10.0.0.11

DNS

可以在集群中部署 CoreDNS 服务(旧版本的 kubernetes 群使用的是 kubeDNS), 来达到集群内部的 pod 通过DNS 的方式进行集群内部各个服务之间的通讯。

当前 kubernetes 集群默认使用 CoreDNS 作为默认的 DNS 服务,主要原因是 CoreDNS 是基于 Plugin 的方式进行扩展的,简单,灵活,并且不完全被Kubernetes所捆绑。

同时 k8s 中也建议使用 DNS 来做服务发现。

Kubernetes DNS 服务器是唯一的一种能够访问 ExternalName 类型的 Service 的方式。

总结

k8s 中一般使用 Service 为 Pod 对象提供一个固定、统一的访问接口及负载均衡的能力;

k8s 中的负载均衡主要借助于 endpoint 和 kube-proxy 来实现;

endpoint 是 k8s 集群中的一个资源对象,存储在 etcd 中,用来记录一个 service 对应的所有 pod 的访问地址,当一个 service 关联的 pod 被删除,更新,新增,对应的 endpoint 资源都会更新;

kube-proxy 是 Kubernetes 的核心组件,部署在每个 Node 节点上,它是实现 Kubernetes Service 的通信与负载均衡机制的重要组件; kube-proxy 负责为 Pod 创建代理服务,从 apiserver 获取所有 server 信息,并根据 server 信息创建代理服务,实现server到Pod的请求路由和转发,从而实现K8s层级的虚拟转发网络;

kube-proxy 的路由转发规则是通过其后端的代理模块实现的,其中 kube-proxy 的代理模块目前有四种实现方案,userspace、iptables、ipvs、kernelspace ;

service 的 endpoints 和 kube-proxy 解决了容器的发现和负载均衡的问题,但是 service 服务如何被内部的服务找到呢,Kubernetes 支持两种基本的服务发现模式 —— 环境变量和 DNS;

其中 k8s 中推荐使用 DNS 来做 service 的服务发现,当前 kubernetes 集群默认使用 CoreDNS 作为默认的 DNS 服务,主要原因是 CoreDNS 是基于 Plugin 的方式进行扩展的,简单,灵活,并且不完全被Kubernetes所捆绑。

参考

【kubernetes service 原理解析】https://zhuanlan.zhihu.com/p/111244353

【service selector】https://blog.csdn.net/luanpeng825485697/article/details/84296765

【一文看懂 Kube-proxy】https://zhuanlan.zhihu.com/p/337806843

【Kubernetes 【网络组件】kube-proxy使用详解】https://blog.csdn.net/xixihahalelehehe/article/details/115370095

【Service】https://jimmysong.io/kubernetes-handbook/concepts/service.html

【Service】https://kubernetes.io/zh-cn/docs/concepts/services-networking/service/

【k8s 中的 service 如何找到绑定的 Pod 以及如何实现 Pod 负载均衡】https://boilingfrog.github.io/2022/10/16/k8s中的service如何找到绑定的Pod以及如何实现Pod负载均衡/

到此这篇关于k8s 中的 service 如何找到绑定的 Pod 以及如何实现 Pod 负载均衡的文章就介绍到这了,更多相关k8s 中的 service 实现 Pod 负载均衡内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 静态pod 创建使用示例详解

    目录 一.系统环境 二.前言 三.静态pod 3.1 何为静态pod 3.2 创建静态pod 3.2.1 使用--pod-manifest-path指定静态pod目录 3.2.2 静态pod默认目录/etc/kubernetes/manifests 一.系统环境 服务器版本 docker软件版本 Kubernetes(k8s)集群版本 CPU架构 CentOS Linux release 7.4.1708 (Core) Docker version 20.10.12 v1.21.9 x86_64

  • 替代pod update速度慢的lg_pod_plugin安装使用详解

    目录 1. 安装方式 2. 如何使用lg_pod_plugin 3. 工作原理 1. 安装方式 推荐使用bundle 安装lg_pod_plugin , 免去手动安装 gem install lg_pod_plugin , 方便后续升级lg_pod_plugin版本, 适合团队开发, 总不能让所有人在自己电脑上都安装一次 lg_pod_plugin吧. 创建 Gemfile 文件 bundle init #初始化一个bundle 环境, 类似于pod init 编写Gemfile 文件, 类似于

  • pod污点taint 与容忍度tolerations详解

    目录 一.系统环境 二.前言 三.污点taint 3.1 污点taint概览 3.2 给节点添加污点taint 四.容忍度tolerations 4.1 容忍度tolerations概览 4.2 设置容忍度tolerations 一.系统环境 服务器版本 docker软件版本 Kubernetes(k8s)集群版本 CPU架构 CentOS Linux release 7.4.1708 (Core) Docker version 20.10.12 v1.21.9 x86_64 Kubernete

  • pod调度将 Pod 指派给节点

    目录 一.系统环境 二.前言 三.pod的调度 3.1 pod的调度概述 3.2 pod自动调度 3.2.1 创建3个主机端口为80的pod 3.3 使用nodeName 字段指定pod运行在哪个节点 3.4 使用节点标签nodeSelector指定pod运行在哪个节点 3.4.1 查看标签 3.4.2 创建标签 3.4.3 通过标签控制pod在哪个节点运行 3.5 使用亲和性与反亲和性调度pod 3.5.1 使用硬策略requiredDuringSchedulingIgnoredDuringE

  • cordon节点drain驱逐节点delete节点详解

    目录 一.系统环境 二.前言 三.cordon节点 3.1 cordon节点概览 3.2 cordon节点 3.3 uncordon节点 四.drain节点 4.1 drain节点概览 4.2 drain 节点 4.3 uncordon节点 五.delete 节点 5.1 delete节点概览 5.2 delete节点 一.系统环境 服务器版本 docker软件版本 Kubernetes(k8s)集群版本 CPU架构 CentOS Linux release 7.4.1708 (Core) Do

  • 详解kubelet 创建pod流程代码图解及日志说明

    目录 正文 kubernetes调度pod简介 kubelet 创建pod代码及图解说明 kubelet 简介 kubelet创建及启动pod流程 kubelet 创建pod代码调用图解 kubelet 创建pod详细说明 kubelet 调用cri说明 kubelet创建pod整体架构图 kubelet创建pod日志说明 正文 本文将从如下方面介绍kubelet创建pod的过程 kubernetes调度pod简介 kubelet 创建pod代码图解说明 (本文重点) kubelet 调用cri

  • k8s 中的 service 如何找到绑定的 Pod 及实现 Pod 负载均衡的方法

    目录 k8s 中的 service 如何找到绑定的 Pod 以及如何实现 Pod 负载均衡 前言 endpoint kube-proxy userspace 模式 iptables ipvs kernelspace 服务发现 环境变量 DNS 总结 参考 k8s 中的 service 如何找到绑定的 Pod 以及如何实现 Pod 负载均衡 前言 Service 资源主要用于为 Pod 对象提供一个固定.统一的访问接口及负载均衡的能力. service 是一组具有相同 label pod 集合的抽

  • grpc-java k8s下的负载均衡处理方法

    目录 前言 现状 负载均衡的方案 一.客户端dns模式 二.客户端注册中心模式 三.代理端走ingress 四.代理端servicemesh 结语 前言 grpc 因为是长连接的,所以负载均衡处理起来没有 rest 接口那么容易.常见的 grpc 负载均衡方法分为两类,一类是客户端侧实现负载逻辑,一类是代理侧实现负载逻辑,对客户端侧是透明的.在容器化的网络环境里, grpc-java 客户端侧的负载均衡有两种常见的实现路径. 1.基于 dns 实现, 2.基于外部的服务注册中心实现(ZooKee

  • 在Nginx服务器中配置针对TCP的负载均衡的方法

    默认nginx不支持tcp的负载均衡,需要打补丁,(连接方式:从客户端收到一个连接,将从本地新建一个连接发起到后端服务器),具体配置如下: 一.安装Nginx 1.下载nginx # wget http://nginx.org/download/nginx-1.2.4.tar.gz 2.下载tcp模块补丁 # wget https://github.com/yaoweibin/nginx_tcp_proxy_module/tarball/master 源码主页: https://github.c

  • Spring Cloud Ribbon 中的 7 种负载均衡策略的实现方法

    目录 Ribbon介绍 负载均衡设置 7种负载均衡策略 1.轮询策略 2.权重策略 3.随机策略 4.最小连接数策略 5.重试策略 6.可用性敏感策略 7.区域敏感策略 项目源码 总结 负载均衡通器常有两种实现手段,一种是服务端负载均衡器,另一种是客户端负载均衡器,而我们今天的主角 Ribbon 就属于后者——客户端负载均衡器. 服务端负载均衡器的问题是,它提供了更强的流量控制权,但无法满足不同的消费者希望使用不同负载均衡策略的需求,而使用不同负载均衡策略的场景确实是存在的,所以客户端负载均衡就

  • Asp.net Core MVC中怎么把二级域名绑定到特定的控制器上

    应用场景:企业门户网站会根据内容不同,设置不同的板块,如新浪有体育,娱乐频道,等等.有的情况下需要给不同的板块设置不同的二级域名,如新浪体育sports.sina.com.cn. 在asp.net core mvc中,如果要实现板块的效果,可能会给不同的板块建立不同的控制器(当然也有其他的技术,这里不讨论实现方式的好坏),在这种情况下,如何给控制器绑定上独有的二级域名,比如体育频道对应的控制器叫SportController,通过sports.XXX.com域名访问系统的时候,直接进入Sport

  • JavaScript函数中的this四种绑定形式

    正文 javascript中的this和函数息息相关,所以今天,我就给大家详细地讲述一番:javascript函数中的this 一谈到this,很多让人晕晕乎乎的抽象概念就跑出来了,这里我就只说最核心的一点--函数中的this总指向调用它的对象,接下来的故事都将围绕这一点展开 (提醒前排的筒子们准备好茶水和西瓜,我要开始讲故事啦!!) [故事]有一个年轻人叫"迪斯"(this),有一天,迪斯不小心穿越到一个叫 "伽瓦斯克利"(javascript)的 异世界,此时此

  • Android中的Service相关全面总结

    1.Service的种类 按运行地点分类: 类别 区别  优点 缺点   应用 本地服务(Local) 该服务依附在主进程上,  服务依附在主进程上而不是独立的进程,这样在一定程度上节约了资源,另外Local服务因为是在同一进程因此不需要IPC,也不需要AIDL.相应bindService会方便很多.  主进程被Kill后,服务便会终止.  非常常见的应用如:HTC的音乐播放服务,天天动听音乐播放服务. 远程服务(Remote) 该服务是独立的进程,  服务为独立的进程,对应进程名格式为所在包名

  • 详解Android中的Service

    Service简介: Service是被设计用来在后台执行一些需要长时间运行的操作. Android由于允许Service在后台运行,甚至在结束Activity后,因此相对来说,Service相比Activity拥有更高的优先级. 创建Service: 要创建一个最基本的Service,需要完成以下工作:1)创建一个Java类,并让其继承Service 2)重写onCreate()和onBind()方法 其中,onCreate()方法是当该Service被创建时执行的方法,onBind()是该S

  • .NET 中Worker Service的使用入门

    译者注: 请先完成以下准备工作,以便于您理解本文. 1.下载并安装最新的 .NET SDK:https://dotnet.microsoft.com/download 2.命令行运行 dotnet new Worker -n "MyService" 命令,创建一个 Worker Service 项目. 什么是 .NET Core Worker Service? Worker Service 是使用模板构建的 .NET 项目,该模板提供了一些有用的功能,可以将常规控制台应用程序变得更加强

  • K8S中五种控制器的介绍以及使用

    目录 k8s的控制器类型 pod与控制器之间的关系 Deployment(无状态化应用) 状态与无状态化对特点 Deployment的更新 Deployment的回滚 CronJob控制器 总结 k8s的控制器类型 Kubernetes中内建了很多controller(控制器),这些相当于一个状态机,用来控制Pod的具体状态和行为 Deployment:适合无状态的服务部署 StatefullSet:适合有状态的服务部署 DaemonSet:一次部署,所有的node节点都会部署,例如一些典型的应

随机推荐