草庐IT

浅入Kubernetes(12):Deployment 的升级、回滚

痴者工良 2023-03-28 原文
目录


本篇内容讨论 Pod 的更新和回滚,内容不多。

更新

打开 https://hub.docker.com/_/nginx 可以查询 nginx 的镜像版本,我们可以先选择一个旧一点的版本。

首先,我们创建一个 Nginx 的 Deployment,副本数量为 3。

kubectl create deployment nginx --image=nginx:1.19.0 --replicas=3首次部署的时候,跟之前的操作一致,不需要什么特殊的命令。

注: 我们也可以加上 --record 标志将所执行的命令写入资源注解 kubernetes.io/change-cause 中。 这对于以后的检查是有用的。例如,要查看针对每个 Deployment 修订版本所执行过的命令。

其实更新 pod 是非常简单的,我们不需要控制每个 pod 的更新,也不需要担心会不会对业务产生影响,k8s 会自动控制这些过程。

我们只需要触发镜像版本更新事件,k8s 会自动为我们更新 pod 的。

kubectl set image deployment.apps/nginx nginx=nginx:1.20.0格式为:

kubectl set image deployment.apps/{deployment名称} {镜像名称}:={镜像名称}:{版本}我们可以查看 pod 的详细信息:

kubectl describe pods找到 Events 描述:

... ... Events:  Type    Reason     Age   From               Message  ----    ------     ----  ----               -------   Normal  Scheduled  66s   default-scheduler  Successfully assigned default/nginx-7b87485749-rlmcx to instance-2   Normal  Pulled     66s   kubelet            Container image "nginx:1.20.0" already present on machine   Normal  Created    66s   kubelet            Created container nginx   Normal  Started    65s   kubelet            Started container nginx为了记录版本更新信息,我们需要在 kubectl create deploymentkubectl set image 命令后面加上 -- --record

我们还可以通过 edit 方式更新 pod。

执行:

kubectl edit deployment nginx然后会弹出编辑 yaml 的界面,将 .spec.template.spec.containers[0].image 从 nginx:1.19.0 更改至 nginx:1.20.0,然后保存即可。

上线

仅当 Deployment Pod 模板(即 .spec.template)发生改变时,例如模板的标签或容器镜像被更新, 才会触发 Deployment 上线。 其他更新(如对 Deployment 执行扩缩容的操作)不会触发上线动作。Deployment 的上线动作可以为我们更新 pod 的版本。

它的上线跟我们所说的更新,有些区别。因为我们所说的更新,版本是往后的,例如 1.19.0 -> 1.20.0 ,用新版本替换旧版本才叫更新。但是 Deployment 的上线,则是任意版本。它会根据我们设置的镜像版本自动替换,可以用 1.19.0 替换 1.20.0。不过这里我们不需要纠结这些。

当我们更新 pod 版本时,k8s 会自动负载均衡,而不是把所有 pod 删除,再重新创建新版本 pod,它会以稳健的方式逐渐替换 pod。

我们可以通过命令,查看 pod 的上线状态:

kubectl rollout status deployment nginx输出类似于:

Waiting for rollout to finish: 2 out of 3 new replicas have been updated...或者

deployment "nginx-deployment" successfully rolled out我们也可以通过获取 deployment 信息时,查看已更新的 pod 数量:

kubectl get deploymentNAME    READY   UP-TO-DATE   AVAILABLE   AGEnginx   3/3     3            3           18mUP-TO-DATE 字段可以看到成功更新的 pod 数量。

还可以查看 ReplicaSet 和 pod:

kubectl get replicaset kubectl get pods输出类型于:

NAME               DESIRED   CURRENT   READY   AGEnginx-7b87485749   0         0         0       20mnginx-85b45874d9   3         3         3       21mNAME                     READY   STATUS    RESTARTS   AGEnginx-85b45874d9-nrbg8   1/1     Running   0          12mnginx-85b45874d9-qc7f2   1/1     Running   0          12mnginx-85b45874d9-t48vw   1/1     Running   0          12m可以看到有两个 ReplicaSet,nginx-7b87485749 已经被全部更新到 nginx-85b45874d9 了,所以前者的数量为 0,我们也可以看到 pod 中,所有 pod 都是以 nginx-85b45874d9 作为前缀的。这几个关键信息,我们可以截图,后面再次对照。

如果我们的项目上线了,我们更新软件版本,如果一次性更新所有容器或者 pod,那么我们的软件会有一段时间处于不可用状态,直到所有 pod 都完成更新。Deployment 可确保在更新时仅关闭一定数量的 Pod,默认情况下,它确保至少所需 Pods 75% 处于运行状态,也就是说正在被更新的 pod 比例不超过 25%。当然,只有两三个 pod 的 Deployment 不会按照这个比例限定。

