Kubernetes yaml 之 Deployment yaml 文件
Deployment 为 Pod 和 ReplicaSet 提供了一个声明式定义 (declarative) 方法,用来替代以前的 ReplicationController 更方便的管理应用。
作为最常用的 Kubernetes 对象,Deployment 经常会用来创建 ReplicaSet 和 Pod,我们往往不会直接在集群中使用 ReplicaSet 部署一个新的微服务,一方面是因为 ReplicaSet 的功能其实不够强大,一些常见的更新、扩容和缩容运维操作都不支持,Deployment 的引入就是为了支持这些复杂的操作。
典型用例如下:
- 使用 Deployment 来创建 ReplicaSet。ReplicaSet 在后台创建 pod。检查启动状态,看它是成功还是失败。
- 然后,通过更新 Deployment 的 PodTemplateSpec 字段来声明 Pod 的新状态。这会创建一个新的ReplicaSet,Deployment 会按照控制的速率将 pod 从旧的 ReplicaSet 移动到新的 ReplicaSet中。
- 如果当前状态不稳定,回滚到之前的 Deployment revision。每次回滚都会更新 Deployment 的 revision。
- 扩容 Deployment 以满足更高的负载。
- 暂停 Deployment 来应用 PodTemplateSpec 的多个修复,然后恢复上线。
- 根据 Deployment 的状态判断上线是否 hang 住了。
- 清除旧的不必要的 ReplicaSet。
Deployment 原理
控制器模型
在 Kubernetes 架构中,有一个叫做 kube-controller-manager 的组件。这个组件,是一系列控制器的集合。其中每一个控制器,都以独有的方式负责某种编排功能。而 Deployment 正是这些控制器中的一种。它们都遵循 Kubernetes 中一个通用的编排模式,即:控制循环
用一段go语言伪代码,描述这个控制循环
1 |
|
在具体实现中,实际状态往往来自于Kubernetes集群本身。比如Kubelet通过心跳汇报的容器状态和节点状态,或者监控系统中保存的应用监控数据,或者控制器主动收集的它感兴趣的信息,这些都是常见的实际状态的来源;期望状态一般来自用户提交的YAML文件,这些信息都保存在Etcd中
对于 Deployment,它的控制器简单实现如下:
- Deployment Controller 从 Etcd 中获取到所有携带“app:nginx”标签的 Pod,然后统计它们的数量,这就是实际状态
- Deployment 对象的 replicas 的值就是期望状态
- Deployment Controller 将两个状态做比较,然后根据比较结果,确定是创建 Pod,还是删除已有 Pod
滚动更新
Deployment 滚动更新的实现,依赖的是 Kubernetes 中的 ReplicaSet
Deployment 控制器实际操纵的,就是 Replicas 对象,而不是 Pod 对象。
Replicas 负责通过“控制器模式”,保证系统中 Pod 的个数永远等于指定的个数。这也正是 Deployment 只允许容器的 restartPolicy=Always
的主要原因:只有容器能保证自己始终是 running 状态的前提下,ReplicaSet 调整 Pod 的个数才有意义。
Deployment 同样通过控制器模式,操作 ReplicaSet 的个数和属性,进而实现“水平扩展/收缩”和“滚动更新”两个编排动作对于“水平扩展/收缩”的实现,Deployment Controller 只需要修改 replicas 的值即可。用户执行这个操作的指令如下:
1 |
|
Deployment.yaml 文件解析
Deployment yaml 文件包含四个部分:
- apiVersion: 表示版本。版本查看命令:kubectl api-versions
- kind: 表示资源
- metadata: 表示元信息
- spec: 资源规范字段
1 |
|
Deployment.yaml 配置项说明
livenessProbe:存活指针
用于判断 Pod(中的应用容器)是否健康,可以理解为健康检查。使用 livenessProbe 来定期的去探测,如果探测成功,则 Pod 状态可以判定为 Running;如果探测失败,可kubectl会根据Pod的重启策略来重启容器。
如果未给Pod设置 livenessProbe,则默认探针永远返回 Success。
执行 kubectl get pods 命令,输出信息中 STATUS 一列可以看到Pod是否处于Running状态。
livenessProbe使用场景:有些后端应用在出现某些异常的时候会有假死的情况,这种情况容器依然是running状态,但是应用是无法访问的,所以需要加入存活探测livenessProbe来避免这种情况的发生。
readinessProbe:就绪指针
就绪的意思是已经准备好了,Pod 的就绪可以理解为这个 Pod 可以接受请求和访问。使用 readinessProbe 来定期的去探测,如果探测成功,则 Pod 的 Ready 状态判定为 True;如果探测失败,Pod 的 Ready 状态判定为 False。
与 livenessProbe 不同的是,kubelet 不会对 readinessProbe 的探测情况有重启操作。
当执行 kubectl get pods 命令,输出信息中 READY 一列可以看到 Pod 的 READY 状态是否为 True。
readinessProbe 使用场景:k8s 应用更新虽然是滚动升级方式,但是很多后端程序启动都比较久,容器起来了,但是服务未起来,而 k8s 只要容器起来了就会移除掉旧的容器,这种情况就会导致在更新发版的时候应用访问失败。这时候就需要配置 readinessProbe 就绪检测,保证新的 pod 已经能正常使用了才会移除掉旧的 pod。
initContainers:初始化容器
用于主容器启动时先启动可一个或多个初始化容器,如果有多个,那么这几个 Init Container 按照定义的顺序依次执行,只有所有的 Init Container 执行完后,主容器才会启动。由于一个 Pod 里的存储卷是共享的,所以 Init Container 里产生的数据可以被主容器使用到。
Init Container 可以在多种K8S资源里被使用到,如 Deployment、Daemon Set、Pet Set、Job 等,但归根结底都是在 Pod 启动时,在主容器启动前执行,做初始化工作。
tolerations:污点容忍度
节点污点:类似节点上的标签或注解信息,用来描述对应节点的元数据信息;污点定义的格式和标签、注解的定义方式很类似,都是用一个 key-value 数据来表示,不同于节点标签,污点的键值数据中包含对应污点的 effect,污点的 effect 是用于描述对应节点上的污点有什么作用;在 k8s 上污点有三种 effect(效用)策略,第一种策略是 NoSchedule,表示拒绝 pod 调度到对应节点上运行;第二种策略是 PreferSchedule,表示尽量不把 pod 调度到此节点上运行;第三种策略是 NoExecute,表示拒绝将 pod 调度到此节点上运行;该效用相比 NoSchedule 要严苛一点;从上面的描述来看,对应污点就是来描述拒绝pod运行在对应节点的节点属性。pod 对节点污点的容忍度:pod 要想运行在对应有污点的节点上,对应 pod 就要容忍对应节点上的污点;pod 对节点污点的容忍度就是在对应 pod 中定义怎么去匹配节点污点;通常匹配节点污点的方式有两种,一种是等值(Equal)匹配,一种是存在性(Exists)匹配;等值匹配表示对应pod的污点容忍度,必须和节点上的污点属性相等,所谓污点属性是指污点的 key、value 以及 effect;即容忍度必须满足和对应污点的key、value 和 effect 相同,这样表示等值匹配关系,其操作符为 Equal;存在性匹配是指对应容忍度只需要匹配污点的 key 和 effect 即可,value 不纳入匹配标准,即容忍度只要满足和对应污点的 key 和 effect 相同就表示对应容忍度和节点污点是存在性匹配,其操作符为 Exists;