YurtHub的功能主要是对客户端Request的反向代理。本文基于Openyurt0.3版本(commit:e1c1651405aeeb61f0ad264a9acdf8d08e917a4d)的源码,提供了对反向代理功能的解析(不包括YurtHub的本地缓存管理:CacheManager,storage和GC)。
YurtHubServer是执行ListenAndServe的主体,其主要结构和功能是YurtReverseProxy,即边缘节点的反向代理。YurtHubServer将YurtReverseProxy挂载在几乎所有路径(以/为前缀的路径,但也有一些路径另作他用)上,当HTTP请求的URL路径满足条件就会交由YurtReverseProxy处理,但在此之前会对request通过context添加一些额外的信息。
YurtHubServer挂载的路径,方法和handler的对应关系:
其中:
updateToken是用来更新节点的证书。
healthz是直接返回StatusOK,用于其它节点对本节点的健康检查。
proxyHandler提供其主要的反向代理功能。
YurtHubServer在接收到HTTPrequest后,在通过YurtReverseProxy转发前,会先对request进行处理。流程如下:
在这之后才会将request转交给YurtReverseProxy。
其构造handler的函数源码如下:
代理来自边缘节点(Kubelet,Kube-Proxy等)的REST请求,根据APIServer的健康状况,如果健康则将该请求通过LoadBalancer转发到APIServer处理,否则在本地节点LocalProxy中进行处理。最后将reponse返回给请求方。
YurtReverseProxy内有:
结构体如下:
typeyurtReverseProxystruct{resolverapirequest.RequestInfoResolverloadBalancerremote.LoadBalancerlocalProxy*local.LocalProxycacheMgrcachemanager.CacheManagermaxRequestsInFlightint//用来限制pendingrequest数量的上限stopCh<-chanstruct{}}YurtReverseProxy工作流程作为YurtHubServer的一个组件,它接受YurtHubServer指定Path(除了/v1/token,/v1/healthz和一些/debug下的路径外)的request,并进行处理。
通过LoadBalancer判断APIServer的健康状况,如果健康则调用LoadBalancer处理请求,否则调用LocalProxy处理请求。
具体源码如下:
Next:
在APIServer处于健康状态时,LoadBalancer接收来自YurtReverseProxy的request,并转发到APIServer。LoadBalancer中记录了多个能处理request的APIServer的地址,在转发request时会采取一定的负载均衡策略。
LoadBalancer内主要有APIServer代理列表([]*RemoteProxy)和负载均衡策略(loadBalancerAlgo)。APIServer代理(RemoteProxy)代理一个能处理request的APIServer。LoadBalancer根据设置的负载均衡策略,挑选一个APIServer代理,将request通过APIServer代理转发到APIServer。
typeloadBalancerstruct{backends[]*RemoteProxyalgoloadBalancerAlgocertManagerinterfaces.YurtCertificateManager}RemoteProxy的结构RemoteProxy内置有
源码如下:
目前LoadBalancer中内置了两种负载均衡策略:Round-Robin和基于优先级的策略。一个LoadBalancer采用哪种负载均衡策略在创建时由lbMode参数指定:rr表示Round-Robin,priority表示基于优先级的调度策略。默认使用的Round-Robin。LoadBalancer统一通过策略的PickOne()接口来选出一个能够转发请求的APIServer。
策略结构
typeloadBalancerAlgointerface{PickOne()*RemoteProxyName()string}Roud-Robin策略原理
如果没有健康的APIServer,则返回nil。否则通过不回退的轮询来找到第一个健康的APIServer。
轮询部分的源码:
hasFound:=falseselected:=rr.next//next是上次轮询的终点位置//rr.backends是记录的所有APIServer的序列fori:=0;i 使用基于优先级的策略时,需要手动按优先级将APIServer序列排序。策略本身的实现是从头开始的轮询。 实现源码: 在APIServer非健康状态下,接受来自YurtReverseProxy的request,并根据本地缓存和request的内容进行处理。目前只支持ResourceRequest。处理内容主要是根据ResourceRequest中对资源的操作类型(verb)来更新本地缓存。 LocalProxy内有: //LocalProxyisresponsibleforhandlingrequestswhenremoteserversareunhealthytypeLocalProxystruct{cacheMgrmanager.CacheManagerisHealthyIsHealthy}LocalProxy的处理流程在Response.Header中设置Transfer-Encoding:chuncked,以长连接处理watch请求。然而目前LocalProxy并不支持本地处理watch,因此直到Timeout都在周期性探测APIServer是否健康,如果感知到APIserver恢复健康则直接返回nil,下次watch将由LoadBalancer处理。 如果请求的resource是event,则调用CacheManager.CacheResponse将请求的内容缓存到本地。并总会返回一个response,header和body与request相同,状态码为201(StatusCreated)。 LocalProxy不支持对resource的delete请求,因此返回的Response的Reason为”Forbidden”,状态码为200(StatusOK)。 根据request中的信息生成key,调用CacheManager.QueryCache根据key找到缓存中的runtime.object(s),将其写入response并返回。