Kubernetes指南:核心组件分析

发布于 2017-11-17 · 本文总共 7946 字 · 阅读大约需要 23 分钟

API Server

提供各类资源对象的增删查改及Watch等HTTP Rest接口; 整个系统的数据总线和数据中心,集群内各个功能模块之间数据交互和通信的中心枢纽;

1.集群管理的API入口;

2.资源配置控制入口;

3.提供了完备的集群安全机制;

概述

kube-apiserver –insecure-port:8080 –secure-port:6443

Pod中的进程如何知道API Server的访问地址:

kubectl  get  svc                                    
NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)             AGE
kubernetes   ClusterIP   10.96.0.1      <none>        443/TCP             299d

API Server架构

1.API层:以REST方式提供各种API接口, 除了有Kubernetes资源对象的CRUD和Watch等主要API, 还有健康检查、UI、 日志、性能指标等运维监控相关的API;

2.访问控制层:当客户端访问API接口时,访问控制层负责对用户身份鉴权, 验明用户身份,核准用户对Kubernetes资源对象的访问权限, 然后根据配置的各种资源访问许可逻辑(Admission Control),判断是否允许访问;

3.注册表层:Kubernetes把所有资源对象都保存在注册表-Registry中, 针对注册表中的各种资源对象都定义了:资源对象的类型、如何创建资源对象、 如何转换资源的不同版本,以及如何将资源编码和解码为JSON或ProtoBuf格式进行存储;

4.etcd数据库:用于持久化存储Kubernetes资源对象的KV数据库;

etcd的watch API接口对于API Server来说至关重要,因为通过这个接口, API Server 创新性地设计了List-Watch这种高性能的资源对象实时同步机制, 使Kubernetes可以管理超大规模的集群,及时响应和快速处理集群中的各种事件;

Pod调度流程

一个完整的Pod调度流程

借助etcd提供的Watch API接口,API Server可以监听 (Watch)在etcd上发生的数据操作事件, 比如Pod创建事件、更新事件、删除事件等,在这些事件发生后,etcd会及时通知API Server。 比如当一个 ReplicaSet对象被创建并被保存到etcd中后, etcd会立即发送一个对应的Create事件给API Server;

为了让Kubernetes中的其他组件在不访问底层etcd数据库的情况下,也能及时获取资源对象的变化事件, API Server模仿etcd的Watch API接口提供了自己的Watch接口, 这样一来,这些组件就能近乎实时地获取它们感兴趣的任意资源对象的相关事件通知了; 同时,在监听自己感兴趣的资源的时候,客户端可以增加过滤条件, 以List-Watch为例,node1节点上的kubelet进程只对自己节点上的Pod事件感兴趣;

Kubernetes List-Watch用于实现数据同步的代码逻辑; 客户端首先调用API Server的List接口获取相关资源对象的全量数据并将其缓存到内存中, 然后启动对应资源对象的Watch协程, 在接收到Watch事件后, 再根据事件的类型(比如新增、修改或删除)对内存中的全量资源对象列表做出相应的同步修改, 从实现上来看,这是一种全量结合增量的、高性能的、近乎实时的数据同步方式;

kubernetes Proxy API接口

kubernetes Proxy API接口的作用是代理REST请求, 即Kubernetes API Server把收到的REST请求转发到某个Node上的kubelet守护进程的REST端口, 由该kubelet进程负责响应;

Node相关接口:

/api/v1/proxy/nodes/{node_name}/pods/  # 列出指定节点内所有pod的信息
/api/v1/proxy/nodes/{node_name}/stats/ # 列出指定节点内物理资源的统计信息
/api/v1/proxy/node/{node_name}/spec/   # 列出指定节点的概要信息

获取的Pod信息数据来自Node而非etcd数据库;

http://192.168.18.131:8080/api/v1/proxy/namespaces/default/pods/myweb- g9pmm/

在 Kubernetes集群之外访问某个Pod容器的服务(HTTP服务)时, 可以用Proxy API实现,这种场景多用于管理目的,比如逐一排查Service的Pod副本, 检查哪些Pod的服务存在异常;

