如何使用示例执行Kubernetes RollingUpdate

时间:2020-01-09 10:41:07  来源:igfitidea点击:

在本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

这次我将使用--recordkubectl 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