从零开始: 入门Kubernetes核心概念

2020-09-12
8

640?wx_fmt=jpeg

1、什么是 Kubernetesnode

Kubernetes,从官方网站上能够看到,它是一个工业级的容器编排平台。Kubernetes 这个单词是希腊语,它的中文翻译是"舵手"或者"飞行员"。在一些常见的资料中也会看到"ks"这个词,也就是"K8s",它是经过将8个字母"ubernete"替换为"8"而致使的一个缩写。nginx

Kubernetes 为何要用"舵手"来命名呢?你们能够看一下这张图:sql

640?wx_fmt=png

这是一艘载着一堆集装箱的轮船,轮船在大海上运着集装箱奔波,把集装箱送到它们该去的地方。咱们以前其实介绍过一个概念叫作 container,container 这个英文单词也有另外的一个意思就是"集装箱"。Kubernetes 也就借着这个寓意,但愿成为运送集装箱的一个轮船,来帮助咱们管理这些集装箱,也就是管理这些容器。后端

这个就是为何会选用 Kubernetes 这个词来表明这个项目的缘由。更具体一点地来讲:Kubernetes 是一个自动化的容器编排平台,它负责应用的部署、应用的弹性以及应用的管理,这些都是基于容器的。api

2、Kubernetes 有以下几个核心的功能网络

  • 服务的发现与负载的均衡;架构

  • 容器的自动装箱,咱们也会把它叫作 scheduling,就是“调度”,把一个容器放到一个集群的某一个机器上,Kubernetes 会帮助咱们去作存储的编排,让存储的声明周期与容器的生命周期能有一个链接;app

  • Kubernetes 会帮助咱们去作自动化的容器的恢复。在一个集群中,常常会出现宿主机的问题或者说是 OS 的问题,致使容器自己的不可用,Kubernetes 会自动地对这些不可用的容器进行恢复;负载均衡

  • Kubernetes 会帮助咱们去作应用的自动发布与应用的回滚,以及与应用相关的配置密文的管理;分布式

  • 对于 job 类型任务,Kubernetes 能够去作批量的执行;

  • 为了让这个集群、这个应用更富有弹性,Kubernetes 也支持水平的伸缩。

下面,咱们但愿以三个例子跟你们更切实地介绍一下 Kubernetes 的能力。

一、调度

Kubernetes 能够把用户提交的容器放到 Kubernetes 管理的集群的某一台节点上去。Kubernetes 的调度器是执行这项能力的组件,它会观察正在被调度的这个容器的大小、规格。

好比说它所须要的 CPU以及它所须要的 memory,而后在集群中找一台相对比较空闲的机器来进行一次 placement,也就是一次放置的操做。在这个例子中,它可能会把红颜色的这个容器放置到第二个空闲的机器上,来完成一次调度的工做。

640?wx_fmt=png

二、自动修复

Kubernetes 有一个节点健康检查的功能,它会监测这个集群中全部的宿主机,当宿主机自己出现故障,或者软件出现故障的时候,这个节点健康检查会自动对它进行发现。

下面 Kubernetes 会把运行在这些失败节点上的容器进行自动迁移,迁移到一个正在健康运行的宿主机上,来完成集群内容器的一个自动恢复。

640?wx_fmt=png

三、水平伸缩

Kubernetes 有业务负载检查的能力,它会监测业务上所承担的负载,若是这个业务自己的 CPU 利用率太高,或者响应时间过长,它能够对这个业务进行一次扩容。

好比说在下面的例子中,黄颜色的过分忙碌,Kubernetes 就能够把黄颜色负载从一份变为三份。接下来,它就能够经过负载均衡把原来打到第一个黄颜色上的负载平均分到三个黄颜色的负载上去,以此来提升响应的时间。

640?wx_fmt=png

以上就是 Kubernetes 三个核心能力的简单介绍。

3、Kubernetes 的架构

Kubernetes 架构是一个比较典型的二层架构和server-client架构。Master做为中央的管控节点,会去与Node进行一个链接。

全部UI的、clients、这些user侧的组件,只会和Master进行链接,把但愿的状态或者想执行的命令下发给Master,Master会把这些命令或者状态下发给相应的节点,进行最终的执行。

640?wx_fmt=png

Kubernetes的Master包含四个主要的组件:

  • API Server、Controller、Scheduler 以及 etcd。

以下图所示:

