在上篇文章 .NET Core + Kubernetes:Pod 中,主要介绍了 Pod 的相关内容, 基于 Pod 为单位能更加合理进行容器编排,然而 Pod 只是个启动了一个或一组容器的资源类型,在实际应用中,我们也需要 Pod 能实现动态扩展与收缩、滚动更新等,但 Pod 本身是没有办法做到的,它需要依赖上层的一种控制来达到这样的效果,这就涉及到 Kubernetes 中的控制器(Controller)模型知识,本文将注意介绍 Deployment 这个最基本的控制器对象。
我们继续以 .NET Core + Kubernetes:快速体验 文中配置为例,将以下配置保存为 k8sdemo-deployment.yaml
:
apiVersion: apps/v1
kind: Deployment
metadata:name: k8sdemo-deployment
spec:replicas: 2selector:matchLabels:name: k8sdemotemplate:metadata:labels:name: k8sdemospec:containers:- name: k8sdemoimage: beckjin/k8sdemo:1.0.0ports:- containerPort: 80imagePullPolicy: IfNotPresent
这个 Deployment 指定创建 2 个含 name=k8sdemo
标签的 Pod,template 字段指定了 Pod 的模板。从表面上来看,Deployment 和 Pod 是直接关系,然而实际上在 Deployment 与 Pod 直接还有 ReplicaSet 一层。如下:
Deployment 实际上一个两层控制器,Deployment 控制 ReplicaSet,ReplicaSet 控制 Pod。ReplicaSet 有版本区分,滚动更新的能力就是基于 ReplicaSet 的版本来实现,下文会介绍。
通过以下命令创建 k8sdemo-deployment
:
kubectl apply -f k8sdemo-deployment.yaml
查看 k8sdemo-deployment
的状态信息:
kubectl get deployments
输出结果中含3个状态字段,含义如下:
READY:当前处于 Running 状态的 Pod 的个数/用户期望的 Pod 个数(配置文件设置的
replicas
值);UP-TO-DATE:当前处于最新版本的 Pod 个数(Pod 的 Spec 部分与 Deployment 里 Pod 模板里定义的完全一致),在滚动更新过程中会有不一致的阶段;
AVAILABLE:当前可用的 Pod 个数。
查看 k8sdemo-deployment
所控制的 ReplicaSet 信息:
kubectl describe replicaset
如上图,Deployment 创建后,Deployment 控制器就会立即创建一个 Pod 个数为 2 的 ReplicaSet,ReplicaSet 的名字是由 Deployment 名字 + 随机字符串,Pod 的名字是由 ReplicaSet 名字 + 随机字符串。
动态伸缩
要实现 Pod 的伸缩只需要调整配置文件中的 replicas
字段,如扩展为 3 个,扩展完成后结果如下:
收缩则类似。
滚动更新
假设现在将镜像 beckjin/k8sdemo:1.0.0
升级为 beckjin/k8sdemo:1.1.0
,重新 apply 后并查看 Deployment 的 Events 信息,输出内容含 "滚动更新" 的整个流程。
kubectl describe deployment k8sdemo-deployment
Deployment 控制器根据修改后的 Pod 模板,创建新的 ReplicaSet(k8sdemo-deployment-68cb864ff6
),Pod 数默认是 0,然后老的 ReplicaSet (k8sdemo-deployment-84d777fb7
)Pod 数逐渐减少,新的 ReplicaSet 的 Pod 数逐渐增加,两个过程交替进行,新的增加一个,老的减少一个,直到全部升级完成。
查看当前 ReplicaSet 的状态:
可以看出原来的 ReplicaSet 的 Pod 已经缩减为 0 个,新的 ReplicaSet 的 Pod 扩展为 3 个,每次配置修改重新部署都可能创建一个新的 ReplicaSet,所以 Deployment、ReplicaSet 和 Pod 的关系图可扩展如下:
回滚
通过上文的介绍,已经了解应用版本与 ReplicaSet 具有一一对应关系,所以如果要回滚版本其实就是使原来的 ReplicaSet 重新扩展 Pod,当前的 ReplicaSet 收缩至 0 个 Pod。
通过 kubectl rollout history
命令查看每次 Deployment 变更对应的版本。
kubectl rollout history deployment/k8sdemo-deployment
由于在创建 Deployment 没有加 –record
参数,所以 CHANGE-CAUSE 都是 none
现在如果需要回滚到版本 1,执行以下命令:
kubectl rollout undo deployment/k8sdemo-deployment --to-revision=1
这时 Deployment 控制器还是按 "滚动更新" 的方式,完成对 k8sdemo-deployment
的回滚操作。
故障转移
故障转移主要是指当集群中某个节点挂了,Pod 会自动转移到其他健康的节点上。当前的 Pod 分布情况如下:
可以看出 node1 上分配了 2 个 Pod,node2 分配了 1 个 Pod,接下来将 node1 强制关机,然后当 Kubernetes 检测到 node1 不可用时,node1 上的 Pod 会变成 Terminating 状态,并在 node2 上新建,维持可用 Pod 总数不变。
当 node1 恢复后,Terminating 状态的 Pod 会被自动删除,不过已经转移到 node2 的 Pod 是不会被重新调度回 node1 的。