kube-proxy源码阅读

这篇具有很好参考价值的文章主要介绍了kube-proxy源码阅读。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

kube-proxy源码阅读

通过阅读kube-proxy的源码可以将proxy的主要逻辑总结为下图所示:
kube-proxy源码阅读首先顺着代码阅读到ProxyServer->Run()函数,这里是kube-proxy启动的主逻辑,启动了两个server,分别是:

...
	var errCh chan error
	if s.BindAddressHardFail {
		errCh = make(chan error)
	}

	// Start up a healthz server if requested
	serveHealthz(s.HealthzServer, errCh)

	// Start up a metrics server if requested
	serveMetrics(s.MetricsBindAddress, s.ProxyMode, s.EnableProfiling, errCh)
...

每个服务都是通过定时任务保证服务存活:

func serveHealthz(hz healthcheck.ProxierHealthUpdater, errCh chan error) {
	if hz == nil {
		return
	}

	fn := func() {
		err := hz.Run()
		if err != nil {
			klog.ErrorS(err, "Healthz server failed")
			if errCh != nil {
				errCh <- fmt.Errorf("healthz server failed: %v", err)
				// if in hardfail mode, never retry again
				blockCh := make(chan error)
				<-blockCh
			}
		} else {
			klog.ErrorS(nil, "Healthz server returned without error")
		}
	}
	go wait.Until(fn, 5*time.Second, wait.NeverStop)
}

然后通过informer机制的list/watch感知services(被观察者)和endpoints(被观察者)的变化,通过观察者模式实现消息同步,从而触发观察者(Proxier)的syncProxyRules方法更新网络规则:

...
	serviceConfig := config.NewServiceConfig(informerFactory.Core().V1().Services(), s.ConfigSyncPeriod)
	serviceConfig.RegisterEventHandler(s.Proxier) // 观察者模式
	go serviceConfig.Run(wait.NeverStop)

	endpointSliceConfig := config.NewEndpointSliceConfig(informerFactory.Discovery().V1().EndpointSlices(), s.ConfigSyncPeriod)
	endpointSliceConfig.RegisterEventHandler(s.Proxier) // 观察者模式
	go endpointSliceConfig.Run(wait.NeverStop)
...

Proxier提供的方法列表,先大概从名称上来了解一下方法用途:

    func (proxier *Proxier) precomputeProbabilities(numberOfPrecomputed int) {/*...*/}
    func (proxier *Proxier) probability(n int) string{/*...*/}
    func (proxier *Proxier) Sync(){/*...*/}
    func (proxier *Proxier) SyncLoop(){/*...*/}
    func (proxier *Proxier) setInitialized(value bool){/*...*/}
    func (proxier *Proxier) isInitialized() bool{/*...*/}
    func (proxier *Proxier) OnServiceAdd(service *v1.Service){/*...*/}
    func (proxier *Proxier) OnServiceUpdate(oldService, service *v1.Service){/*...*/}
    func (proxier *Proxier) OnServiceDelete(service *v1.Service){/*...*/}
    func (proxier *Proxier) OnServiceSynced(){/*...*/}
    func (proxier *Proxier) OnEndpointsAdd(endpoints *v1.Endpoints){/*...*/}
    func (proxier *Proxier) OnEndpointsUpdate(oldEndpoints, endpoints *v1.Endpoints){/*...*/}
    func (proxier *Proxier) OnEndpointsDelete(endpoints *v1.Endpoints) {/*...*/}
    func (proxier *Proxier) OnEndpointsSynced() {/*...*/}
    func (proxier *Proxier) deleteEndpointConnections(connectionMap []proxy.ServiceEndpoint){/*...*/}
    func (proxier *Proxier) appendServiceCommentLocked(args []string, svcName string){/*...*/}
    func (proxier *Proxier) syncProxyRules(){/*...*/}

其中Proxier的实现方式有两种,分别是:iptables和 IPVS
IPVS:

IPVS 全名 IP Virtual Server
实现 L4 的 load balancing
主要在 cluster 前的实体主机上运行
直接请求 base on service 的 TCP / UDP 到真实的 server
使真实 server 的 service 显示为有一个 IP 的虚拟 service
实现为 Netfilter 框架上的 module
Based on kernel 中的 hash tables
Kernel source code: net/netfilter/ipvs
ipvsadm 是管理 IPVS 的工具