640?wx_fmt=png

  • API Server:顾名思义是用来处理 API 操做的,Kubernetes 中全部的组件都会和 API Server 进行链接,组件与组件之间通常不进行独立的链接,都依赖于 API Server 进行消息的传送;

  • Controller:是控制器,它用来完成对集群状态的一些管理。好比刚刚咱们提到的两个例子之中,第一个自动对容器进行修复、第二个自动进行水平扩张,都是由 Kubernetes 中的 Controller 来进行完成的;

  • Scheduler:是调度器,“调度器”顾名思义就是完成调度的操做,就是咱们刚才介绍的第一个例子中,把一个用户提交的 Container,依据它对 CPU、对 memory 请求大小,找一台合适的节点,进行放置;

  • etcd:是一个分布式的一个存储系统,API Server 中所须要的这些原信息都被放置在 etcd 中,etcd 自己是一个高可用系统,经过 etcd 保证整个 Kubernetes 的 Master 组件的高可用性。

咱们刚刚提到的 API Server,它自己在部署结构上是一个能够水平扩展的一个部署组件;Controller 是一个能够进行热备的一个部署组件,它只有一个 active,它的调度器也是相应的,虽然只有一个 active,可是能够进行热备。

Kubernetes 的架构:Node

Kubernetes 的 Node 是真正运行业务负载的,每一个业务负载会以 Pod 的形式运行。等一下我会介绍一下 Pod 的概念。一个 Pod 中运行的一个或者多个容器,真正去运行这些 Pod 的组件的是叫作 kubelet,也就是 Node 上最为关键的组件,它经过 API Server 接收到所须要 Pod 运行的状态,而后提交到咱们下面画的这个 Container Runtime 组件中。

640?wx_fmt=png

在 OS 上去建立容器所须要运行的环境,最终把容器或者 Pod 运行起来,也须要对存储跟网络进行管理。Kubernetes 并不会直接进行网络存储的操做,他们会靠 Storage Plugin 或者是网络的 Plugin 来进行操做。用户本身或者云厂商都会去写相应的 Storage Plugin 或者 Network Plugin,去完成存储操做或网络操做。

在 Kubernetes 本身的环境中,也会有 Kubernetes 的 Network,它是为了提供 Service network 来进行搭网组网的。(等一下咱们也会去介绍“service”这个概念。)真正完成 service 组网的组件的是 Kube-proxy,它是利用了 iptable 的能力来进行组建 Kubernetes 的 Network,就是 cluster network,以上就是 Node 上面的四个组件。

Kubernetes的Node并不会直接和user进行interaction,它的interaction只会经过 Master。而User是经过Master向节点下发这些信息的。

Kubernetes每一个Node上,都会运行咱们刚才提到的这几个组件。

下面咱们以一个例子再去看一下Kubernetes架构中的这些组件,是如何互相进行interaction的。

640?wx_fmt=png

用户能够经过 UI 或者 CLI 提交一个 Pod 给 Kubernetes 进行部署,这个 Pod 请求首先会经过 CLI 或者 UI 提交给 Kubernetes API Server,下一步 API Server 会把这个信息写入到它的存储系统 etcd,以后 Scheduler 会经过 API Server 的 watch 或者叫作 notification 机制获得这个信息:有一个 Pod 须要被调度。

这个时候 Scheduler 会根据它的内存状态进行一次调度决策,在完成此次调度以后,它会向 API Server report 说:“OK!这个 Pod 须要被调度到某一个节点上。”

这个时候 API Server 接收到此次操做以后,会把此次的结果再次写到 etcd 中,而后 API Server 会通知相应的节点进行此次 Pod 真正的执行启动。相应节点的 kubelet 会获得这个通知,kubelet 就会去调 Container runtime 来真正去启动配置这个容器和这个容器的运行环境,去调度 Storage Plugin 来去配置存储,network Plugin 去配置网络。

这个例子咱们能够看到:这些组件之间是如何相互沟通相互通讯,协调来完成一次Pod的调度执行操做的。

4、Kubernetes 的核心概念与它的 API

核心概念

第一个概念:Pod

Pod 是 Kubernetes 的一个最小调度以及资源单元。用户能够经过 Kubernetes 的 Pod API 生产一个 Pod,让 Kubernetes 对这个 Pod 进行调度,也就是把它放在某一个 Kubernetes 管理的节点上运行起来。一个 Pod 简单来讲是对一组容器的抽象,它里面会包含一个或多个容器。

好比像下面的这幅图里面,它包含了两个容器,每一个容器能够指定它所须要资源大小。好比说,一个核一个 G,或者说 0.5 个核,0.5 个 G。

固然在这个 Pod 中也能够包含一些其余所须要的资源:好比说咱们所看到的 Volume 卷这个存储资源;好比说咱们须要 100 个 GB 的存储或者 20GB 的另一个存储。

