27.5 重要组件

如果现在从头设计一套容器集群管理平台,可能不同人最终设计出来的方案是不相同的,但相信大部分都能想到如下几个方面的需求:

·要采用分布式架构,保证良好的可扩展性;

·控制平面要实现逻辑上的集中,数据平面要实现物理上的分布;

·得有一套资源调度系统,负责所有的资源调度工作,要容易插拔;

·对资源对象要进行抽象,所有资源要能实现高可用性。

Kubernetes中的节点包括两种类型:Master节点负责控制,Node节点负责干活,各自又通过若干组件组合来实现。

Master节点上组件主要有Etcd、apiserver、scheduler、controller-manager,以及ui、DNS等可选插件:

·Etcd:作为数据库,存放所有集群相关的数据;

·kube-apiserver:Kubernetes系统的对外接口,提供RESTful API供客户端和其他组件调用,支持水平扩展。

·kube-scheduler:负责对资源进行调度,具体负责分配某个请求的Pod到某个节点上;

·kube-controller-manager:对不同资源的管理器,包括节点管理器、复制管理器、服务管理器、权限管理器等;

·kube-ui:自带的一套用来查看集群状态的Web界面;

·DNS:记录启动的容器组和服务地址;

其他组件:包括容器资源使用监控、日志记录、setup脚本等。这些组件可以任意部署在相同或者不同机器上,只要可以通过标准的HTTP接口相互访问到即可,这意味着对Kubernetes的管理组件进行扩展将变得十分简单。

Node节点上主要包括kubelet、kube-proxy、容器引擎和一些辅助组件:

·kubelet:节点上最主要的工作代理,汇报节点状态并实现容器组的生命周期管理;

·kube-proxy:代理对抽象的应用地址的访问,负责配置正确的转发规则;

·容器引擎:本地的容器依赖,目前支持Docker和rkt;

·辅助组件:supervisord用来保持kubelet和docker进程运行,fluentd用来转发日志等。

下面分别介绍这些组件的作用和基本用法。

27.5.1 Etcd

Kubernetes依赖Etcd数据库服务来记录所有节点和资源的状态。可以说,Etcd是Kubernetes集群中最重要的组件。apiserver的大量功能都是通过跟Etcd进行交互来实现。关于Etcd数据库的详细信息,请参考之前的第22章。

27.5.2 kube-apiserver

作为REST API服务端,kube-apiserver接收来自客户端和其他组件的请求,更新Etcd中的数据,是响应对API资源操作的最前端组件。一般推荐部署多个kube-apiserver来提高可用性。

可以通过kube-apiserver-h命令查看服务端支持的参数选项,其中比较重要的配置选项参见表27-1。

表27-1 kube-apiserver配置选项

27.5 重要组件 - 图1

27.5.3 kube-scheduler

kube-scheduler负责具体的资源调度工作,对节点进行筛选和过滤。当收到资源请求后,负责按照调度策略选择最合适的节点运行Pod。

kube-scheduler是以插件形式存在的,支持各种复杂的调度策略,确保Kubernetes集群服务的性能和高可用性。kube-scheduler在调度上考虑服务质量、软硬件限制、(抗)亲和性(affinity)、locality、工作负载交互等多个方面。

可以通过kube-scheduler-h命令查看支持的参数选项,其中比较重要的配置选项参见表27-2。

表27-2 kube-scheduler配置选项

27.5 重要组件 - 图2

27.5.4 kube-controller-manager

提供控制器服务,监视集群的状态,一旦不满足状态则采取操作,让状态恢复正常,常见的控制器包括:

·复制(replication)控制器:确保指定Pod同时存在指定数目的实例;

·端点(endpoint)控制器:负责Endpoints对象的创建,更新;

·节点(Node)控制器:负责节点的发现,管理和监控;

·命名空间(namespace)控制器:响应对命名空间的操作,如创建、删除等;

·服务账户(ServiceAccounts)控制器:管理命名空间中的ServiceAccount,确保默认账户存在于每个正常的命名空间中。

可以通过kube-controller-manager-h命令查看支持的参数选项,其中比较重要的配置选项见表27-3。

表27-3 kube-controller-manager配置选项

27.5 重要组件 - 图3

27.5.5 kubelet

kubelet是Node节点上最重要的工作程序,它是负责具体干活的,将给定的Pod运行在自己负责的节点上。

如果kubelet出现故障,则Kubernetes将用人工使该Node变得不可用。因此,在生产环节中推荐对kubelet进程进行监控,并通过诸如supervisord这样的软件来及时重启故障的进程。

另外,一般要通过—system-reserved和—kube-reserved参数为系统和Kubernetes组件预留出运行资源,避免耗尽后让节点挂掉。

可以通过kubelet-h命令查看支持的参数选项,其中比较重要的配置选项见表27-4。

表27-4 kubelet配置选项

27.5 重要组件 - 图4

27.5 重要组件 - 图5

27.5.6 kube-proxy

kube-proxy会监听在每一个Node节点上,负责把对应服务端口来的通信映射给后端对应的Pod。简单的说,它既是一个NAT(支持TCP和UDP),同时也有负载均衡(目前仅支持TCP)的功能。

例如,服务test-service定义服务端口为80,实际映射到大量Pod的8080端口上:


  1. {
  2. "kind": "Service",
  3. "apiVersion": "v1",
  4. "metadata": {
  5. "name": "test-service"
  6. },
  7. "spec": {
  8. "selector": {
  9. "app": "webapp"
  10. },
  11. "ports": [
  12. {
  13. "protocol": "TCP",
  14. "port": 80,
  15. "targetPort": 8080
  16. }
  17. ]
  18. }
  19. }

则kube-proxy会自动配置本地的iptables rales规则,一旦有网包(client)想访问服务的80端口,将到达的网包转发到某个绑定Pod的8080端口。在1.2.0版本开始,kube-proxy已经默认完全通过iptables来配置对应的NAT转发过程,自身不再参与转发过程,如图27-4所示。

27.5 重要组件 - 图6

图27-4 kube-proxy运行机制

kube-proxy默认采用轮询的负载均衡算法,并且支持亲和性。例如如果配置service.spec.sessionAffinity为ClientIP,则同一个客户端发过来的多个请求会转发给同一个后端的Pod,保证了会话一致性。具体实现上,在早期版本中采用用户态的程序来转发,现在已经逐渐转换到基于Linux Iptables的更高效转发机制。

可以通过kube-proxy-h命令查看支持的参数选项,其中比较重要的配置选项参见表27-5。

表27-5 kube-proxy配置选项

27.5 重要组件 - 图7