如果我们的 pod 数量足够大,或者在更新 Deployment 时迅速输出上线状态,可以看到新旧的 pod 数量加起来不一定就是 3 个,因为它不会杀死老 Pods,直到有足够的数量新的 Pods 已经出现。 在足够数量的旧 Pods 被杀死前并没有创建新 Pods。它确保至少 2 个 Pod 可用,同时 最多总共 4 个 Pod 可用。

Deployment 确保仅所创建 Pod 数量只可能比期望 Pods 数高一点点。 默认情况下,它可确保启动的 Pod 个数比期望个数最多多出 25%(最大峰值 25%)所以在自动更新 Deployment 时,观察到的 pod 可能为 4个。另外,在 Deployment 更新时,除了可以更改镜像的版本,也可以更改 ReplicaSet 的数量。

执行 kubectl describe deployment nginx 查看 Deployment 详细信息,我们查看 Event 字段。

但是这些原理等知识我们都不需要记,也不需要深入,我们记得有这回事就行,有需要的时候也可以直接查看文档的。

会滚

默认情况下, Deployment 的上线记录都会保留在系统中,以便可以随时回滚。

我们查看 Deployment 的上线历史记录:

kubectl rollout history deployment nginxREVISION  CHANGE-CAUSE2         <none>3         <none>注:我们的版本不一定一样,因为我为了这这篇文章,进行了一些测试,可能版本数量比你的多。

可以看到有 2,3 两个版本,我们查看 版本3 的信息:

kubectl rollout history deployment nginx --revision=3deployment.apps/nginx with revision #3Pod Template:   Labels: app=nginx pod-template-hash=85b45874d9   Containers:    nginx:     Image: nginx:1.20.0     Port: <none>     Host Port: <none>     Environment: <none>     Mounts: <none>   Volumes: <none>目前介绍了几个查看 Deployment 上线的历史记录,下面我真正来回滚 Deployment。

回滚是一个版本:

kubectl rollout undo deployment nginx再执行 kubectl rollout history deployment nginx 会看到不一样的信息。

此时版本数量多了,我们还可以指定回滚到特点的版本。

kubectl rollout undo deployment nginx --to-revision=2这里提一下 --record,在前面,我们创建和更新 Deployment 时,都没有使用到这个参数。我们可以试试这个参数的作用。

kubectl set image deployment.apps/nginx nginx=nginx:1.19.0kubectl rollout history deployment nginx输出:

REVISION  CHANGE-CAUSE5         <none>6         kubectl set image deployment.apps/nginx nginx=nginx:1.19.0 --record=true说明加上了 --record ,会把我们操作时的命令记录下来。

但是我们这里目前来说,只有两个记录,我们明明提交了多次,但是这里查询的只有两条记录,这时因为我们操作的时候,只用到了 1.19.0、1.20.0 两个版本,所以也就只有这两个版本的提交记录。多用几个版本,输出结果:

REVISION  CHANGE-CAUSE7         kubectl set image deployment.apps/nginx nginx=nginx:1.19.0 --record=true8         kubectl set image deployment.apps/nginx nginx=nginx:1.20.0 --record=true9         kubectl set image deployment.apps/nginx nginx=nginx:latest --record=true

缩放 Deployment

直接设置

很简单,使用 kubectl scale 命令直接设置:

kubectl scale deployment.v1.apps/nginx --replicas=10修改 yaml 的方式也行,一是修改 yaml文件,使用 kubectl apply -f 的方式更新,或者使用 kube edit 的方式。

Pod 水平自动缩放

K8S有个 Pod 水平自动扩缩(Horizontal Pod Autoscaler) 可以基于 CPU 利用率自动扩缩 ReplicationController、Deployment、ReplicaSet 和 StatefulSet 中的 Pod 数量。

除了 CPU 利用率,也可以基于其他应程序提供的自定义度量指标 来执行自动扩缩。 Pod 自动扩缩不适用于无法扩缩的对象,比如 DaemonSet。

参考资料:https://kubernetes.io/zh/docs/tasks/run-application/horizontal-pod-autoscale/

命令:

kubectl autoscale deployment nginx --min=10 --max=15 --cpu-percent=80表示目标 CPU 使用率为 80%(期望指标),副本数量配置应该为 10 到 15 之间,CPU 是动态缩放 pod 的指标,会根据具体的 CPU 使用率计算副本数量,其计算公式如下。

期望副本数 = ceil[当前副本数 * (当前指标 / 期望指标)]算法细节请查看:https://kubernetes.io/zh/docs/tasks/run-application/horizontal-pod-autoscale/#algorithm-details

比例缩放

另外还有个比例缩放,允许 Deployment 支持同时运行应用程序的多个版本。