Kubernetes Proxy API也有Service的Proxy接口, 其接口定义与Pod的接口定义基本一样: http://192.168.18.131:8080/api/v1/proxy/namespaces/default/services/myweb

集群功能模块之间的通信

集群内各个功能模块通过API server将信息存入etcd,当需要获取和操作这些数据时, 则通过REST接口(GET、LIST、WATCH)调用实现,从而完成各模块之间的信息交互

1.kubelet进程与API Service的交互

1.每个Node上的kubelet每隔一个时间周期, 就会调用一次API Server的REST接口报告自身状态, API Server在接收到这些信息后,会将节点状态信息更新到etcd中;

2.kubelet也通过API Server的Watch接口监听Pod信息, 如果监听到新的Pod副本被调度绑定到本节点,则执行Pod对应的容器创建和启动逻辑; 如果监听到Pod对象被删除,则删除本节点上相应的Pod容器; 如果监听到修改Pod的信息,kubelet就会相应地修改本节点的Pod容器;

2.kube-controller-manager进程与API server的交互

Node Controller模块通过Watch接口,实时监控Node的信息;

3.kube-scheduler与API Server

Watch到新建Pod副本的信息后,检索所有符合该Pod要求的Node列表,执行调度;

各功能模块对API Server的访问数据会有缓存;

Controller Manager

集群内部的管理控制中心; 负责集群内的Node、Pod副本、Endpoint、Nemespace、ServiceAccount、ResourceQuota等的管理; Node宕机时发现故障并执行自动化修复;

Replication Controller

Replication Controller的职责:

1.确保在当前集群中有且仅有N个Pod实例,N是在RC中定义的Pod副本数量;

2.通过调整RC的spec.replicas属性值来实现系统扩容或者缩容;

3.通过改变RC中的Pod模板(主要是镜像版本)来实现系统的滚动升级;

Replication Controller的典型使用场景:

1.重新调度(Rescheduling)。 副本控制器都能确保指定数量的副本存在于集群中,即使发生节点故障或Pod副本被终止运行等意外状况。

2.弹性伸缩(Scaling)。 手动或者通过自动扩容代理修改副本控制器的spec.replicas属性值,实现增加或减少副本的数量;

3.滚动更新(Rolling Updates)。 副本控制器被设计成通过逐个替换Pod的方式来辅助服务的滚动更新。 推荐的方式是创建一个只有一个副本的新RC,若新RC副本数量加1,则旧RC的副本数量减1,直到这个旧RC的副本数量为0,然后删除该旧RC。 通过上述模式,即使在滚动更新的过程中发生了不可预料的错误,Pod集合的更新也都在可控范围内。 在理想情况下,滚动更新控制器需要将准备就绪的应用考虑在内,并保证在集群中任何时刻都有足够数量的可用Pod;

Node Controller

kubelet进程在启动时通过API Server注册自身的节点信息, 并定时向API Server汇报状态信息, API Server在接收到这些信息后,会将这些信息更新到etcd中;

Node Controller通过API Server实时获取Node的相关信息, 实现管理和监控集群中的各个Node的相关控制功能;

ResourceQuota Controller

Kubernetes支持如下三个层次的资源配额管理。

1.容器级别,可以对CPU和Memory进行限制;

2.Pod级别,可以对一个Pod内所有容器的可用资源进行限制;

3.Namespace级别,为Namespace(多租户)级别的资源限制; 包括;Pod数量,Replication Controller数量,Service数量, ResourceQuota数量,Secret数量,可持有的PV数量;

NameSpace Controller

用户通过API Server可以创建新的Namespace并将其保存在etcd中, Namespace Controller定时通过API Server读取这些Namespace的信息;

如果Namespace被API标识为优雅删除(通过设置删除期限实现,即设置 DeletionTimestamp属性), 则将该NameSpace的状态设置成Terminating 并保存到etcd中;

在Namespace的状态被设置成Terminating后,由Admission Controller的NamespaceLifecycle插件来阻止为该Namespace创建新的资源; 同时,在Namespace Controller删除该Namespace中的所有资源对象后, Namespace Controller对该Namespace执行finalize操作,删除Namespace的spec.finalizers域中的信息;

