vs201检查更新不成功_Kubernetes玩转Pod滚动更新123
前言
今天推荐一篇关于Kubernetes上服务滚动更新相关的配置选项的文章,文章列出了最常用的几个配置项,解释了他们是怎么影响调度器对服务进行滚动更新的,同时还带出了Kubernetes
项目中Pod
这个逻辑单元的Ready
状态是怎么确定的,并不是容器运行起来后Pod
就进入Ready
状态的。总之个人觉得是篇非常好的普及Kubernetes
基础的文章,文章由本人完全手工翻译,尽量做到通顺易懂,英文好的同学可以直接看原文。
原文标题:Kubernetes Deployments 滚动更新配置/ Kubernetes Deployments Rolling Update Configration.
发布时间:February 26, 2020
原文链接:https://www.bluematador.com/blog/kubernetes-deployments-rolling-update-configuration
文章作者:Keilan Jackson
文章译者:Keivn Yan
Deployment
是Kubernetes
中一种常用的Pod
控制器,它对Pod
提供了细粒度的全面控制:如何进行Pod
配置、如何执行Pod
更新,应运行多少Pod
以及何时终止Pod
。有许多这方面的资源会教你如何配置Deployment
,但是你可能很难理解每个选项是如何影响滚动更新的执行方式的。在此博客文章中,我们将涵盖以下主题,以帮助您成为Kubernetes
Deployment
的专家:
- Kubernetes Deployment概貌;
- Kubernetes服务的滚动更新;
- 怎么定义
Pod
的Ready状态; - Pod Affinity和Anti-Affinity;
Deployment 概貌
Deployment
实质上是ReplicaSet
的上层包装。ReplicaSet
管理正在运行的Pod
数量,Deployment
在其之上实现功能从而拥有了Pod
滚动更新,对Pod的运行状况进行健康检查以及轻松回滚更新的能力。在常规运行期间,Deployment
仅管理一个ReplicaSet
,以确保期望数量的Pod
正在运行:
在Kubernetes
里我们不应直接操作由Deployment
创建的ReplicaSet
,对ReplicaSet
执行的所有操作应改为在Deployment
上执行,然后由Deployment
管理更新ReplicaSet
的过程。以下是一些通常在Deployment
上执行的操作的示例kubectl
命令:
# 列出默认命名空间下的所有Deploymentkubectl get deploy
# 通过定义文件更新Deploymentkubectl apply -f test.yaml
# 监控"test"这个Deployment的状态更新kubectl rollout status deploy/test
# 暂停"test"这个Deployment的更新流程:kubectl rollout pause deploy/test
# 恢复"test"这个Deployment的更新流程:kubectl rollout resume deploy/test
# 查看"test"这个Deployment的更新历史:kubectl rollout history deploy/test
# 回退test最近的更新kubectl rollout undo deploy/test
# 把test这个Deployment回滚到指定版本kubectl rollout undo deploy/test --to-revision=1
Pod的滚动更新
使用Deployment
来控制Pod
的主要好处之一是能够执行滚动更新。滚动更新允许你逐步更新Pod
的配置,并且Deployment
提供了许多选项来控制滚动更新的过程。
控制滚动更新最重要的选项是更新策略。在Deployment
的YAML
定义文件中,由spec.strategy.type
字段指定Pod
的滚动更新策略,它有两个可选值:
- RollingUpdate (默认值):逐步创建新的Pod,同时逐步终止旧Pod,用新Pod替换旧Pod。
- Recreate:在创建新Pod前,所有旧Pod必须全部终止。
大多数情况下,RollingUpdate
是Deployment
的首选更新策略。如果你的Pod
需要作为单例运行,并且不允许在任何时间存在多副本,这种时候Recreate
更新策略会很有用。
使用RollingUpdate
策略时,还有两个选项可以让你微调更新过程:
- maxSurge:在更新期间,允许创建超过期望状态定义的
Pod
数的最大值。 - maxUnavailable:在更新期间,容忍不可访问的Pod数的最大值
maxSurge
和maxUnavailable
选项都可以使用整数(比如:2)或者百分比(比如:50%)进行配置,而且这两项不能同时为零。当指定为整数时,表示允许超期创建或者不可访问的Pod
数。当指定为百分比时,将使用期望状态里定义的Pod
数作为基数。比如:如果对maxSurge
和maxUnavailable
都使用默认值25%,并且将更新应用于具有8个容器的Deployment
,那么意味着maxSurge
为2个容器,maxUnavailable
也将为2个容器。这意味着在更新过程中,将满足以下条件:
- 最多有10个
Pod
(8个期望状态里指定的Pod
和2个maxSurge
允许超期创建的Pod
)在更新过程中处于Ready状态。 - 最少有6个
Pod
(8个期望状态里指定的Pod
和2个maxUnavailable
允许不可访问的Pod
)将始终处于Ready状态。
值得注意的一点是,在考虑Deployment
应在更新期间运行的Pod
数量时,使用的是在Deployment
的更新版本中指定的副本数,而不是现有Deployment
版本的期望状态中指定的副本数。
可以用另外一种方式理解这两个选项:maxSurge
是一次将创建的新Pod
的最大数量,maxUnavailable
是一次将被删除的旧Pod
的最大数量。让我们具体看一下使用以下更新策略将具有3个副本的Deployment
从"v1"更新为" v2"的过程:
replicas: 3 strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 maxUnavailable: 0
这个更新策略是,我们想一次新建一个Pod
,并且应该始终保持Deployment
中的Pod
有三个是Ready状态。下面的动图说明了滚动更新的每一步都发生了什么。如果Deployment
看到Pod
已经完全部署好了将会把Pod
标记为Ready,创建中的Pod
标记为NotReady
,正在被删除的Pod
标记为Terminating。
怎么判读Pod是否Ready
Kubernetes
自身实现了一个叫做Ready Pod的概念来辅助滚动更新。具体来说就是,ReadinessProbe
(就绪探针)可以使Deployment
逐步更新Pod
,同时也可以使用它控制何时才能进行滚动更新,Service
也使用它来确定应该将哪些Pod
包含在服务的Endpoints中。就绪探针与活动性探针相似但不相同,活性探针使kubelet
可以根据其“重新启动策略”来确定哪些Pod
需要重新启动,并且它们与就绪性探针分开配置,不会影响Deployment
的滚动更新的过程。
译者注:关于就绪探针和活性探针详细的解释可以看我以前的文章:浅析Kubernetes Pod重启策略和健康检查
一个Ready状态的Pod
是指:Pod
通过了就绪探针的测试,并且自创建以来经过了spec.minReadySeconds
指定的秒数则被视为已经Ready
。这些选项的默认值将导致Pod
内部的容器启动后Pod
立即进入Ready状态。
事实上,有几个原因通常让你并不想让容器启动后Pod
立即进入Ready状态:
- 希望在接收流量前,
Pod
能够先通过健康检查。 - 服务需要先预热,然后再提供流量。
- 你要放慢部署速度,以减少对运行中的系统的影响。
对于Web
应用程序,要求通过健康检查非常常见,这对于以最小的中断执行更新至关重要。下面是为了对一个Web应用进行健康检查而配置的就绪探针:
readinessProbe: periodSeconds: 15 timeoutSeconds: 2 successThreshold: 2 failureThreshold: 2 httpGet: path: /health port: 80
这个探针要求对端口80上的/health
的调用在2秒内成功完成,每15秒执行一次,并且在Pod
准备就绪之前必须进行2次成功的调用。这意味着在最佳情况下,Pod
将在约30秒内准备就绪。许多应用程序在启动后2秒钟之内无法立即提供服务,即使是简单的请求,因此应该为前1项或2次检查的失败做好准备,这种情况下实际需要约60秒的准备时间Pod
才能进入Ready状态。
您还可以配置在容器上执行命令的就绪探针。这让你可以编写可执行的自定义脚本,并确定Pod
是否已准备好,Deployment
是否可以继续执行滚动更新:
readinessProbe: exec: command: - /startup.sh initialDelaySeconds: 5 periodSeconds: 15 successThreshold: 1
在这个配置中,Deployment
在Pod
创建成功后将等待5秒钟,然后每15秒钟执行一次命令。脚本的exit code为0被认为是执行成功。使用命令脚本的灵活性让你可以执行以下类似操作,例如将数据加载到缓存中或预热JVM,或在不修改应用程序代码的情况下对下游服务进行运行状况检查。
我们将在这里讨论的最后一种情况是故意减慢更新过程,以最大程度地减少对系统的影响。乍一看似乎不需要,但是在某些情况下它可能非常有用,包括事件处理系统,监视工具和预热时间较长的Pod
。通过在Deployment
定义中指定spec.minReadySeconds
字段可以轻松实现此目标。当指定minReadySeconds
时,Pod
必须运行这么多秒,而且其容器中的任何一个都不能崩溃,才能被Deployment
视为进入Ready状态。
比如说,假设一个Deployment
管控着5个Pod
副本,它们从事件流读取、处理事件,然后把数据保存在数据库中。每个Pod
需要预热60秒后才能全速处理事件,如果使用默认的选项值,Pod
创建后立即进入Ready状态,但是它们在第一分钟内处理事件的速度会很慢。更新完成后,由于所有Pod
同时预热,因此事件将会堆积在事件流里面。相反,你可以将maxSurge
设置为1,将maxUnavailable
设置为0,将minReadySeconds
设置为60。这将确保一次创建一个新的Pod
,在经过一分钟预热后新建的Pod
才能进入Ready状态,并且旧Pod
在新Pod
就绪之前不会被删除。这样,就可以在大约5分钟的时间内更新所有Pod
,并且能保持更新期间服务的稳定。
Pod Affinity和Anti-Affinity
PodAffinity
和PodAntiAffinity
这两个配置让你可以控制将Deployment
的Pod
调度到哪些节点上。尽管这个功能并非Deployment
控制器特有的,但对于许多应用程序来说可能非常有用。在配置PodAffinity
或PodAntiAffinity
时,你必须选择在不同环境条件下要添加给新建的Pod
的调度偏好。这里有两个选项:
- requiredDuringSchedulingIgnoredDuringExecution:除非节点与
Affinity
配置相匹配,否则即使没有匹配的节点,直接调度失败,也不会把Pod
调度到不匹配的节点上去。 - preferredDuringSchedulingIgnoredDuringExecution:调度程序将尝试在与配置匹配的节点上调度Pod,但如果无法这样做,则仍将
Pod
调度在另一个节点上。
podAffinity
用于将Pod
调度到某些节点上。如果知道某个Pod
具有特定的资源要求(例如,只有一组特定的,带有GPU的节点或者某个区域中的节点),则通常需要进行podAffinity
配置。或者你希望Pod
与其他Pod
并置在一个节点上:
affinity: podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - cache topologyKey: "kubernetes.io/hostname" podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchExpressions: - key: app operator: In values: - web topologyKey: kubernetes.io/hostname
相反地,podAntiAffinity
在确保同属一个Deployment
的Pod
不被调度到同一个节点上时非常有用,上面例子偏向于将标签为app:web
的Pod
部署到不同的节点上,降低服务的所有Pod
因为节点出问题同时出故障的可能性。
使用affinity
配置时,要注意非常重要的一点是,affinity
规则是在对Pod
进行调度时进行评估的。而调度器无法预见Pod
的调度位置,这意味着affinity
配置可能无法达到预期的效果。考虑有一个拥有3个节点的集群,一个拥有3个Pod
副本的使用了上面示例affinity
规则的Deployment
,Deployment
把maxSurge
配置成1。你期望的调度目标可能是,在每个节点上运行Deployment
的一个Pod
,但是由于maxSurge
设置为1,在滚动更新期间调度器每次只能创建一个新Pod
。这意味着随着时间的流逝,你可能最终会得到一个更新后没有任何这些Pod
的节点,然后所有或大多数Pod
将在下一次更新时移至该节点。调度程序不知道你将要终止旧的Pod,在做affinity
规则判断时仍然会算上旧Pod
,这就是导致上面说的可能情况的原因。如果确实需要在每个节点上只能运行一个Pod
副本,则应使用DaemonSets
控制器。如果您的应用程序可以接受,另一种选择是将更新策略更改为“重新创建”。这样,当调度程序评估affinity
规则时,将不会算上旧的Pod
。
podAffinity
和PodAntiAffinity
有很多选项可以影响Pod
的调度方式,但通常无法保证滚动更新也能满足规则。在某些情况下,这是一个非常有用的功能,但是除非真的需要控制Pod
的运行位置,否则应让kubernetes
调度程序来做出这些决定。可以在此处[1]找到有关podAffinity
和podAntiAffinity
的详细文档。
总结
我们已经介绍了Deployment
的基本用法,滚动更新的工作方式以及用于微调更新和Pod
调度的许多配置选项。此时,你应该能够使用更新策略,就绪探针和Pod
关联性(affinity
)来自信地创建和修改Deployment
的定义文件,以达到应用程序期望的状态。有关Deployment
支持的所有选项的详细参考,请查看Kubernetes
文档。
引用链接
[1]
此处: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity
推荐阅读
深入理解StatefulSet,用Kubernetes编排有状态应用
常用限流算法的应用场景和实现原理
觉得WaitGroup不好用?试试ErrorGroup吧!
- END -
关注公众号,获取更多精选技术原创文章
vs201检查更新不成功_Kubernetes玩转Pod滚动更新123相关推荐
- Kubernetes--玩转Pod滚动更新123
前言 今天推荐一篇关于Kubernetes上服务滚动更新相关的配置选项的文章,文章列出了最常用的几个配置项,解释了他们是怎么影响调度器对服务进行滚动更新的,同时还带出了Kubernetes项目中Pod ...
- Kubernetes Pod篇:带你轻松玩转Pod
本文将对Kubernetes如何发布与管理容器应用进行详细说明,主要包括Pod概述.基本用法.生命周期.Pod的控制和调度管理.Pod的升级和回滚,以及Pod的扩容机制等内容,并结合具体详细的示例,带 ...
- 深入玩转K8S之智能化的业务弹性伸缩和滚动更新操作
在上篇我们讲到了较为傻瓜初级的弹性伸缩和滚动更新,那么接下来我们来看看较为高级的智能的滚动更新.本节的知识点呢是K8S的liveness和readiness探测,也就是说利用健康检查来做更为智能化的弹 ...
- 如何滚动更新 Service?- 每天5分钟玩转 Docker 容器技术(102)
在前面的实验中,我们部署了多个副本的服务,本节将讨论如何滚动更新每一个副本. 滚动更新降低了应用更新的风险,如果某个副本更新失败,整个更新将暂停,其他副本则可以继续提供服务.同时,在更新的过程中,总是 ...
- k8s之滚动更新及pod流量分析
一.LB Service流量 LoadBalancer 负责接收 K8s 集群外部流量并转发到 Node 节点上,ipvs/iptables 再负责将节点接收到的流量转发到 Pod 中(kube-pr ...
- 小米手机扩容教程_小米手机加运存和扩容(成功的DIY,过程已更新完)|创意DIY...
小米手机加运存和扩容(成功的DIY,过程已更新完)|创意DIY 2018-09-12 话说小米4手机用了快两年了,屏的左不角摔碎了,下面三个按键早就失灵了,在三手鱼收了个电信4G的2+16的尸体,卖家 ...
- k8s滚动升级_kubernetes滚动更新
简介 当kubernetes集群中的某个服务需要升级时,传统的做法是,先将要更新的服务下线,业务停止后再更新版本和配置,然后重新启动并提供服务.如果业务集群规模较大时,这个工作就变成了一个挑战,而且先 ...
- k8s 查看pod流量_Kubernetes K8S之Pod生命周期与探针检测
K8S中Pod的生命周期与ExecAction.TCPSocketAction和HTTPGetAction探针检测 主机配置规划 Pod容器生命周期 Pause容器说明 每个Pod里运行着一个特殊的被 ...
- 放飞梦想 成功由玩美时尚精品超市开始
市场的竞争是一个成就梦想的大舞台,有些人在这里寻找到自己的人生之路,而又有些人可能会因为自己的一次失误而被这大舞台所抛弃.诸多品牌在商海中沉浮,玩美时尚精品超市从这里脱颖而出,玩美个性饰品店的成功告诉 ...
- 短信 铃声设置成功 android,玩转Android GPhone铃声设置图文教程
第1页: 昨日,一位同事向笔者问了一个颇具"挑战性"的问题,"HTC G2如何设置铃声".的确对于一款智能手机来说,无论是来电铃声.短信铃声还是脑中铃声的设置都 ...
最新文章
- YOLOv5目标检测源码重磅发布了!
- Windows 10 周年更新后的 Edge 14 的 HierarchyRequestError 报错
- python的jupyter的使用教程-Jupyter notebook快速入门教程
- problem a: 简单的整数排序_什么是基数排序?
- LCP 01. Guess Numbers 猜数字
- 22、多进程和多线程
- 纽大博士宿舍内自缢身亡,本月即将毕业
- 微软发布 .NET for Apache Spark 首个预览版
- 自定义控件三部曲之动画篇(一)——alpha、scale、translate、rotate、set的xml属性及用法
- lua的元表、模块和面向对象
- Hyperledger Fabric on SAP Cloud Platform
- 西安电子科大2010年的硕士博士考试推荐书
- 图书管理系统软件测试实验报告,软件工程课程设计实验报告--图书馆管理系统...
- 乐高大颗粒作品23:磁悬浮列车
- 驱动开发遇到version magic不匹配
- html图片闪现循环效果,CSS实现图片无缝无限循环展示效果
- JavaEE | 集合之HashMap与ConcurrentHashMap(看完多线程后补充)
- Obsolete属性
- QTabBar 和 QTabWidget部件 页签
- 基于人体感应模块的驱鸟器设计
热门文章
- MySQL常用命令收录
- 不到30行JS代码实现的Excel表格
- IntelliJ IDEA 中 右键新建时,选项没有Java class
- mysql--------常用命令
- EXT.NET GridPanel默认选中多行
- Google API 设计指南-兼容性
- 易宝典文章——玩转Office 365中的Exchange Online服务 之二十八 怎样过滤病毒***邮件...
- Java千百问_06数据结构(003)_什么是基本类型包装器
- 应用程序正常初始化(0xc015002)失败解决方法
- 【翻译】Sencha Touch 2入门:创建一个实用的天气应用程序之一