640?wx_fmt=png

在 Pod 里面,咱们也能够去定义容器所须要运行的方式。好比说运行容器的 Command,以及运行容器的环境变量等等。Pod 这个抽象也给这些容器提供了一个共享的运行环境,它们会共享同一个网络环境,这些容器能够用 localhost 来进行直接的链接。而 Pod 与 Pod 之间,是互相有 isolation 隔离的。

第二个概念:Volume

Volume 就是卷的概念,它是用来管理 Kubernetes 存储的,是用来声明在 Pod 中的容器能够访问文件目录的,一个卷能够被挂载在 Pod 中一个或者多个容器的指定路径下面。

而 Volume 自己是一个抽象的概念,一个 Volume 能够去支持多种的后端的存储。好比说 Kubernetes 的 Volume 就支持了不少存储插件,它能够支持本地的存储,能够支持分布式的存储,好比说像 ceph,GlusterFS ;它也能够支持云存储,好比说阿里云上的云盘、AWS 上的云盘、Google 上的云盘等等。

640?wx_fmt=png

第三个概念:Deployment

Deployment 是在 Pod 这个抽象上更为上层的一个抽象,它能够定义一组 Pod 的副本数目、以及这个 Pod 的版本。通常你们用 Deployment 这个抽象来作应用的真正的管理,而 Pod 是组成 Deployment 最小的单元。

Kubernetes 是经过 Controller,也就是咱们刚才提到的控制器去维护 Deployment 中 Pod 的数目,它也会去帮助 Deployment 自动恢复失败的 Pod。

好比说我能够定义一个 Deployment,这个 Deployment 里面须要两个 Pod,当一个 Pod 失败的时候,控制器就会监测到,它从新把 Deployment 中的 Pod 数目从一个恢复到两个,经过再去新生成一个 Pod。经过控制器,咱们也会帮助完成发布的策略。好比说进行滚动升级,进行从新生成的升级,或者进行版本的回滚。

640?wx_fmt=png

第四个概念:Service

Service 提供了一个或者多个 Pod 实例的稳定访问地址。

好比在上面的例子中,咱们看到:一个 Deployment 可能有两个甚至更多个彻底相同的 Pod。对于一个外部的用户来说,访问哪一个 Pod 其实都是同样的,因此它但愿作一次负载均衡,在作负载均衡的同时,我只想访问某一个固定的 VIP,也就是 Virtual IP 地址,而不但愿得知每个具体的 Pod 的 IP 地址。

咱们刚才提到,这个 pod 自己可能 terminal go(终止),若是一个 Pod 失败了,可能会换成另一个新的。

对一个外部用户来说,提供了多个具体的 Pod 地址,这个用户要不停地去更新 Pod 地址,当这个 Pod 再失败重启以后,咱们但愿有一个抽象,把全部 Pod 的访问能力抽象成一个第三方的一个 IP 地址,实现这个的 Kubernetes 的抽象就叫 Service。

实现 Service 有多种方式,Kubernetes 支持 Cluster IP,上面咱们讲过的 kuber-proxy 的组网,它也支持 nodePort、 LoadBalancer 等其余的一些访问的能力。

640?wx_fmt=png

第五个概念:Namespace

Namespace 是用来作一个集群内部的逻辑隔离的,它包括鉴权、资源管理等。Kubernetes 的每一个资源,好比刚才讲的 Pod、Deployment、Service 都属于一个 Namespace,同一个 Namespace 中的资源须要命名的惟一性,不一样的 Namespace 中的资源能够重名。

Namespace 一个用例,好比像在阿里巴巴,咱们内部会有不少个 business units,在每个 business units 之间,但愿有一个视图上的隔离,而且在鉴权上也不同,在 cuda 上面也不同,咱们就会用 Namespace 来去给每个 BU 提供一个他所看到的这么一个看到的隔离的机制。

640?wx_fmt=png

Kubernetes 的 API

下面咱们介绍一下 Kubernetes 的 API 的基础知识。从 high-level 上看,Kubernetes API 是由 HTTP+JSON 组成的:用户访问的方式是 HTTP,访问的 API 中 content 的内容是 JSON 格式的。

640?wx_fmt=png

下面有个例子:好比说,对于这个 Pod 类型的资源,它的 HTTP 访问的路径,就是 API,而后是 apiVesion: V1, 以后是相应的 Namespaces,以及 Pods 资源,最终是 Podname,也就是 Pod 的名字。

640?wx_fmt=png