当我们设置.spec.strategy.type==RollingUpdate时,采取 滚动更新的方式更新 Pods,就可以指定 maxUnavailable 和 maxSurge 来控制滚动更新 过程。这个我们之前提到过,就是 Deployment 默认会保证一直有 75% 的 pod处于可用状态,在完成更新前可能有多个版本的 pod 共存。

这里不细说,请参考:https://kubernetes.io/zh/docs/concepts/workloads/controllers/deployment/#max-unavailable

默认的话,deployment 的 yaml 是这样的:

  strategy:     rollingUpdate:       maxSurge: 25%       maxUnavailable: 25%     type: RollingUpdate我们可以改成:

  strategy:     rollingUpdate:       maxSurge: 3       maxUnavailable: 2     type: RollingUpdate注:执行 kubectl edit deployment nginx 直接改。

我们可以观察到这个过程:

root@instance-1:~# kubectl set image deployment nginx nginx=nginx:1.20.0 deployment.apps/nginx image updated root@instance-1:~# kubectl get replicaset NAME               DESIRED   CURRENT   READY   AGE nginx-7b87485749   5         5         0       93m nginx-85b45874d9   0         0         0       93m nginx-bb957bbb5    8         8         8       35m前面我们设置了最大存在两个不可用 pod(maxUnavailable=2),所以一开始会更新两个 pod,所以 nginx-bb957bbb5 8个处于可用状态。而 maxSurge 表示允许超出的期望 pod 数量,所以nginx-7b87485749 的数量不是 2 个,而是 5个,因为允许超出 3 个。其实意思就是不需要等旧的 pod 删除 一个,新的 pod 创建一个。可以多创建几个 pod,再按照慢一些的速度删除旧的 pod,最终完成版本更新。

最终:

NAME               DESIRED   CURRENT   READY   AGEnginx-7b87485749   10        10        10      99mnginx-85b45874d9   0         0         0       99mnginx-bb957bbb5    0         0         0       41m

暂停 Deployment 上线

命令:

kubectl rollout pause deployment nginx用途就是我们更新 Deployment 的 pod 版本时,可以暂停。

前面我们已经设置了这个 maxSurge 和 maxUnavailable,可以让 pod 的创建慢一些。

执行下面的命令可以快速卡住上线过程。

kubectl set image deployment nginx nginx=nginx:latest kubectl rollout pause deployment nginx之后,多次执行 kubectl get replicaset ,会发现副本数量不会变化。

NAME               DESIRED   CURRENT   READY   AGEnginx-7b87485749   8         8         8       109mnginx-85b45874d9   0         0         0       109mnginx-bb957bbb5    5         5         5       52m如果我们再次执行:

kubectl set image deployment nginx nginx=nginx:1.19.0会发现虽然提示更新了,但是实际上没有变化。在暂停中,执行新的更新操作是无效的。

执行 kubectl rollout history deployment nginx 也查不到我们提交的 1.19.0 的请求。

暂停的时候,我们可以更新一些限制的 CPU 和 资源:

kubectl set resources deployment nginx -c=nginx --limits=cpu=200m,memory=512Mi恢复 Deployment:

kubectl rollout resume deployment nginx

