本系列前三部分:

  • 适合 Kubernetes 初学者的一些实战练习 (一)
  • 适合 Kubernetes 初学者的一些实战练习 (二)
  • 适合 Kubernetes 初学者的一些实战练习 (三)

练习1 - Kubernetes pod 的自动 scale (水平自动伸缩)

​kubectl scale​​​ 命令用于程序在负载加重或缩小时进行 pod 扩容或缩小,本练习我们通过一个实际例子来观察 ​​scale​​命令到底能达到什么效果。

命令行创建一个 ​​deployment​​:


kubectl run jerry-nginx --image=nginx:1.12.2


适合 Kubernetes 初学者的一些实战练习 (四)_cloud-native

​kubectl get deploy​​ 查看刚刚创建的 deployment:

适合 Kubernetes 初学者的一些实战练习 (四)_云原生_02

自动被 deployment 创建的 pod:

kubectl get pod:

适合 Kubernetes 初学者的一些实战练习 (四)_nginx_03

使用下列命令查看生成的 deployment 明细:


kubectl get deployment jerry-nginx -o yaml


适合 Kubernetes 初学者的一些实战练习 (四)_云原生_04

适合 Kubernetes 初学者的一些实战练习 (四)_云原生_05

另一个有用的命令:


kubectl describe deployment jerry-nginx


适合 Kubernetes 初学者的一些实战练习 (四)_云原生_06

现在我们使用下面的命令对 deployment 进行水平扩展:


kubectl scale deployment jerry-nginx --replicas=3


适合 Kubernetes 初学者的一些实战练习 (四)_nginx_07


kubectl get pods -l run=jerry-nginx


下图这个 Age 为 15 分钟之前的是第一次创建 deployment 时生成的,其他两个 Age 为 1 分钟之前的是执行了 scale 命令后自动创建的。

适合 Kubernetes 初学者的一些实战练习 (四)_Kubernetes_08

选中一个才创建的 pod,查看其事件记录:


kubectl describe pod jerry-nginx-69fd9f6c4-8dpvb


适合 Kubernetes 初学者的一些实战练习 (四)_Kubernetes_09


kubectl get replicaset


得到自动创建的 replication set:

适合 Kubernetes 初学者的一些实战练习 (四)_Kubernetes_10

desired = 3 意思就是我们水平扩展时指定的参数 3.

即使手动删除一个 pod实例,replication set 又会很快自动创建一个新的:

适合 Kubernetes 初学者的一些实战练习 (四)_云原生_11

自动创建的新 pod:

适合 Kubernetes 初学者的一些实战练习 (四)_云原生_12

练习2 - Kubernetes 滚动升级(rolling update)特性体验

在 Kubernetes 上运行我们的应用,有什么收益?Kubernetes 可以帮助应用开发人员确保其开发出的应用程序以一种高可用的、可伸缩和容错的方式进行部署和运行。

换句话说,Kubernetes 环境的搭建,系统的配置,可以全部交给 Kubernetes 的管理员,而应用开发人员作为 Kubernetes 的消费者,只需要记住几个简单的 kubectl 命令,就能够轻松完成应用程序到 Kubernetes 上的部署,几乎不需付出额外的代价就能享受到 Kubernetes 作为一个平台给应用程序带来的上述非功能性的提升。

在本系列第三篇文章适合 Kubernetes 初学者的一些实战练习 (三)​ 我们已经接触了 Gardener, 一个开源的创建 Kubernetes 集群的解决方案:

适合 Kubernetes 初学者的一些实战练习 (四)_docker_13

我在 Gardener 上创建一个基于 Google Cloud Platform 的 Kubernetes 集群,取名jerry1204:

适合 Kubernetes 初学者的一些实战练习 (四)_docker_14

适合 Kubernetes 初学者的一些实战练习 (四)_Kubernetes_15

点击上图 Access 标签页里的 Dashboard(控制台)超链接,即可对这个 Kubernetes 集群进行操作。

适合 Kubernetes 初学者的一些实战练习 (四)_云原生_16

控制台里看到的 Kubernetes 集群工作节点信息和命令行 ​​kubectl get node -o wide​​ 看到的一致:

适合 Kubernetes 初学者的一些实战练习 (四)_云原生_17

使用命令行来运行 Docker Hub 上的一个镜像 i042416/ui5-nginx:


kubectl run jerry-ui5 --image=i042416/ui5-nginx


适合 Kubernetes 初学者的一些实战练习 (四)_nginx_18

这个命令行背后发生了很多事情。

首先,运行在 Kubernetes 上的应用程序,其高可用性,可伸缩性和容错性到底是通过 Kubernetes 什么机制保证的?

适合 Kubernetes 初学者的一些实战练习 (四)_nginx_19

