如何使用示例执行Kubernetes RollingUpdate
在本Kubernetes教程中,我们将使用部署来执行RollingUpdate我们在Pod中运行的应用程序。
本节介绍如何更新在Kubernetes集群中运行的应用程序,以及Kubernetes如何迈向真正的"零停机时间"更新过程。
尽管仅使用ReplicationControllers或者ReplicaSets即可实现,但Kubernetes还提供了我们在上一节中讨论的Deployment资源,该资源位于ReplicaSets之上,并支持声明式应用程序更新。
最初,AD连播会运行我们应用程序的第一个版本-假设它的镜像标记为" v1"。
然后,我们开发该应用程序的较新版本,并将其作为新图像推送到图像存储库,标记为" v2"。
接下来,我们要用此新版本替换所有AD连播。
我们有两种更新所有这些Pod的方法。
我们可以执行以下操作之一:
重新创建:首先删除所有现有的Pod,然后再开始新的Pod。
这将导致暂时不可用。滚动更新:一次更新Pod,以保证应用程序的可用性。
这是首选方法,我们可以进一步调整其行为。
使用Kubernetes RollingUpdate
RollingUpdate
选项用于确保一定数量的最小和最大数量的Pod始终可用:
maxUnavailable:在更新过程中不可用的Pod的最大数量。
该值可以是百分比(默认值为25%)或者整数。
如果maxSurge的值为0,则表示Pod的数量对所需数量没有容忍度,maxUnavailable的值不能为0。" maxSurge:"在更新过程中,可以在所需数量的" ReplicaSet"上创建的Pod的最大数量。
该值可以是百分比(默认值为25%)或者整数。
如果maxUnavailable的值为0,这表示服务Pod的数量应始终满足所需的数量,则maxSurge的值不能为0
我将创建一个新的部署来演示RollingUpdate
,为此,我将从一个现有部署中复制YAML模板文件:
[root@controller ~]# vim rolling-nginx.yml
接下来,我将进行必要的更改,并为RollingUpdate
添加strategy
:
[root@controller ~]# cat rolling-nginx.yml apiVersion: apps/v1 kind: Deployment metadata: name: rolling-nginx spec: replicas: 4 strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 maxUnavailable: 1 selector: matchLabels: app: rolling-nginx template: metadata: labels: app: rolling-nginx spec: containers: - name: nginx image: nginx:1.9
其中我们需要四个副本,并将更新策略设置为RollingUpdate
。
" MaxSurge"值为1,这是高于所需副本数的最大值,而" maxUnvailable"则为1. 这意味着在整个过程中,我们应该至少有3个,最多5个正在运行的Pod。
同样为了示例,我已经明确定义了要使用的非常老版本的nginx图像,以便我们可以在下一节中使用RollingUpdate
将其更新为最新版本:
让我继续创建此部署:
[root@controller ~]# kubectl create -f rolling-nginx.yml deployment.apps/rolling-nginx created
列出并验证新创建的Pod:
[root@controller ~]# kubectl get pods NAME READY STATUS RESTARTS AGE ... ... ... ... ... rolling-nginx-74cf96d8bb-6f54x 0/1 ContainerCreating 0 43s rolling-nginx-74cf96d8bb-dmkqj 0/1 ContainerCreating 0 43s rolling-nginx-74cf96d8bb-gmqjz 0/1 ContainerCreating 0 43s rolling-nginx-74cf96d8bb-phkth 0/1 ContainerCreating 0 43s
因此,我们有4个新的容器,目前正在为这些容器创建容器。
我们会在几秒钟内检查部署状态,并且所有四个Pod都处于"就绪"状态:
[root@controller ~]# kubectl get deployments NAME READY UP-TO-DATE AVAILABLE AGE lab-nginx 2/2 2 2 4h9m label-nginx-example 2/2 2 2 5h12m nginx-deploy 2/2 2 2 27h rolling-nginx 4/4 4 4 107s
要获取Pod的事件列表,我们可以使用field-selector
:
[root@controller ~]# kubectl get event --field-selector involvedObject.name=rolling-nginx-74cf96d8bb-6f54x LAST SEEN TYPE REASON OBJECT MESSAGE 5m21s Normal Scheduled pod/rolling-nginx-74cf96d8bb-6f54x Successfully assigned default/rolling-nginx-74cf96d8bb-6f54x to worker-2.example.com 5m19s Normal Pulling pod/rolling-nginx-74cf96d8bb-6f54x Pulling image "nginx:1.9" 4m13s Normal Pulled pod/rolling-nginx-74cf96d8bb-6f54x Successfully pulled image "nginx:1.9" in 1m6.412630691s 4m13s Normal Created pod/rolling-nginx-74cf96d8bb-6f54x Created container nginx 4m13s Normal Started pod/rolling-nginx-74cf96d8bb-6f54x Started container nginx
因此,容器已从" nginx:1.9"版本的镜像开始。
检查推出历史记录
在此阶段,我们讨论了kubectl
如何在不停机的情况下管理应用程序的更新,但是我们一定想知道这些更新实际上是如何推出的?
答案是使用部署历史记录。
每次修改部署时,都会存储相应修改的修订历史记录。
因此,我们可以使用这些修订ID来执行更新或者回滚到最新修订。
让我们举个例子,如果我检查新创建的部署的部署历史记录:
[root@controller ~]# kubectl rollout history deployment rolling-nginx deployment.apps/rolling-nginx REVISION CHANGE-CAUSE 1 <none>
由于我们尚未对此部署进行任何更改,因此只有一个修订历史记录。
"但是为什么CHANGE-CAUSE没有显示?
"这是因为在创建部署时我们没有使用--record。--record
参数将为每个修订历史记录在CHANGE-CAUSE
下添加一个命令。
因此,我将删除此部署并再次创建它:
[root@controller ~]# kubectl delete deployment rolling-nginx deployment.apps "rolling-nginx" deleted
这次我将使用--record
和kubectl create
:
[root@controller ~]# kubectl create -f rolling-nginx.yml --record deployment.apps/rolling-nginx created
现在验证修订历史记录,这一次记录了第一个修订的命令:
[root@controller ~]# kubectl rollout history deployment rolling-nginx deployment.apps/rolling-nginx REVISION CHANGE-CAUSE 1 kubectl create --filename=rolling-nginx.yml --record=true
修改部署并启动更新让我们修改部署以验证我们的RollingUpdate,如果我们还记得我们为容器使用了非常旧的nginx镜像,那么我们将更新镜像详细信息以使用其他nginx镜像:
[root@controller ~]# kubectl set image deployment rolling-nginx nginx=nginx:1.15 --record deployment.apps/rolling-nginx image updated
其中我刚刚将image部分更新为使用nginx:1.15而不是1.9,或者,我们也可以使用Kubectl edit编辑部署的YAML文件。
监视滚动更新状态
现在,一旦我们修改了Pod模板,更新就会自动开始。
要监视推出状态,我们可以使用:
[root@controller ~]# kubectl rollout status deployment rolling-nginx Waiting for deployment "rolling-nginx" rollout to finish: 1 old replicas are pending termination... Waiting for deployment "rolling-nginx" rollout to finish: 1 old replicas are pending termination... Waiting for deployment "rolling-nginx" rollout to finish: 1 old replicas are pending termination... Waiting for deployment "rolling-nginx" rollout to finish: 3 of 4 updated replicas are available... deployment "rolling-nginx" successfully rolled out
这是说明滚动更新过程的图:
"那么,这是怎么回事?"
在这种情况下,一个副本可能不可用,因此,由于所需的副本数为4,因此仅需要其中3个副本可用。
这就是为什么推出过程会立即删除一个Pod并创建一个新Pod的原因,因为maxSurge定义为1,因此任何时候我们最多可以拥有4个Pod。
这样可以确保至少有3个Pod可用,并且不超过最大Pod数量。
新的窗格可用后,下一个窗格将终止,并使用更新的镜像启动新的窗格。
这将继续,直到所有Pod都使用更新的Nginx镜像运行为止。
暂停和继续推出过程
假设我们要在更新整个部署之前验证某些Pod上的更新。
在这种情况下,我们可以使用以下语法暂停发布过程:
kubectl rollout pause deployment rolling-nginx <deployment-name>
我将再次修改部署的镜像以使用nginx 1.16(在此阶段,打开控制器的另一个终端,以便我们可以监视部署的状态):
[root@controller ~]# kubectl set image deployment rolling-nginx nginx=nginx:1.16 --record deployment.apps/rolling-nginx image updated
现在,我将立即暂停发布过程:
[root@controller ~]# kubectl rollout pause deployment rolling-nginx deployment.apps/rolling-nginx paused
在控制器节点的另一个终端上,我正在监视首次发布的状态:
[root@controller ~]# kubectl rollout status deployment rolling-nginx Waiting for deployment "rolling-nginx" rollout to finish: 2 out of 4 new replicas have been updated... Waiting for deployment "rolling-nginx" rollout to finish: 2 out of 4 new replicas have been updated... ..
在此阶段,只有4.4个Pod中的2个已部署了1.16 nginx镜像,此后暂停了首次展示,因此现在我们可以执行任何验证,然后再恢复首次展示。
检查可用Pod的列表:
[root@controller ~]# kubectl get pods -l app=rolling-nginx NAME READY STATUS RESTARTS AGE rolling-nginx-6dc6fcd44c-46ckr 1/1 Running 0 69m rolling-nginx-6dc6fcd44c-4bzzj 1/1 Running 0 69m rolling-nginx-6dc6fcd44c-bhbqb 1/1 Running 0 69m rolling-nginx-765c4fc67d-cfn6n 1/1 Running 0 3m31s rolling-nginx-765c4fc67d-dzzrg 1/1 Running 0 3m31s
我们的运行阶段有5个Pod,因为我们的maxSurge值为1. 在AGE中,我们可以找出新创建的Pod,即
rolling-nginx-765c4fc67d-cfn6n 1/1 Running 0 3m31s rolling-nginx-765c4fc67d-dzzrg 1/1 Running 0 3m31s
提示:
在这种情况下,最好使用minReadySeconds
属性,该属性指定在将新创建的Pod视为可用之前应准备多长时间。
在容器可用之前,推出过程将不会继续。
完成验证后,我们可以使用以下方法恢复部署:
[root@controller ~]# kubectl rollout resume deployment rolling-nginx deployment.apps/rolling-nginx resumed
我们可以使用以下命令再次检查发布的进度,当我暂停发布过程时,该命令使我在另一个终端中仍处于运行状态:
[root@controller ~]# kubectl rollout status deployment rolling-nginx Waiting for deployment "rolling-nginx" rollout to finish: 2 out of 4 new replicas have been updated... Waiting for deployment "rolling-nginx" rollout to finish: 2 out of 4 new replicas have been updated... Waiting for deployment "rolling-nginx" rollout to finish: 2 out of 4 new replicas have been updated... Waiting for deployment spec update to be observed... Waiting for deployment spec update to be observed... Waiting for deployment "rolling-nginx" rollout to finish: 2 out of 4 new replicas have been updated... Waiting for deployment "rolling-nginx" rollout to finish: 2 out of 4 new replicas have been updated... Waiting for deployment "rolling-nginx" rollout to finish: 1 old replicas are pending termination... Waiting for deployment "rolling-nginx" rollout to finish: 1 old replicas are pending termination... Waiting for deployment "rolling-nginx" rollout to finish: 1 old replicas are pending termination... Waiting for deployment "rolling-nginx" rollout to finish: 3 of 4 updated replicas are available... deployment "rolling-nginx" successfully rolled out
说明:
如果部署已暂停,则在我们恢复部署之前,undo命令不会将其撤消。
回滚(撤消)更新
通过告诉Kubernetes撤消上一次部署部署,部署可以轻松地回滚到先前部署的版本。
我们可以检查修订版ID,以便可以定义要将部署回滚到的修订版ID:
[root@controller ~]# kubectl rollout history deployment rolling-nginx deployment.apps/rolling-nginx REVISION CHANGE-CAUSE 2 kubectl set image deployment rolling-nginx nginx=nginx:1.15 --record=true 3 kubectl set image deployment rolling-nginx nginx=nginx:1.16 --record=true
在我的情况下,这里有2个修订版,其中ID 3是最新的修订版,因此我可以回滚到修订版2,其中我们部署了1.15版的nginx镜像。
[root@controller ~]# kubectl rollout undo deployment rolling-nginx --to-revision=2 deployment.apps/rolling-nginx rolled back
监视回滚的状态:
[root@controller ~]# kubectl rollout status deployment rolling-nginx Waiting for deployment "rolling-nginx" rollout to finish: 2 out of 4 new replicas have been updated... Waiting for deployment "rolling-nginx" rollout to finish: 2 out of 4 new replicas have been updated... Waiting for deployment "rolling-nginx" rollout to finish: 2 out of 4 new replicas have been updated... Waiting for deployment "rolling-nginx" rollout to finish: 3 old replicas are pending termination... Waiting for deployment "rolling-nginx" rollout to finish: 1 old replicas are pending termination... Waiting for deployment "rolling-nginx" rollout to finish: 1 old replicas are pending termination... Waiting for deployment "rolling-nginx" rollout to finish: 1 old replicas are pending termination... Waiting for deployment "rolling-nginx" rollout to finish: 1 old replicas are pending termination... deployment "rolling-nginx" successfully rolled out