Kubernetes进阶实战(第2版)
上QQ阅读APP看书,第一时间看更新

1.2 Kubernetes基础

微服务的出现与发展促进了容器化技术的广泛应用,以Docker为代表的容器技术定义了新的标准化交付方式,而以Kubernetes为代表的容器编排系统则为规模化、容器化的微服务应用的落地提供了坚实基础和根本保障。Kubernetes是一种可自动实施Linux容器编排的开源平台,支持在物理机和虚拟机集群上调度和运行容器,为用户提供了一个极为便捷、有效的容器管理平台,可帮助用户省去应用容器化过程中许多需要手动进行的部署和扩展操作。

Kubernetes(希腊语,意为“舵手”或“飞行员”)又称k8s,或者简称为kube,由Joe Beda、Brendan Burns和Craig McLuckie创立,而后Google的其他几位工程师(包括Brian Grant和Tim Hockin等)加盟共同研发,并由Google在2014年首次对外发布。Google是最早研发Linux容器技术的企业之一(创建CGroups),目前,Google每周会基于内部平台Borg启用超过20亿个容器,而Kubernetes的研发和设计都深受该内部平台的影响,事实上,Kubernetes的许多顶级贡献者之前也是Borg系统的开发者。

1.2.1 Kubernetes集群概述

Kubernetes是一个跨多主机的容器编排平台,它使用共享网络将多个主机(物理服务器或虚拟机)构建成统一的集群。其中,一个或少量几个主机运行为Master(主节点),作为控制中心负责管理整个集群系统,余下的所有主机运行为Worker Node(工作节点),这些工作节点使用本地和外部资源接收请求并以Pod(容器集)形式运行工作负载。图1-6为Kubernetes集群工作模式示意图。

图1-6 Kubernetes集群

▪Master是集群的网关和中枢,负责诸如为用户和客户端暴露API、确保各资源对象不断地逼近或符合用户期望的状态、以最优方式调度工作负载,以及编排其他组件之间的通信等任务,它是各类客户端访问集群的唯一入口,肩负Kubernetes系统上大多数集中式管控逻辑。单个Master节点即可完成其所有功能,但出于冗余及负载均衡等目的,生产环境中通常需要协同部署多个此类主机。Master节点类似于蜂群中的蜂王。

▪Worker Node(以下简称Node)负责接收来自Master的工作指令并相应创建或销毁Pod对象,以及调整网络规则以合理完成路由和转发流量等任务,是Kubernetes集群的工作节点。理论上讲,Node可以是任何形式的计算设备,负责提供CPU、内存和存储等计算和存储资源,不过Master会统一将其抽象为Node对象进行管理。Node类似于蜂群中的工蜂,在生产环境中,通常数量众多。

概括来说,Kubernetes将所有工作节点的资源集结在一起形成一台更加强大的“服务器”,其计算和存储接口通过Master之上的API服务暴露,再由Master通过调度算法将客户端通过API提交的工作负载运行请求自动指派至某特定的工作节点以Pod对象的形式运行,且Master会自动处理因工作节点的添加、故障或移除等变动对Pod的影响,用户无须关心其应用究竟运行于何处。

由此可见,Kubernetes程序自身更像是构建在底层主机组成的集群之上的“云操作系统”或“云原生应用操作系统”,而容器是运行其上的进程,但Kubernetes要通过更高级的抽象Pod来运行容器,以便于处理那些具有“超亲密”关系的容器化进程,这些进程必须运行于底层的同一主机之上。因此,Pod类似于单机操作系统上的“进程组”,它包含一到多个容器,却是Kubernetes上的最小调度单元,因而同一Pod内的容器必须运行于同一工作节点之上,如图1-7所示。

图1-7 Kubernetes Pod

不过,Kubernetes的功能并不限于简单的容器调度,其本质是“以应用为中心”的现代应用基础设施,它通过管理各种基础支撑类服务(例如消息队列、集群存储系统、服务发现、数据处理框架以及负载均衡器等)将各种传统中间件“下沉”至自身内部,并经由声明式API向上层应用暴露这些基础设施能力。Kubernetes实际上是一个Platform for Platform类型的项目,其根本目的在于方便基础设施工程师(或称为“容器团队”等)构建其他的平台系统,例如Service Mesh、PaaS或Serverless等。

有了这种声明式基础设施的支撑,在开发基于Kubernetes的云原生应用时,程序员可更好地集中精力于应用程序的业务本身而无须为程序中需要集成基础设施的能力而困扰。在运行应用时,用户也只需要通过API声明应用程序的终态,例如为Nginx应用运行6个实例、为myapp实例执行滚动更新等,Kubernetes自己便能完成后续的所有任务,包括确保应用本身的运行终态以及应用所依赖的所有底层基础设施能力的终态,比如路由策略、访问策略和存储需求等。