答案是 pod。请单击上面 Kubernetes 的架构图,然后放大,能看到 node(节点)里包含了多个 pod,每个 pod 里又包含了多个容器。像它的中文含义(豆荚,飞机,航天器或船只上可与主体分离的分离仓)暗示的一样,pod 就是应用程序运行的载体,是 Kubernetes 的基本操作单元。整套 Kubernetes 系统的设计都是围绕着 pod 展开,例如 pod 的部署和运行,如何保证处于运行状态的 pod 总数量等于一个恒定值,如何将 pod 里应用提供的服务暴露给外部访问等等。

适合 Kubernetes 初学者的一些实战练习 (四)_云原生_20

回到我们之前的命令行,我们试着执行另一个命令 kubectl get pod,果然发现了一个 pod 被创建出来,诞生已经40秒了(Age = 40s)。

适合 Kubernetes 初学者的一些实战练习 (四)_nginx_21

用 describe 命令查看这个 pod 的明细:


kubectl describe pod jerry-ui5-6ffd46bb95-6bgpg


下图 Container ID 后面的 docker://说明这是一个 docker 容器,当然并不意味着 Kubernetes 只支持 Docker 这一种容器技术,比如 Kubernetes 还支持 CoreOS 的 Rocket。

适合 Kubernetes 初学者的一些实战练习 (四)_Kubernetes_22

describe 命名输出的 Events 区域揭示了一个 pod 从诞生到开始服役的生命周期状态跳转:


Scheduled->Pulling->Pulled->Created->Started


从每个状态的 from 字段也能看出很多信息。

  • Scheduled 状态的 from: default-scheduler.

Scheduler 是 Kubernetes 的组件之一,负责调度 pod 到合适的节点上。具体什么样的节点算合适,取决于 Kubernetes Scheduler 调度算法的实现。如果把Scheduler看成一个黑匣子,那么它的输入是 pod 和由多个节点组成的列表,输出是 Pod 和一个匹配节点的绑定。这个状态 message 显示的内容 ​​Successfully assigned XXX to shoot--jerrytest-jerry1204-worker-yamer-z1-XXX​​ 后面这个 shoot–jerrytest 开头的字符串就是 pod 被分配到的节点的名称。

后面几个状态的 from 字段都是 ​​kubelet,shoot--jerrytest-jerry1204-worker-yamer-z1-XXX​​,其中 kubelet 是 Kubernetes 节点上一个重要的模块,负责维护和管理运行于该节点上的所有容器,确保 pod 的运行状态与使用者期望一致。

在 Kubernetes web 控制台里也一样能看到这个处于运行状态的 pod:

适合 Kubernetes 初学者的一些实战练习 (四)_nginx_23

除了 pod 之外,Kubernetes 第二个重要的概念就是 deployment.

执行另一个命令 ​​kubectl get deploy​​,发现 kubectl run 命令除了生成一个 pod 外,还生成了一个 deployment.

从这个命令输出的 Desired, Current 和 Up-to-Date, Available 下面的数字,结合前面提到的 Kubernetes 里几乎所有的设计都是围绕着 pod 来展开这一指导思想,我们不难猜测出,这个生成的 deployment 也是为 pod 服务的。

适合 Kubernetes 初学者的一些实战练习 (四)_Kubernetes_24

实际上,Kubernetes 的初学者可以把 deployment 的主要职责理解成是保证 pod 的数量和健康。

在 Kubernetes 的世界里,我们不会直接和运行在 pod 里的 docker 容器打交道,而是通过 Kubernetes service 将 pod 里的应用提供的服务暴露给外界消费。

到目前为止,Kubernetes 集群上还没有任何和应用程序相关的 service 生成。命令 kubectl get svc 只返回了一个 Kubernetes 的标准服务。

适合 Kubernetes 初学者的一些实战练习 (四)_云原生_25

因此我们使用命令 kubectl expose 基于刚刚使用 kubectl run 生成的 deployment 创建一个service:


kubectl expose deployment jerry-ui5 --type=LoadBalancer --port=80 --target-port=80
一旦 expose 命令执行后,get svc 命令这次就返回了一个和 deployment 同名的 service,暴露给外界访问的 IP 地址为 35.205.230.209:


适合 Kubernetes 初学者的一些实战练习 (四)_docker_26

适合 Kubernetes 初学者的一些实战练习 (四)_nginx_27

于是,使用 url ​​35.205.230.209/webapp​​ 就能访问运行在 Kubernetes pod 里的 SAP UI5 应用了:

适合 Kubernetes 初学者的一些实战练习 (四)_Kubernetes_28

到目前为止我们的 SAP UI5 应用仅仅运行在 Kubernetes 集群上的一个工作节点的单个 pod 里,还没有感受到这个应用运行时的表现和之前运行在 Docker 容器里有什么差异。

我们现在就来尝试下 Kubernetes deployment 的水平扩展功能。在 Kubernetes 操作台里选中 deployment,从菜单里执行 Scale 命令,