若是咱们去提交一个 Pod,或者 get 一个 Pod 的时候,它的 content 内容都是用 JSON 或者是 YAML 表达的。上图中有个 yaml 的例子,在这个 yaml file 中,对 Pod 资源的描述也分为几个部分。

第一个部分,通常来说会是 API 的 version。好比在这个例子中是 V1,它也会描述我在操做哪一个资源;好比说个人 kind 若是是 pod,在 Metadata 中,就写上这个 Pod 的名字;好比说 nginx,咱们也会给它打一些 label,咱们等下会讲到 label 的概念。在 Metadata 中,有时候也会去写 annotation,也就是对资源的额外的一些用户层次的描述。

比较重要的一个部分叫作 Spec,Spec 也就是咱们但愿 Pod 达到的一个预期的状态。好比说它内部须要有哪些 container 被运行;好比说这里面有一个 nginx 的 container,它的 image 是什么?它暴露的 port 是什么?

当咱们从 Kubernetes API 中去获取这个资源的时候,通常来说在 Spec 下面会有一个项目叫 status,它表达了这个资源当前的状态;好比说一个 Pod 的状态多是正在被调度、或者是已经 running、或者是已经被 terminates,就是被执行完毕了。

刚刚在 API 之中,咱们讲了一个比较有意思的 metadata 叫作“label”,这个 label 能够是一组 KeyValuePair。

好比下图的第一个 pod 中,label 就多是一个 color 等于 red,即它的颜色是红颜色。固然你也能够加其余 label,好比说 size: big 就是大小,定义为大的,它能够是一组 label。

这些 label 是能够被 selector,也就是选择器所查询的。这个能力实际上跟咱们的 sql 类型的 select 语句是很是类似的,好比下图中的三个 Pod 资源中,咱们就能够进行 select。name color 等于 red,就是它的颜色是红色的,咱们也能够看到,只有两个被选中了,由于只有他们的 label 是红色的,另一个 label 中写的 color 等于 yellow,也就是它的颜色是黄色,是不会被选中的。

640?wx_fmt=png

经过 label,kubernetes 的 API 层就能够对这些资源进行一个筛选,那这些筛选也是 kubernetes 对资源的集合所表达默认的一种方式。

例如说,咱们刚刚介绍的 Deployment,它多是表明一组的 Pod,它是一组 Pod 的抽象,一组 Pod 就是经过 label selector 来表达的。固然咱们刚才讲到说 service 对应的一组 Pod,就是一个 service 要对应一个或者多个的 Pod,来对它们进行统一的访问,这个描述也是经过 label selector 来进行 select 选取的一组 Pod。

因此能够看到 label 是一个很是核心的 kubernetes API 的概念,咱们在接下来的课程中也会着重地去讲解和介绍 label 这个概念,以及如何更好地去使用它。

5、以一个 demo 结尾

最后一部分,我想以一个例子来结束,让你们跟我一块儿来尝试一个 kubernetes,在尝试 Kubernetes 以前,我但愿你们能在本机上安装一下 Kubernetes,安装一个 Kubernetes 沙箱环境。

安装这个沙箱环境,主要有三个步骤:

  • 首先须要安装一个虚拟机,来在虚拟机中启动 Kubernetes。咱们会推荐你们利用 virtualbox 来做为虚拟机的运行环境;安装:

  • VirtualBox:

  • https://www.virtualbox.org/wiki/Downloads

  • 其次咱们须要在虚拟机中启动 Kubernetes,Kubernetes 有一个很是有意思的项目,叫 minikube,也就是启动一个最小的 local 的 Kubernetes 的一个环境。

minikube 咱们推荐使用下面写到的阿里云的版本,它和官方 minikube 的主要区别就是把 minikube 中所须要的 Google 上的依赖换成国内访问比较快的一些镜像,这样就方便了你们的安装工做;安装:

  • MiniKube(中国版): 

  • https://yq.aliyun.com/articles/221687

  • 最后在安装完 virtualbox 和 minikube 以后,你们能够对 minikube 进行启动,也就是下面这个命令。

启动命令:minikube start —vm-driver virtualbox

若是你们不是 Mac 系统,其余操做系统请访问下面这个连接,查看其它操做系统如何安装 minikube 沙箱环境。

  • https://kubernetes.io/docs/tasks/tools/install-minikube/

当你们安装好以后,我会跟你们一块儿作一个例子,来作三件事情:

640?wx_fmt=png