iptables:
kube-proxy源码阅读
大致了解 IPVS ,那 IPVS 和 iptables 有什么差別呢?
其实他们都是使用 Netfilter ,来让封包传送的机制,但作面却是不一样的。
在 INPUT chain 这边,不论是 IPVS 或是 iptables 都会到 userspace 来进行封包解析,来看看封包要往哪里走。然而,就是在判断封包要往哪里走,这里的方法两者使用的方式是不一样的。

iptables 规则设定是:n 张 table,每张 table 内有 m 个 chain ,每个 chain 中有 多个rule。
虽然封包不会跑过所有的 Table 和 chain,但 rules 通常会是很多的。虽然封包只要被拆解一次,但封包在比对每个 rule 时,都要再看要用进來的这个封包和目前轮到的 rule 进行行比对。
这也是为什么我们在下 rule 的时候很重视 rule 的顺序性。(所以 rule 也会因人的设定好不好,效能也会有差异)。

IPVS 在判断上面就简单很多,他是用 hash table(hash表),在时间复杂度上,通常是是 O(1),即便遇到最差的情況(worst case),也只是 O(n)。

在kube-proxy中这两种Proxier的实现的最大区别也主要是规则的更新,也就是syncProxyRules这个方法,下面梳理两种实现的主要逻辑:

iptables:

  • 更新proxier.endpointsMap,proxier.servieMap
  • 创建自定义链将当前内核中 filter 表和 nat 表中的全部规则导入到内存中
  • 为每个 service 创建规则
  • 为 clusterIP 设置访问规则
  • 为 externalIP 设置访问规则
  • 为 ingress 设置访问规则
  • 为 nodePort 设置访问规则
  • 为 endpoint 生成规则链
  • 写入 DNAT 规则
  • 删除不再使用的服务自定义链
  • 使用 iptables-restore 同步规则

IPVS:

  • 通过 iptables-save 获取现有的 Filter 和 NAT 表存在的链数据
  • 创建自定义链与规则
  • 创建 Dummy 接口和 ipset 默认列表
  • 为每个服务生成 ipvs 规则
  • 对 serviceMap 内的每个服务进行遍历处理,对不同的服务类型(clusterip/nodePort/externalIPs/load-balancer)进行不同的处理(ipset 列表/vip/ipvs 后端服务器)
  • 根据 endpoint 列表,更新 KUBE-LOOP-BACK 的 ipset 列表
  • 若为 clusterIP 类型更新对应的 ipset 列表 KUBE-CLUSTER-IP
  • 若为 externalIPs 类型更新对应的 ipset 列表 KUBE-EXTERNAL-IP
  • 若为 load-balancer 类型更新对应的 ipset 列表 KUBE-LOAD-BALANCER、KUBE-LOAD-BALANCER-LOCAL、KUBE-LOAD-BALANCER-FW、KUBE-LOAD-BALANCER-SOURCE-CIDR、KUBE-LOAD-BALANCER-SOURCE-IP
  • 若为 NodePort 类型更新对应的 ipset 列表 KUBE-NODE-PORT-TCP、KUBE-NODE-PORT-LOCAL-TCP、KUBE-NODE-PORT-LOCAL-SCTP-HASH、KUBE-NODE-PORT-LOCAL-UDP、KUBE-NODE-PORT-SCTP-HASH、KUBE-NODE-PORT-UDP
  • 同步 ipset 记录
  • 刷新 iptables 规则

此外,由于 linux 内核原生的 ipvs 模式只支持 DNAT,不支持 SNAT,所以,在以下几种场景中 ipvs 仍需要依赖 iptables 规则:

  • 1、kube-proxy 启动时指定 –-masquerade-all=true 参数,即集群中所有经过 kube-proxy 的包都做一次 SNAT;
  • 2、kube-proxy 启动时指定 --cluster-cidr= 参数;
  • 3、对于 Load Balancer 类型的 service,用于配置白名单;
  • 4、对于 NodePort 类型的 service,用于配置 MASQUERADE;
  • 5、对于 externalIPs 类型的 service;

但对于 ipvs 模式的 kube-proxy,无论有多少 pod/service,iptables 的规则数都是固定的。文章来源地址https://www.toymoban.com/news/detail-501549.html