适合 Kubernetes 初学者的一些实战练习 (四)_docker_29

设定新的 pod 的数量:下面截图的 3,意思是告诉这个 deployment,在命令执行完毕后,它必须要努力保证,在任何时候由它控制和监控的 pod 个数必须等于 3。

适合 Kubernetes 初学者的一些实战练习 (四)_nginx_30

当然这个控制台上的图形菜单在命令行里也存在对应的命令,我们后面会用到。

上图 OK 按钮点击后,再次执行 ​​kubectl get pod​​, 能观察到水平扩展执行之后,生成了两个新的 deployment,所以这次 get pod 命令总共返回了 3 个 pod,其中后两个 pod 从 Age 能看出是水平扩展执行之后刚刚创建的。

适合 Kubernetes 初学者的一些实战练习 (四)_Kubernetes_31

使用 kubectl describe 命令查看 deployment 的明细,在 Replicas 这个字段里看到这个 deployment 控制的 pod 的运行时明细:

3 desired | 3 updated | 3 total | 3 available | 0 unavailable

适合 Kubernetes 初学者的一些实战练习 (四)_docker_32

我们现在故意用 ​​kubectl delete​​ 删除一个 pod,再次查看,发生一个新的 pod 瞬间就自动生成了,处于运行状态的 pod 总数仍然为 3.

Kubernetes滚动升级(Rolling Update)特性体验

滚动升级是 Kubernetes 一大特色,顾名思义,这是一种平滑过渡的升级方式,通过逐个容器替代升级的方式,来实现无中断的服务升级。下图 deployment 的 describe 命令的输出,其中字段 StrategyType 字段表明 kubectl run 创建的 deployment 默认的升级方式就是滚动升级。

适合 Kubernetes 初学者的一些实战练习 (四)_nginx_33

我设计了这样一个简单的升级场景:我的 SAP UI5 应用 ​​1.0​​​ 版本同时运行在一个 Kubernetes 节点的 10 个 pod 上。在整个应用不中断的前提下,通过滚动升级的方式升级到 ​​2.0​​ 版本。

下面的命令行推送一个标签为 ​​v1.0​​ 的镜像到 Docker Hub:

适合 Kubernetes 初学者的一些实战练习 (四)_cloud-native_34

适合 Kubernetes 初学者的一些实战练习 (四)_nginx_35

修改 UI5 应用明细页面的标题,在文字后加上一个(v2.0), 用来表示这一版的应用为 2.0 版本:

适合 Kubernetes 初学者的一些实战练习 (四)_云原生_36

同样将这个 ​​2.0​​ 版本的镜像推送到 Docker Hub 上:

适合 Kubernetes 初学者的一些实战练习 (四)_nginx_37

Docker Hub 上两个版本的镜像都就绪了:

适合 Kubernetes 初学者的一些实战练习 (四)_docker_38

首先使用 ​​1.0​​ 版本的镜像,启动单个 pod 去执行 SAP UI5 应用:


kubectl run jerry-ui5 --image=i042416/ui5-nginx:v1.0
使用 scale 命令将单个 pod 水平扩展到 10 个 pod:
kubectl scale --replicas=10 deployment/jerry-ui5


适合 Kubernetes 初学者的一些实战练习 (四)_云原生_39

上图看出 kubectl get pod 返回 10 个处于运行状态的 pod.

使用下面的命令触发滚动升级,把名为 jerry-ui5 的 deployment 基于的镜像从 ​​v1.0​​​ 升级到​​v2.0​​:


kubectl set image deployment/jerry-ui5 i042416/ui5-nginx=i042416/ui5-nginx:v2.0


适合 Kubernetes 初学者的一些实战练习 (四)_云原生_40

使用 ​​kubectl rollout status deployment/jerry-ui5​​ 查看滚动升级的实时进展情况。上图显示的日志表明,在某个时间点,有多少个旧版本的 pod 正等待被终止,有多少个新版本的 pod 已经处于可用状态。

任意点开一个 pod 查看明细,发现其使用的 docker 镜像已经是 ​​v2.0​​版本了:

适合 Kubernetes 初学者的一些实战练习 (四)_cloud-native_41

最后在浏览器里看到订单明细页面的标题,后面已经出现(v2.0), 再次确认了滚动升级已经成功结束了。

适合 Kubernetes 初学者的一些实战练习 (四)_cloud-native_42

总结

Kubernetes Pod 水平自动伸缩和滚动升级,是实际项目中两个重要且常用的操作,也是能够体现 Kubernetes 优越性的亮点所在。本文作为 Kubernetes 初学者实战练习系列的第四部分,通过两个实际的例子,详细介绍了 Kubernetes 水平自动伸缩和滚动升级的命令行操作步骤,以及这些命令行执行后背后的实现细节,希望对初学者有所帮助。