提示

声明式(declarative)编程和命令式(imperative)编程是两种相对的高级编程概念:前者着重于最终结果,如何达成结果则要依赖于给定语言的基础组件能力,程序员只需要指定做什么而非如何去做;后者称为过程式编程更合适,它需要由程序员指定做事情的具体步骤,更注重如何达成结果的过程。声明式编程常用于数据库和配置管理软件中,关系型数据库的SQL语言便是最典型的代表之一,而Kubernetes中声明式API的核心依赖是控制器组件。

Kubernetes在其RESTful风格的API中以资源形式抽象出多种概念以描述应用程序及其周边组件,这些程序及组件被统称为API对象,它们有特定的类型,例如Node、Namespace、Pod、Service和Deployment等。每个API对象都使用“名称”作为其唯一标识符,出于名称隔离与复用以及资源隔离的目的,Kubernetes使用“名称空间”为名称提供了作用域,并将大多数资源类型归属到名称空间级别。

运行应用的请求需要以配置清单(manifest)格式提交给Kubernetes API进行,大多数资源对象包含元数据(例如标签和注释)、所需状态(也称为期望状态或终态)和观察状态(也称为当前状态)等信息。Kubernetes支持JSON或YAML编码的配置清单,由API服务器通过HTTP/HTTPS协议接收配置清单并存储于etcd中,查询请求的结果也将以JSON序列化格式返回,同时支持更高效的Protobuf格式。下面是用于描述API对象的常用配置清单的框架,其意义将在后面的章节予以介绍。


apiVersion: …    # 资源对象所属的API群组及版本
kind: …          # 资源类型
metadata:        # 资源对象的原数据
  …
spec:            # 所需状态
  …

上述配置清单是基于Kubernetes API声明式编程接口的配置代码,读者需要掌握API资源类型的定义格式与使用方式后才能灵活使用,难度系数较高。为了平缓初学者的入门曲线,Kubernetes也支持在命令行工具kubectl中以命令式语句提交运行请求。

1.2.2 Kubernetes集群架构

Kubernetes属于典型的Server-Client形式的二层架构,在程序级别,Master主要由API Server(kube-apiserver)、Controller-Manager(kube-controller-manager)和Scheduler(kube-scheduler)这3个组件,以及一个用于集群状态存储的etcd存储服务组成,它们构成整个集群的控制平面;而每个Node节点则主要包含kubelet、kube-proxy及容器运行时(Docker是最为常用的实现)3个组件,它们承载运行各类应用容器。各组件如图1-8中的粗体部分组件所示。

图1-8 Kubernetes系统组件

1. Master组件

Master组件是集群的“脑力”输出者,它维护有Kubernetes的所有对象记录,负责持续管理对象状态并响应集群中各种资源对象的管理操作,以及确保各资源对象的实际状态与所需状态相匹配。控制平面的各组件支持以单副本形式运行于单一主机,也能够将每个组件以多副本方式同时运行于多个主机上,提高服务可用级别。控制平面各组件及其主要功能如下。

(1)API Server

API Server是Kubernetes控制平面的前端,支持不同类型应用的生命周期编排,包括部署、缩放和滚动更新等。它还是整个集群的网关接口,由kube-apiserver守护程序运行为服务,通过HTTP/HTTPS协议将RESTful API公开给用户,是发往集群的所有REST操作命令的接入点,用于接收、校验以及响应所有的REST请求,并将结果状态持久存储于集群状态存储系统(etcd)中。

(2)集群状态存储

Kubernetes集群的所有状态信息都需要持久存储于存储系统etcd中。etcd是由CoreOS基于Raft协议开发的分布式键值存储,可用于服务发现、共享配置以及一致性保障(如数据库主节点选择、分布式锁等)。显然,在生产环境中应该以etcd集群的方式运行以确保其服务可用性,并需要制定周密的备份策略以确保数据安全可靠。

etcd还为其存储的数据提供了监听(watch)机制,用于监视和推送变更。API Server是Kubernetes集群中唯一能够与etcd通信的组件,它封装了这种监听机制,并借此同其他各组件高效协同。

(3)控制器管理器