到了这里,关于kube-proxy源码阅读的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • kube-proxy模式 iptables和ipvs对比

    kube-proxy的ipvs模式和iptables模式在Kubernetes集群中各有优劣,主要体现在性能、功能和支持的协议方面。 IPVS模式:由于IPVS是专门为负载均衡设计的,它在性能方面通常优于iptables。IPVS使用基于哈希的负载均衡算法,能够快速处理大量的并发连接,其连接处理的名义计算复杂度

    2024年04月08日
    浏览(40)
  • prometheus监控k8s kube-proxy target down

    解决 修改配置 删除 kube-proxy pod 使之重启应用配置

    2024年02月14日
    浏览(47)
  • 解决阿里云ESC启动kube-proxy服务时出现错误 亲测有效

    启动kube-proxy服务时出现错误如下:Failed to execute iptables-restore: exit status 1 (iptables-restore: invalid option – ‘5’ 我用的k8s是1.90 二进制安装 一般都是说版本过低怎么 降版本 1下载上传低版本iptable 下载地址 https://download.csdn.net/download/qq_33121481/13218948 主要是使用这个版本的 我以前使

    2024年02月03日
    浏览(38)
  • 【云原生 | 从零开始学Kubernetes】二十、Service代理kube-proxy组件详解

    该篇文章已经被专栏《从零开始学k8s》收录 上一篇文章:Kubernetes核心技术Service实战 点击跳转 Kubernetes service 只是把应用对外提供服务的方式做了抽象,真正的应用跑在 Pod 中的 container 里,我们的请求转到 kubernetes nodes 对应的 nodePort 上,那么 nodePort 上的请求是如何进一步转

    2024年02月03日
    浏览(39)
  • 【K8S】外部访问请求原理流程(service、kube-proxy、pod的关系)

    用户发起请求,请求传送到Ingress Ingress :作用是定义请求如何转发到service的规则,ingress支持7层代理转发,它可以通过根据不同的域名或者URL访问路径把请求流量转发到不同的service上,实现调度不同业务域、不同URL访问路径的业务流量。 Service: 提供了服务的负载均衡和反向代

    2024年01月17日
    浏览(46)
  • 如何查看k8s中kube-proxy的模式是ipvs还是iptables

    要查看 Kubernetes 中 kube-proxy 的模式(IPVS 还是 iptables),可以使用以下方法之一: 1. 通过 kubectl 命令查看 kube-proxy 的配置: 这将显示 kube-proxy 的配置信息,包括使用的模式。如果配置中包含 mode: \\\"ipvs\\\" ,则表示 kube-proxy 使用 IPVS 模式。如果配置中包含 mode: \\\"iptables\\\" ,则表示

    2024年02月14日
    浏览(36)
  • Kubernetes高可用集群二进制部署(五)kubelet、kube-proxy、Calico、CoreDNS

    Kubernetes概述 使用kubeadm快速部署一个k8s集群 Kubernetes高可用集群二进制部署(一)主机准备和负载均衡器安装 Kubernetes高可用集群二进制部署(二)ETCD集群部署 Kubernetes高可用集群二进制部署(三)部署api-server Kubernetes高可用集群二进制部署(四)部署kubectl和kube-controller-man

    2024年02月14日
    浏览(36)
  • 高阶k8s二次开发教程 -- 通过阅读Istio源码习得

    本篇文章全网几乎找不到,在做深层次的k8s二次开发时非常管用。那就是使用Client-go去访问自定义CRD资源。 我们先使用kubebuilder生成一个CRD,论生成CRD这些,还是kubebuilder更加方便。 Kubernetes API(在本例中为Project和ProjectList)提供的每种类型都需要实现该k8s.io/apimachinery/pkg/r

    2024年02月15日
    浏览(38)
  • 通过kube-apiserver访问K8s集群中的App

    K8s集群中的App(或者svc),通常使用ClusterIP,NodePort,Loadbalancer这些方式访问,但是你也可以通过Kube-apiserver(管理面)来访问App。 在《跟唐老师学习云网络 - Kubernetes网络实现》里面,提到K8s集群里面的容器,有几种访问方法: LoadBalancer Ingress ClusterIP NodePort 这里就不再分析

    2024年01月19日
    浏览(45)
  • 【k8s源码分析-Apiserver-2】kube-apiserver 结构概览以及主体部分源码分析

    Kubernetes 源码剖析(书籍) kube-apiserver的设计与实现 - 自记小屋 APIGroupInfo 记录 GVK 与 Storage 的对应关系 将 GVK 转换成,Restful HTTP Path 将 Storage 封装成 HTTP Handler 将上面两个形成映射,实现相关的路由处理 发起请求并处理的流程 发送请求:通过 GVK 对应的 Restful HTTP Path 发送请求

    2024年02月03日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包