第一步,咱们提交一个 nginx 的 Deployment,而后对这个 Deployment 进行一次版本升级,也就是改变它中间 Pod 的版本。最后咱们也会尝试对 nginx 进行一次扩容,进行一次水平的伸缩,下面就让你们一块儿跟我来尝试这三个操做吧。

首先,咱们先看一下 minikube 的 status,能够看到 kubelet master 和 kubectl 都是配置好的。

640?wx_fmt=png

下一步咱们利用 kubectl 来看一下这个集群中节选的状态,能够看到这个master 的节点已是running状态:

640?wx_fmt=png

咱们就以这个为节点,下面咱们尝试去看一下如今集群中 Deployment 这个资源:

640?wx_fmt=png

能够看到集群中没有任何的 Deployment,咱们能够利用 watch 这个语义去看集群中 Deployment 这个资源的变化状况。

下面咱们去作刚才想要的三个操做:第一个操做是去建立一个 Deployment。能够看到下面第一个图,这是一个 API 的 content,它的 kind 是 Deployment,name 是 nginx-deployment, 有图中它的 replicas 数目是2,它的镜像版本是 1.7.9。

640?wx_fmt=png

咱们下面仍是回到 kubectl 这个 commnd 来执行此次 Deployment 的真正的操做。咱们能够看到一个简单的操做,就会去让 Deployment 不停地生成副本。

640?wx_fmt=png

Deployment 副本数目是 2 个,下面也能够 describe 一下如今的 Deployment 的状态。咱们知道以前是没有这个 Deployment 的,如今咱们去 describe 这个 nginx-deployment。

下图中能够看到:有一个 nginx-deployment 已经被生成了,它的 replicas 数目也是咱们想要的、selector 也是咱们想要的、它的 image 的版本也是 1.7.9。还能够看到,里面的 deployment-controller 这种版本控制器也是在管理它的生成。

640?wx_fmt=png

下面咱们去升级这个 Deployment 版本,首先下载另一个 yaml 文件 deployment-update.yaml,能够看到这里面的 image 自己的版本号从 1.7.9 升级到 1.8。

640?wx_fmt=png

接下来咱们从新 apply 新的 deployment-update 这个 yaml 文件。

能够看到,在另外一边的屏幕上显示出了这个 Deployment 升级的一些操做,最终它的 up-to-date 值从 0 变成了 2,也就是说全部的容器都是最新版本的,全部的 Pod 都是最新版本的。咱们也能够 discribe 具体去看一下是否是全部 Pod 的版本都被更新了,能够看到这个 image 的版本由 1.7.9 真正更新到了 1.8。

最后,咱们也能够看到  controller 又执行了几回新的操做,这个控制器维护了整个 Deployment 和 Pod 状态。

640?wx_fmt=png

最后咱们演示一下给 Deployment 作水平扩张,下载另外一个 yaml 文件 deployment-scale.yaml,这里面的 replicas 数目已经从 2 改为了 4。

640?wx_fmt=png

回到最开始的窗口,用 kubectl 去 apply 这个新的 deployment-scale.yaml 文件,在另一个窗口上能够看到,当咱们执行了 deployment-scale 操做以后,它的容器 Pod 数目从 2 变成了 4。咱们能够再一次 describ 一下当前集群中的 deployment 的状况,能够看到它的 replicas 的数目从 2 变到了 4,同时也能够看到 controller 又作了几回新的操做,这个 scale up 成功了。

640?wx_fmt=png

最后,让咱们利用 delete 操做把咱们刚才生成的 Deployment 给删除掉。kubectl delete deployment,也是刚才咱们自己的 deployment name,当咱们把它删除掉以后,咱们今天全部的操做就完成了。

咱们再去从新 get 这个 Deployment,也会显示这个资源再也不存在,这个集群又回到了最开始干净的状态。

640?wx_fmt=png

本文总结

本文咱们关注了 Kubernetes 的核心概念以及 Kubernetes 的架构设计,主要有如下内容:

  • Kubernetes 是一个自动化的容器编排平台,它负责应用的部署、应用的弹性以及应用的管理,这些都是基于容器的;

  • Kubernetes 架构是一个比较典型的二层架构和 server-client 架构;

文章做者:李响,阿里巴巴资深技术专家、CNCF 9个 TCO 之一 。

更多架构师技术关知识请参考“架构师技术全店资料打包汇总(全)”电子书(32本技术资料打包汇总、详解目录和内容请经过“阅读原文”获取)。

舒适提示:

请识别二维码关注公众号,点击原文连接获取架构师技术全店资料打包汇总(全)电子书资料详情

640?wx_fmt=jpeg

640?wx_fmt=gif&wxfrom=5&wx_lazy=1

评论