Service Controller

属于Kubernetes集群与外部的云平台之间的一个接口控制器。

Service Controller监听Service的变化, 如果该Service是一个LoadBalancer类型的Service(externalLoadBalancers=true), 则Service Controller确保在外部的云平台上该Service对应的LoadBalancer实例被相应地创建、 删除及更新路由转发表(根据Endpoints的条目);

Endpoint Controller

Endpoints表示一个Service对应的所有Pod副本的访问地址, Endpoints Controller就是负责生成和维护所有Endpoints对象的控制器;

它负责监听Service和对应的Pod副本的变化,如果监测到Service被 删除,则删除和该Service同名的Endpoints对象。如果监测到新的Service 被创建或者修改,则根据该Service信息获得相关的Pod列表,然后创建 或者更新Service对应的Endpoints对象。如果监测到Pod的事件,则更新 它所对应的Service的Endpoints对象(增加、删除或者修改对应的 Endpoint条目)

(kube-proxy进程获取每个Service的Endpoints,实现了Service的负载均衡功能;)

scheduler–承上启下

Scheduler的作用是将待调度的Pod(API新创建的Pod、Controller Manager为补足副本而创建的Pod等) 按照特定的调度算法和调度策略绑定(Binding)到集群中某个合适的Node上,并将绑定信息写入etcd中;

接收Controller Manager创建的新Pod,安排一个Node,并负责Pod生命周期;

将调度的Pod通过一些复杂的调度流程计算出最佳目标节点;

  • 待调度Pod列表;

  • 可用Node列表;

  • 调度算法和策略;

Scheduler当前提供的默认调度流程分为两步:

(1)预选调度过程:即遍历所有目标Node,筛选出符合要求的候选节点。 为此,Kubernetes内置了多种预选策略(xxx Predicates)供用户选择;

(2)确定最优节点,在第1步的基础上,采用优选策略(xxx Priority)计算出每个候选节点的积分,积分最高者胜出;

预选策略:

1.NoDiskConflict

2.PodFitsResources

3.PodSelectorMatches

4.PodFitsHost

5.CheckNodeLabelPresence

6.CheckServiceAffinity

7.PodFitsPorts

优选策略:

1.LeastRequestedPriority

2.CalculateNodeLabelPriority

3.BalencedResourceAllocation

kubelet

处理Master节点下发到本节点的任务,管理Pod及Pod中的容器;

1.节点管理

–register-ndoe

节点通过设置kubelet的启动参数“–register-node”,来决定是否向API Server注册自己;

–api-servers

API Server的位置;

–kubeconfig

kubeconfig文件,用于访问API Server的安全配置文件;

–cloud-provider

云服务商(IaaS)地址,仅用于公有云环境;

–node-statu-update-frequency

定时向API Server 发送节点的新消息,API Server在接收到这些信息后,将这些信息写入etcd; 通过kubelet的启动参数“–node-status- update-frequency” 设置kubelet每隔多长时间向API Server报告节点状态;

当前每个kubelet都被授予创建和修改任何节点的权限。 但是在实践中,它仅仅创建和修改自己。 将来会限制kubelet的权限,仅允许它修改和创建所在节点的权限;

2.Pod管理

获取Node上要运行的Pod清单:

1.文件:

2.HTTP端点(URL):

3.API Server:

所有以非API Server方式创建的Pod都叫作Static Pod。 kubelet将 Static Pod的状态汇报给API Server,API Server为该Static Pod创建一个Mirror Pod和其相匹配。Mirror Pod的状态将真实反映Static Pod的状态。 当Static Pod被删除时,与之相对应的Mirror Pod也会被删除;

kubelet监听etcd,所有针对Pod的操作都会被kubelet监听。 如果发现有新的绑定到本节点的Pod,则按照Pod清单的要求创建该Pod;

如果发现本地的Pod被修改,则kubelet会做出相应的修改,比如在删除Pod中的某个容器时, 会通过Docker Client删除该容器;

如果发现删除本节点的Pod,则删除相应的Pod,并通过DockerClient删除Pod中的容器;

3.容器健康检查

