cloud provider Service Controller
service controller 负责观察 k8s 中 service 资源的创建,更新和删除事件。并基于当前 k8s 中的 service 状态去云上配置负载均衡,保证云上的负载均与 serivce 资源描述相一致。
service controller 在 cloud contorller 中的一个模块随 cloud controller 启动,可以通过启动 new service controller 参数可以观测到,service controller 是通过观察 service 和 node 资源来工作的。
1 | // Start the service controller |
new 函数的实现如下,核心是流程是通过 list/watch 机制来观测 service 的 event,然后触发 enqueue 的函数,再通过 sync woker 从 wrok queue 中取出 item 处理云上 lb 的绑定逻辑。
1 | // New returns a new service controller to keep cloud provider service resources |
service 通过形如 namespace+serivce 名字的 key 放入 work queue,而 syncService 函数根据 key 取出 service 进行实际的处理操作,如果操作完成过后从 work queue 中调用 queue.done(key) 移除掉。
1 | func (s *ServiceController) processNextWorkItem() bool { |
之所以 service 要一个额外的 work queue 有原因的,其一是因为云上 lb 的实际绑定解绑操作相对于单纯的 serivce 声明要慢很多,其二是当 service 从 k8s 中删除的时候就真的被从 etcd 中移除了,这个时候从缓存里面找个删除对应公网 lb 的关键参数。
这个才是 service controller 的核心逻辑,这里会确认 service 是删除还是更新。
1 | // syncService will sync the Service with the given key if it has had its expectations fulfilled, |
看一下处理 service update 的核心逻辑,
1 | // processServiceUpdate operates loadbalancers for the incoming service accordingly. |
根据实际情况判断是更新,还是创建云上 lb 资源。
1 | // createLoadBalancerIfNeeded ensures that service's status is synced up with loadbalancer |
1 | func (s *ServiceController) ensureLoadBalancer(service *v1.Service) (*v1.LoadBalancerStatus, error) { |
下面是抽象给 cloud provider 实现的接口,由 serivce controller 来统一调用,EnsureLoadBalancer 是最核心的函数,一般云厂商的实现方式就是将他们的公网 LB 产品和 k8s 的 LoadBalancer type 的 service 结合起来。
1 | // LoadBalancer is an abstract, pluggable interface for load balancers. |
如果客户在 k8s 中创建 LoadBalancer type 的 service,cloud proivder 的 EnsureLoadBalancer 常见实现方式是,调用云上 LB 相关接口将 LB 及其必要的依赖资源创建出来,其 LB 对应的后端是 serivce 所属的集群内的 k8s node全部节点,部分节点也可以的原因是因为收到流量的部分节点会通过 kube-proxy 的规则将流量二次转发具体细节。
当 lb 创建完成,后端绑定成功后,客户就可以通过访问公网类型的 LB 的 VIP 来访问 Pod 中的业务了。这个时候流量是先到云厂商的公网网关,然后流量通过 LB 到云厂商提供给 k8s 的 node 上,最后再由 kube-proxy 通过 watch endpoint 产生的转发规则讲流量运到 pod 中。