Kubernetes用来管理容器集群的平台。既然是管理集群,那么就存在被管理节点,针对每个Kubernetes集群都由一个Master负责管理和控制集群节点。
通过Master对每个节点Node发送命令。简单来说,Master就是管理者,Node就是被管理者。Node可以是一台机器或者一台虚拟机。在Node上面可以运行多个Pod,Pod是Kubernetes管理的最小单位,同时每个Pod可以包含多个容器(Docker)。
1、API Server
APIServer的核心功能是对核心对象(例如:Pod,Service,RC)的增删改查操作,同时也是集群内模块之间数据交换的枢纽。它包括常用的API、访问(权限)控制、注册、信息存储(etcd)等功能。在它的下面可以看到Scheduler,它将待调度的Pod绑定到Node上,并将绑定信息写入etcd中。etcd包含在APIServer中,用来存储资源信息。
API Server的架构从上到下分为4层:
- API层:主要以REST方式提供各种API接口,针对Kubernetes资源对象的CRUD和Watch等主要API,还有健康检查、UI、日志、性能指标等运维监控相关的API。
- 访问控制层:负责身份鉴权,核准用户对资源的访问权限,设置访问逻辑(Admission Control)。
- 注册表层:选择要访问的资源对象。注意,Kubernetes把所有资源对象都保存在注册表(Registry)中,如Pod、Service、Deployment等。
- etcd数据库:保存创建副本的信息。用来持久化Kubernetes资源对象的Key-Value数据库。
当kubectl用Create命令建立Pod时,是通过APIServer中的API层调用对应的RESTAPI方法。之后会进入权限控制层,通过Authentication获取调用者身份,通过Authorization获取权限信息。
AdmissionControl中可配置权限认证插件,通过插件来检查请求约束。例如,启动容器之前需要下载镜像,或者检查具备某命名空间的资源。还记得redis-leader-deployment.yaml中配置需要生成的Pod的个数为1。
到了Registry层,会从CoreRegistry资源中取出1个Pod作为要创建的Kubernetes资源对象。然后将Node、Pod和Container信息保存到etcd中去。这里的etcd可以是一个集群,由于里面保存集群中各个Node/Pod/Container的信息,所以必要时需要备份,或者保证其可靠性。
通过kubectl根据配置文件向APIServer发送命令,在Node上面建立Pod和Container。在API Server,经过API调用、权限控制、调用资源和存储资源的过程,实际上还没有真正开始部署应用。
2、Controller Manager
Kubernetes是一个自动化运行的系统,需要有一套管理规则来控制这套系统。Controller Manager就是这个管理者,或者说是控制者。它包括8个Controller,分别对应着副本、节点、资源、命名空间、服务等。
由于微服务的部署都是分布式的,所以对应的Pod及容器的部署也是。为了能够方便地找到这些Pod或者容器,引入了Service(kube-proxy)进程,由它来负责反向代理和负载均衡的实施。
Kubernetes需要管理集群中的不同资源,所以针对不同的资源要建立不同的Controller。每个Controller通过监听机制获取API Server中的事件(消息),它们通过API Server提供的(List-Watch)接口监控集群中的资源,并且调整资源的状态。
可以把它想象成一个尽职的管理者,随时管理和调整资源。比如MySQL所在的Node意外宕机了,Controller Manager中的Node Controller会及时发现故障,并执行修复流程。在部署了成百上千微服务的系统中,这个功能极大地协助了运维人员。由此可以看出,Controller Manager是Kubernetes资源的管理者,是运维自动化的核心。
3、Scheduler与kubelet
Scheduler的作用是,将待调度的Pod按照算法和策略绑定到Node上,同时将信息保存在etcd中。
如果把Scheduler比作调度室,那么下面这3件事就是它需要关注的,待调度的Pod、可用的Node,以及调度算法和策略。
简单地说,就是通过调度算法/策略把Pod放到合适的Node中。此时Node上的kubelet通过API Server监听到Scheduler产生的Pod绑定事件,然后通过Pod的描述装载镜像文件,并且启动容器。
也就是说Scheduler负责思考Pod放在哪个Node中,然后将决策告诉kubelet,kubelet完成Pod在Node的加载工作。也可以这样认为,Scheduler是“boss”,kubelet是干活的“工人”,它们都通过API Server进行信息交换。部署在Kubernetes中,Pod如何访问其他的Pod呢?答案是通过Kubernetes的Service机制。
在Kubernetes中的Service定义了一个服务的访问入口地址(IP+Port)。Pod中的应用通过这个地址访问一个或者一组Pod副本。Service与后端Pod副本集群之间是通过Label Selector来实现连接的。Service所访问的这一组Pod都会有同样的Label,通过这种方法知道这些Pod属于同一个组。
4、kube-proxy
只有理解了kube-proxy的原理和机制,才能真正理解Service背后的实现逻辑。在Kubernetes集群的每个Node上都会运行一个kube-proxy服务进程,可以把这个进程看作Service的负载均衡器,其核心功能是将发送到Service的请求转发到后端的多个Pod上。
此外,Service的Cluster-IP与NodePort是kube-proxy服务通过iptables的NAT转换实现的。kube-proxy在运行过程中动态创建与Service相关的iptables规则。
由于iptables机制针对的是本地的kube-proxy端口,所以在每个Node上都要运行kube proxy组件。
因此在Kubernetes集群内部,可以在任意Node上发起对Service的访问请求。Pod在Kubernetes内互相访问,外网访问Pod。
另外,作为资源监控,Kubernetes在每个Node和容器上都运行了cAdvisor。它是用来分析资源使用率和性能的工具,支持Docker容器。kubelet通过cAdvisor获取其所在Node及容器(Docker)的数据。
cAdvisor自动采集CPU、内存、文件系统和网络使用的统计信息。kubelet作为Node的管理者,把cAdvisor采集上来的数据通过RESTAPI的形式暴露给Kubernetes的其他资源,让他们知道Node/Pod中的资源使用情况。
下面部署一个Nginx服务来说明Kubernetes系统各个组件调用关系。
首先需要明确,一旦Kubernetes环境启动后,master和node都会将自身的信息存储到etcd数据库中。
一个Nginx服务的安装请求首先会被发送到master节点上的API Server组件。
API Server组件会调用Scheduler组件来决定到底应该把这个服务安装到哪个node节点上。此时,它会从etcd中读取各个Node节点的信息,然后按照一定的算法进行选择,并将结果告知API Server。
API Server调用Controller-Manager去调用Node节点安装Nginx服务。Kubelet接收到指令后,会通知Docker,然后由Docker来启动一个Nginx的Pod。
Pod是Kubernetes的最小操作单元,容器必须跑在Pod中。这样,一个Nginx服务就开始运行了,如果需要访问Nginx,就需要通过kube-proxy来对Pod产生访问的代理,这样外界用户就可以访问集群中的Nginx服务了。