Kubernetes起源于Google的Borg系统。Borg是在2003年开发的一个大规模集群管理系统。它支撑Google数千个应用程序(十万个应用程序)。
运行时,Kubernetes指定了CRI,网络指定了CNI,存储指定了CSI,各种设备通过device plugin 接入。总之,它就像一个钢筋混凝土的框架,至于最终的房间的设计都是交给第三方根据自己的业务场景去实现的。
Yaml是一种数据组织格式,非常强大。与JSON通过大括号的方法分级相比,Yaml采用了缩进的方式组织数据。Yaml文件支持三种数据结构,分别是散列表、数组及复合结构。
声明式API是相对于命令式API来说的。所谓的声明式API是指只需要告诉机器最终结果,不用关心实现过程和细节,而命令式API则是一种面向过程的操作,需要告诉机器每一步应如何执行,才能达到最终目标。
声明式API是Kubernetes最重要的设计思想,通过Yaml或者json文件定义最终的资源形态,剩下的交给 Kubernetes去完成。Kubernetes获取用户提交的资源声明后,通过多个组件相互协作,最终满足用户定义的资源需求。
Kubernetes是容器管理系统,但是它并不是将单个容器当作管理单位的。容器的设计哲学是希望在一个容器里面只运行一个进程,那么针对这个进程的监控程序该如何部署,以及和这个进程强耦合的sidecar程序将如何去部署则变得复杂起来。Kubernetes创新地将多个容器组合到一起,产生一个新的资源管理单位,叫作Pod。Pod是Kubernetes调度和管理的最小单位,每个Pod都是由若干个容器组成,Pod共享网络命名空间和存储。
就是通过Pod的设计方式将多个紧密关联的容器共享网络、存储等资源,通过对Pod生命周期的管理,完成对一组容器的生命周期管理。
Service 和Endpoint
容器的地址不是固定的。如果集群内部的容器相互调用或者是被集群外部访问调用, Kubernetes提供了一种负载均衡和服务发现机制。Service是Kubernetes提供的一种负载均衡器,每个服务都有一个虚IP(headless Service除外),这个虚IP是固定不变的,实现方式可以是iptables或者ipvs,这个IP并非是绑定到某一个网卡上面,所以ping是不同的。
Kubernetes物理资源抽象
Kubernetes 将管理的物理资源抽象成指定的类型和对应的计量单位,如 CPU (millicores)、内存(B)、磁盘和GPU等。其中,CPU和内存是Kubernetes原生支持的,其他资源扩展可以通过device plugin方式加入。这些资源可以分为两种,一种是可压缩资源,譬如CPU,当Pod使用超过设置的limits值时,Pod中进程使用CPU会被限制,但不会被kill;另一种是将不可压缩资源当作资源,譬如内存。当资源不足时,先kill掉优先级低的Pod。在实际使用过程中,通过OOM分数值来实现,OOM分数值为0~1000。当然,磁盘也属于不可压缩的资源。
Kubernetes组件分析
Kubernetes 的节点包含两种角色:Master 节点和 Node 节点。Master 节点上面部署apiserver、scheduler、controllermanager(replication controller、node controller等), Node节点上面部署kubelet和proxy。当然也可以将它们部署到一起,只是生产环境通常不建议这样做。Kubernetes整体架构如图10-1所示。
Kubernetes API 接口主要分为组、版本和资源三层,接口层次如图10-2所示。对于“/apis/batch/v1/jobs”接口,batch是组,v1是版本,jobs是资源。Kubernetes的核心资源都放在“/api”接口下,扩展的接口放在“/apis”下。
Apiserver启动后会将每个版本的接口都注册到一个核心的路由分发器(Mux)中。当客户端请求到达Apiserver后,首先经过Authentication认证和Authorization授权。认证支持Basic、Token及证书认证等。授权目前默认使用的是RBAC。经过路由分发到指定的接口,为了兼容多个资源版本,请求的不同版本的资源类型会统一转化为一个内部资源类型,然后进入Admission准入控制和Validation资源校验,在准入控制采用插件机制,用户可以定义自己的注入控制器验证,并更改资源配置。资源校验主要是验证参数是否合法,必传参数是否齐备等。最后再转化到用户最初的资源版本,并保存到Etcd中。Apiserver请求处理流程图如图10-3所示。
其他容器管理平台
除了Kubernetes,还有其他一些容器管理平台,比如OpenShift、Rancher等管理平台。在之前的版本中,它们都独立开发了一套容器管理方案,但2018年后,无论是OpenShift,还是Rancher,都已经全面转向Kubernetes,把重点放到了Devops及Kubernetes集群管理等方面,容器的管理则全部交给Kubernetes。
Kubernetes的生态圈
第一个出场的就是Prometheus,结合cAdvisor和各种exporter采集器,Prometheus可以监控容器、主机及Kubernetes性能指标,并做到自动发现(不需要为每一个容器配置监控项),而且支持性能指标告警。
Prometheus 是一套开源的系统监控报警框架。它提供了多维度数据模型,每个数据指标都可以关联很多 label,这个和Kubernetes 的 label 思想一致,松耦合、高度自由定制数据维度。举例来说,每个容器的CPU指标都可以关联容器、Pod、容器所在主机、namespace等多个维度,那么在查询的时候可以根据这些 label自由关联,并且支持promsql,允许用户以类 sql 的方式查询指标。Prometheus 不仅提供了高效的本地时序数据存储,还可以支撑各种远端时序数据库,如OpenTSDB、InfluxDB等,极大地扩展了Prometheus的数据存储能力。
Prometheus采用拉取(PULL)的方式采集数据,这与采用上报(PUSH)的采集方式不同,拉取方式有以下几个特点:第一是拉取方式对于客户端没有感知,客户端只需要不断采集数据,既不用关心数据后续的处理,也不需要维护数据状态(哪些数据已经上报,哪些数据上报失败需要重试,还有哪些还未上报),可以做到更加简单。第二是增强了数据汇聚服务的可控性,数据的汇聚节点可以根据当前系统情况,调整汇聚的周期和数据量,避免大量客户端一起上报数据,压垮汇聚节点。
Filebeat
Filebeat 是一款由 Go 语言编写的具有高并发能力的日志采集插件。Filebeat 的工作原理如图11-5所示:其中,Harvester负责逐行读取文件,每个文件都对应一个Harvester,然后Harvester 将采集的数据发送到 Spooler,经过 Spooler 整合后发送到不同的后端,如Elasticsearch或者Kafka等。