控制器负责实现用户通过API Server提交的终态声明,它通过一系列操作步骤驱动API对象的当前状态逼近或等同于期望状态。Kubernetes提供了驱动Node、Pod、Server、Endpoint、ServiceAccount和Token等数十种类型API对象的控制器。从逻辑上讲,每个控制器都是一个单独的进程,但是为了降低复杂性,它们被统一编译进单个二进制程序文件kube-controller-manager(即控制器管理器),并以单个进程运行。

(4)调度器

Kubernetes系统上的调度是指为API Server接收到的每一个Pod创建请求,并在集群中为其匹配出一个最佳工作节点。kube-scheduler是默认调度器程序,它在匹配工作节点时的考量因素包括硬件、软件与策略约束,亲和力与反亲和力规范以及数据的局部性等特征。

2. Node组件

Node组件是集群的“体力”输出者,因而一个集群通常会有多个Node以提供足够的承载力来运行容器化应用和其他工作负载。每个Node会定期向Master报告自身的状态变动,并接受Master的管理。

(1)kubelet

kubelet是Kubernetes中最重要的组件之一,是运行于每个Node之上的“节点代理”服务,负责接收并执行Master发来的指令,以及管理当前Node上Pod对象的容器等任务。它支持从API Server以配置清单形式接收Pod资源定义,或者从指定的本地目录中加载静态Pod配置清单,并通过容器运行时创建、启动和监视容器。

kubelet会持续监视当前节点上各Pod的健康状态,包括基于用户自定义的探针进行存活状态探测,并在任何Pod出现问题时将其重建为新实例。它还内置了一个HTTP服务器,监听TCP协议的10248和10250端口:10248端口通过/healthz响应对kubelet程序自身的健康状态进行检测;10250端口用于暴露kubelet API,以验证、接收并响应API Server的通信请求。

(2)容器运行时环境

Pod是一组容器组成的集合并包含这些容器的管理机制,它并未额外定义进程的边界或其他更多抽象,因此真正负责运行容器的依然是底层的容器运行时。kubelet通过CRI(容器运行时接口)可支持多种类型的OCI容器运行时,例如docker、containerd、CRI-O、runC、fraki和Kata Containers等。

(3)kube-proxy

kube-proxy也是需要运行于集群中每个节点之上的服务进程,它把API Server上的Service资源对象转换为当前节点上的iptables或(与)ipvs规则,这些规则能够将那些发往该Service对象ClusterIP的流量分发至它后端的Pod端点之上。kube-proxy是Kubernetes的核心网络组件,它本质上更像是Pod的代理及负载均衡器,负责确保集群中Node、Service和Pod对象之间的有效通信。

3. 核心附件

附件(add-ons)用于扩展Kubernetes的基本功能,它们通常运行于Kubernetes集群自身之上,可根据重要程度将其划分为必要和可选两个类别。网络插件是必要附件,管理员需要从众多解决方案中根据需要及项目特性选择,常用的有Flannel、Calico、Canal、Cilium和Weave Net等。KubeDNS通常也是必要附件之一,而Web UI(Dashboard)、容器资源监控系统、集群日志系统和Ingress Controller等是常用附件。

▪CoreDNS:Kubernetes使用定制的DNS应用程序实现名称解析和服务发现功能,它自1.11版本起默认使用CoreDNS——一种灵活、可扩展的DNS服务器;之前的版本中用到的是kube-dns项目,SkyDNS则是更早一代的解决方案。

▪Dashboard:基于Web的用户接口,用于可视化Kubernetes集群。Dashboard可用于获取集群中资源对象的详细信息,例如集群中的Node、Namespace、Volume、ClusterRole和Job等,也可以创建或者修改这些资源对象。

▪容器资源监控系统:监控系统是分布式应用的重要基础设施,Kubernetes常用的指标监控附件有Metrics-Server、kube-state-metrics和Prometheus等。

▪集群日志系统:日志系统是构建可观测分布式应用的另一个关键性基础设施,用于向监控系统的历史事件补充更详细的信息,帮助管理员发现和定位问题;Kubernetes常用的集中式日志系统是由ElasticSearch、Fluentd和Kibana(称之为EFK)组合提供的整体解决方案。

▪Ingress Controller:Ingress资源是Kubernetes将集群外部HTTP/HTTPS流量引入到集群内部专用的资源类型,它仅用于控制流量的规则和配置的集合,其自身并不能进行“流量穿透”,要通过Ingress控制器发挥作用;目前,此类的常用项目有Nginx、Traefik、Envoy、Gloo、kong及HAProxy等。

在这些附件中,CoreDNS、监控系统、日志系统和Ingress控制器基础支撑类服务是可由集群管理的基础设施,而Dashboard则是提高用户效率和体验的可视化工具,类似的项目还有polaris和octant等。