LivenessProbe探针:用于判断容器是否健康并反馈给kubelet。 如果LivenessProbe探针探测到容器不健康,则kubelet将删除该容器, 并根据容器的重启策略做相应的处理;

ReadinessProbe探针:用于判断容器是否启动完成,且准备接收请求。 如果ReadinessProbe探针检测到容器启动失败,则Pod的状态将被修改, Endpoint Controller将从Service的Endpoint中删除包含该容器所在Pod的IP地址的Endpoint条目;

kubelet定期调用容器中的LivenessProbe探针来诊断容器的健康状况。 LivenessProbe包含3种实现方式:ExecAction、TCPSocketAction、HTTPGetAction;

4.cAdvisor资源监控

cAdvisor是一个开源的分析容器资源使用率和性能特性的代理工具,因容器而产生;

在Kubernetes项目中,cAdvisor被集成到Kubernetes代码中, kubelet则通过cAdvisor获取其所在节点及容器的数据; cAdvisor自动查找所有在其所在Node上的容器,自动采集CPU、内存、文件系统和网络使用的统计信息; 在大部分Kubernetes集群中,cAdvisor通过它所在Node的4194端口暴露一个简单的UI;

cAdvisor只能提供2~3min的监控数据,对性能数据也没有持久化;

从Kubernetes 1.8版本开始,性能指标数据的查询接口升级为标准的Metrics API, 后端服务则升级为全新的 Metrics Server;

因此,cAdvisor在4194端口提供的UI和API服务从Kubernetes 1.10版本开始进入弃用流程, 并于1.12版本完全关闭;

如果还希望使用cAdvisor的这个特性, 则从1.13版本开始可以通过部署一个DaemonSet在每个Node上启动一个cAdvisor来提供UI和API;

kube-proxy

Service是对一组Pod的抽象,它会根据访问策略(如负载均衡策略)来访问这组Pod;

真正将Service的作用落实的是kube-proxy;

在Kubernetes集群的每个Node上都会运行一个kube-proxy服务进程, 可以把这个进程看作Service的透明代理兼负载均衡器,其核心功能是将到某个Service的访问请求转发到后端的多个Pod实例上;

此外,Service的Cluster IP与NodePort等概念是kube-proxy服务通过iptables的NAT转换实现的, kube-proxy在运行过程中动态创建与Service相关的 ptables规则, 这些规则实现了将访问服务(Cluster IP或NodePort)的请求负载分发到后端Pod的功能;

Kubernetes从1.2版本开始,将iptables作为kube-proxy的默认模式; iptables模式下的kube-proxy不再起到Proxy的作用,其核心功能:通过API Server的Watch接口实时跟踪Service与Endpoint的变更信息, 并更新对应的iptables规则,Client的请求流量则通过iptables的NAT机制“直接路由”到目标Pod;

Kubernetes从1.8版本开始引入第3代的IPVS(IP Virtual Server)模式; IPVS在Kubernetes 1.11 中升级为GA稳定版;

iptables与IPVS虽然都是基于Netfilter实现的,但因为定位不同, 二者有着本质的差别:iptables是为防火墙而设计的; IPVS则专门用于高性能负载均衡,并使用更高效的数据结构(Hash表),允许几乎无限的规模扩张, 因此被kube-proxy采纳为第三代模式;

与iptables相比,IPVS拥有以下明显优势:

1.为大型集群提供了更好的可扩展性和性能;

2.支持比iptables更复杂的复制均衡算法(最小负载、最少连接、加权等);

3.支持服务器健康检查和连接重试等功能;

4.可以动态修改ipset的集合,即使iptables的规则正在使用这个集合。

refs

《Kubernetes:The Definitive Guide》

https://borismattijssen.github.io/articles/kubernetes-informers-controllers-reflectors-stores




本博客所有文章采用的授权方式为 自由转载-非商用-非衍生-保持署名 ,转载请务必注明出处,谢谢。
声明:
本博客欢迎转发,但请保留原作者信息!
博客地址:邱文奇(qiuwenqi)的博客;
内容系本人学习、研究和总结,如有雷同,实属荣幸!
阅读次数:

文章评论

comments powered by Disqus


章节列表