有关浅入Kubernetes(12):Deployment 的升级、回滚的更多相关文章

  1. ruby - 通过 rvm 升级 ruby​​gems 的问题 - 2

    尝试通过RVM将RubyGems升级到版本1.8.10并出现此错误:$rvmrubygemslatestRemovingoldRubygemsfiles...Installingrubygems-1.8.10forruby-1.9.2-p180...ERROR:Errorrunning'GEM_PATH="/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/ruby-1.9.2-p180@global:/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/rub

  2. ruby-on-rails - 项目升级后 Pow 不会更改 ruby​​ 版本 - 2

    我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby​​版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby​​版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘

  3. ruby - 如何在 Lion 上安装 Xcode 4.6,需要用 RVM 升级 ruby - 2

    我实际上是在尝试使用RVM在我的OSX10.7.5上更新ruby,并在输入以下命令后:rvminstallruby我得到了以下回复:Searchingforbinaryrubies,thismighttakesometime.Checkingrequirementsforosx.Installingrequirementsforosx.Updatingsystem.......Errorrunning'requirements_osx_brew_update_systemruby-2.0.0-p247',pleaseread/Users/username/.rvm/log/138121

  4. ruby - 在不使用 RVM 的情况下在 Mac 上卸载和升级 Ruby - 2

    我最近决定从我的系统中卸载RVM。在thispage提出的一些论点说服我:实际上,我的决定是,我根本不想担心Ruby的多个版本。我只想使用1.9.2-p290版本而不用担心其他任何事情。但是,当我在我的Mac上运行ruby--version时,它告诉我我的版本是1.8.7。我四处寻找如何简单地从我的Mac上卸载这个Ruby,但奇怪的是我没有找到任何东西。似乎唯一想卸载Ruby的人运行linux,而使用Mac的每个人都推荐RVM。如何从我的Mac上卸载Ruby1.8.7?我想升级到1.9.2-p290版本,并且我希望我的系统上只有一个版本。 最佳答案

  5. ruby - 我正在学习编程并选择了 Ruby。我应该升级到 Ruby 1.9 吗? - 2

    我完全不是程序员,正在学习使用Ruby和Rails框架进行编程。我目前正在使用Ruby1.8.7和Rails3.0.3,但我想知道我是否应该升级到Ruby1.9,因为我真的没有任何升级的“遗留”成本。缺点是什么?我是否会遇到与普通gem的兼容性问题,或者甚至其他我不太了解甚至无法预料的问题? 最佳答案 你应该升级。不要坚持从1.8.7开始。如果您发现不支持1.9.2的gem,请避免使用它们(因为它们很可能不被维护)。如果您对gem是否兼容1.9.2有任何疑问,您可以在以下位置查看:http://www.railsplugins.or

  6. ruby-on-rails - 从 Rails 2.3 升级到 Rails 4.0 - 2

    我们有一个目前在Rails2.3.12版和Ruby1.8.7版上运行的应用程序。我们想将我们的应用程序更新到Rails4.0和Ruby2.1.0。我们有大约200个模型和150个Controller。我想知道升级过程需要多大的努力。您还可以提供升级可以遵循的步骤。我们应该先升级Ruby然后再升级Rails还是相反? 最佳答案 您想要实现的目标将是史诗般的努力。我无法为您提供分步说明,因为不可能在一个答案中涵盖所有情况。我建议不要同时升级Ruby和Rails,而是分步升级。升级本身的复杂性是巨大的,但只要您的应用程序具有合理的测试覆盖

  7. 深度学习12. CNN经典网络 VGG16 - 2

    深度学习12.CNN经典网络VGG16一、简介1.VGG来源2.VGG分类3.不同模型的参数数量4.3x3卷积核的好处5.关于学习率调度6.批归一化二、VGG16层分析1.层划分2.参数展开过程图解3.参数传递示例4.VGG16各层参数数量三、代码分析1.VGG16模型定义2.训练3.测试一、简介1.VGG来源VGG(VisualGeometryGroup)是一个视觉几何组在2014年提出的深度卷积神经网络架构。VGG在2014年ImageNet图像分类竞赛亚军,定位竞赛冠军;VGG网络采用连续的小卷积核(3x3)和池化层构建深度神经网络,网络深度可以达到16层或19层,其中VGG16和VGG

  8. ruby-on-rails - Rails 4.1.0.beta1 升级失败 - 2

    我最近尝试安装rails4.1.0.beta1,但是railss导致以下错误。[RVM]/gems/ruby-2.0.0-p247/gems/activesupport-4.1.0.beta1/lib/active_support/core_ext/module/aliasing.rb:32:in`alias_method':undefinedmethod`graft'forclass`ActiveRecord::Associations::JoinDependency'(NameError)[RVM]/gems/ruby-2.0.0-p247/gems/activesupport-4

  9. ruby-on-rails - 无法构建 gem native 扩展 (mkmf (LoadError)) - Ubuntu 12.04 - 2

    这个问题在这里已经有了答案:Unabletoinstallgem-Failedtobuildgemnativeextension-cannotloadsuchfile--mkmf(LoadError)(17个答案)关闭9年前。嘿,我正在尝试在一台新的ubuntu机器上安装rails。我安装了ruby​​和rvm,但出现“无法构建gemnative扩展”错误。这是什么意思?$sudogeminstallrails-v3.2.9(没有sudo表示我没有权限)然后它会输出很多“获取”命令,最终会出现这个错误:Buildingnativeextensions.Thiscouldtakeawhi

  10. ruby - 使用 OpenSSL ruby​​ 从一个 .p12 文件中提取多个 key - 2

    我想知道如何从Apple.p12文件中提取key。根据我有限的理解,.p12文件是X504证书和私钥的组合。我看到我遇到的每个.p12文件都有一个X504证书和至少一个key,在某些情况下有两个key。这是因为每个.p12都有一个Apple开发人员key,有些还有一个额外的key(可能是Appleroot授权key)。我只考虑那些具有两个key的.p12文件是有效的。我的目标是区分具有一个key的.p12文件和具有两个key的.p12文件。到目前为止,我已经使用OpenSSL来检查X504文件和任何.p12的key。例如,我有这段代码可以检查目录中的所有.p12文件:Dir.glob(

随机推荐