什么是滚动更新

滚动更新是一次只更新一小部分副本,成功后再更新更多的副本,最终完成所有副本的更新。
滚动更新的最大好处是零停机,整个更新过程始终有副本在运行,从而保证了业务的连续性

实践

下面我们部署三副本应用,初始镜像为httpd:2.2.31,然后将其更新到httpd:2.2.32

[k8s@server1 ~]$ cat httpd.yml 
apiVersion: apps/v1
kind: Deployment
metadata:
 name: httpd
spec:
 replicas: 3
 selector:
  matchLabels:
   run: httpd
 template:
  metadata:
   labels:
    run: httpd
  spec:
   containers:
   - name: httpd
     image: httpd:2.2.31
     ports:
     - containerPort: 80

# 通过kubectl apply部署
[k8s@server1 ~]$ kubectl apply -f httpd.yml 
[k8s@server1 ~]$ kubectl get deployment httpd -o wide
NAME    READY   UP-TO-DATE   AVAILABLE   AGE     CONTAINERS   IMAGES         SELECTOR
httpd   3/3     3            3           2m55s   httpd        httpd:2.2.31   run=httpd
[k8s@server1 ~]$ kubectl get replicaset  -o wide
NAME               DESIRED   CURRENT   READY   AGE    CONTAINERS   IMAGES         SELECTOR
httpd-56df754d56   3         3         3       3m9s   httpd        httpd:2.2.31   pod-template-hash=56df754d56,run=httpd
[k8s@server1 ~]$ kubectl get pod
NAME                     READY   STATUS    RESTARTS   AGE
httpd-56df754d56-2sqfd   1/1     Running   0          3m14s
httpd-56df754d56-jdgkf   1/1     Running   0          3m14s
httpd-56df754d56-rl9z8   1/1     Running   0          3m14s

部署过程如下:

  • (1)创建Deployment httpd
  • (2)创建ReplicaSet(容器副本) httpd-56df754d56
  • (3)创建三个Pod
  • (4)当前镜像为httpd:2.2.31

将配置文件中的httpd:2.2.31替换为httpd:2.2.32,再次执行kubectl apply

[k8s@server1 ~]$ cat httpd.yml 
apiVersion: apps/v1
kind: Deployment
metadata:
 name: httpd
spec:
 replicas: 3
 selector:
  matchLabels:
   run: httpd
 template:
  metadata:
   labels:
    run: httpd
  spec:
   containers:
   - name: httpd
     image: httpd:2.2.32
     ports:
     - containerPort: 80

# 注意:要等待一些时间

[k8s@server1 ~]$ kubectl get pod
NAME                     READY   STATUS    RESTARTS   AGE
httpd-77896d99b5-hz579   1/1     Running   0          5m3s
httpd-77896d99b5-rnjfn   1/1     Running   0          3m32s
httpd-77896d99b5-x7fd9   1/1     Running   0          4m20s
[k8s@server1 ~]$ kubectl get replicaset  -o wide
NAME               DESIRED   CURRENT   READY   AGE    CONTAINERS   IMAGES         SELECTOR
httpd-56df754d56   0         0         0       10m    httpd        httpd:2.2.31   pod-template-hash=56df754d56,run=httpd
httpd-77896d99b5   3         3         3       5m5s   httpd        httpd:2.2.32   pod-template-hash=77896d99b5,run=httpd
[k8s@server1 ~]$ kubectl get deployment httpd -o wide
NAME    READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES         SELECTOR
httpd   3/3     3            3           10m   httpd        httpd:2.2.32   run=httpd

我们发现了如下变化:

  • (1)Deployment httpd的镜像更新为httpd:2.2.32。
  • (2)新创建了ReplicaSethttpd-77896d99b5,镜像为httpd:2.2.32,并且管理了三个新的Pod。
  • (3)之前的ReplicaSet httpd-56df754d56里面已经没有任何Pod。结论是:ReplicaSet httpd-56df754d56的三个httpd:2.2.31 Pod已经被ReplicaSet httpd-77896d99b5的三个httpd:2.2.32 Pod替换了

具体过程可以通过kubectl describe deployment httpd查看

[k8s@server1 ~]$ kubectl describe deployment httpd
Name:                   httpd
Namespace:              default
CreationTimestamp:      Sun, 25 Aug 2019 15:15:27 +0800
Labels:                 run=httpd
Annotations:            deployment.kubernetes.io/revision: 2
                        kubectl.kubernetes.io/last-applied-configuration:
                          {"apiVersion":"apps/v1beta1","kind":"Deployment","metadata":{"annotations":{},"name":"httpd","namespace":"default"},"spec":{"replicas":3,"...
Selector:               run=httpd
Replicas:               3 desired | 3 updated | 3 total | 3 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  run=httpd
  Containers:
   httpd:
    Image:        httpd:2.2.32
    Port:         80/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
  Progressing    True    NewReplicaSetAvailable
OldReplicaSets:  <none>
NewReplicaSet:   httpd-77896d99b5 (3/3 replicas created)
Events:
  Type    Reason             Age    From                   Message
  ----    ------             ----   ----                   -------
  Normal  ScalingReplicaSet  13m    deployment-controller  Scaled up replica set httpd-56df754d56 to 3
  Normal  ScalingReplicaSet  8m2s   deployment-controller  Scaled up replica set httpd-77896d99b5 to 1
  Normal  ScalingReplicaSet  7m19s  deployment-controller  Scaled down replica set httpd-56df754d56 to 2
  Normal  ScalingReplicaSet  7m19s  deployment-controller  Scaled up replica set httpd-77896d99b5 to 2
  Normal  ScalingReplicaSet  6m31s  deployment-controller  Scaled down replica set httpd-56df754d56 to 1
  Normal  ScalingReplicaSet  6m31s  deployment-controller  Scaled up replica set httpd-77896d99b5 to 3
  Normal  ScalingReplicaSet  6m30s  deployment-controller  Scaled down replica set httpd-56df754d56 to 0

回滚

kubectl apply每次更新应用时,Kubernetes都会记录下当前的配置,保存为一个revision(版次),这样就可以回滚到某个特定 revision

默认配置下,Kubernetes只会保留最近的几个revision,可以在Deployment配置文件中通过revisionHistoryLimit属性增加revision数量

实践回滚功能

应用有三个配置文件,即httpd.v1.yml、httpd.v2.yml和httpd.v3.yml,分别对应不同的httpd镜像2.4.16、2.4.17

# 可以删除之前的应用 
# 注意:删除和创建都是需要时间的
[k8s@server1 ~]$ kubectl delete deployment httpd 
deployment.apps "httpd" deleted
[k8s@server1 ~]$ cat httpd.v1.yml 
apiVersion: apps/v1
kind: Deployment
metadata:
 name: httpd
spec:
 revisionHistoryLimit: 10
 replicas: 3
 selector:
  matchLabels:
   run: httpd
 template:
  metadata:
   labels:
    run: httpd
  spec:
   containers:
   - name: httpd
     image: httpd:2.4.16
     ports:
     - containerPort: 80


[k8s@server1 ~]$ cat httpd.v2.yml 
apiVersion: apps/v1
kind: Deployment
metadata:
 name: httpd
spec:
 revisionHistoryLimit: 10
 replicas: 3
 selector:
  matchLabels:
   run: httpd
 template:
  metadata:
   labels:
    run: httpd
  spec:
   containers:
   - name: httpd
     image: httpd:2.4.17
     ports:
     - containerPort: 80
     

[k8s@server1 ~]$ cat httpd.v3.yml 
apiVersion: apps/v1
kind: Deployment
metadata:
 name: httpd
spec:
 revisionHistoryLimit: 10
 replicas: 3
 selector:
  matchLabels:
   run: httpd
 template:
  metadata:
   labels:
    run: httpd
  spec:
   containers:
   - name: httpd
     image: httpd:2.4.18
     ports:
     - containerPort: 80

通过kubectl apply部署并更新应用

[k8s@server1 ~]$ kubectl apply -f httpd.v1.yml --record
deployment.apps/httpd configured
[k8s@server1 ~]$ kubectl apply -f httpd.v2.yml --record
deployment.apps/httpd configured
[k8s@server1 ~]$ kubectl apply -f httpd.v3.yml --record
deployment.apps/httpd configured
[k8s@server1 ~]$ kubectl get deployment httpd -o wide
NAME    READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES         SELECTOR
httpd   3/3     1            3           44m   httpd        httpd:2.4.18   run=httpd


注意:是替换,并不会重新创建新的容器,最终只创建了三个容器

–record的作用是将当前命令记录到revision记录中,这样我们就可以知道每个revison对应的是哪个配置文件了。通过kubectl rollout history deployment httpd查看revison历史记录

[k8s@server1 ~]$ kubectl rollout history deployment httpd 
deployment.extensions/httpd 
REVISION  CHANGE-CAUSE
1         <none>
2         <none>
3         kubectl apply --filename=httpd.v1.yml --record=true
4         kubectl apply --filename=httpd.v2.yml --record=true
5         kubectl apply --filename=httpd.v3.yml --record=true

CHANGE-CAUSE就是–record的结果。如果要回滚到某个版本,比如revision 3,可以执行命令kubectl rollout undo deployment httpd --to-revision=3

[k8s@server1 ~]$ kubectl rollout undo deployment httpd --to-revision=3 
deployment.extensions/httpd rolled back
[k8s@server1 ~]$ kubectl get deployment httpd -o wide
NAME    READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES         SELECTOR
httpd   3/3     1            3           46m   httpd        httpd:2.4.16   run=httpd

此时,revison历史记录也会发生相应变化

[k8s@server1 ~]$ kubectl rollout history deployment httpd 
deployment.extensions/httpd 
REVISION  CHANGE-CAUSE
1         <none>
2         <none>
5         kubectl apply --filename=httpd.v3.yml --record=true
6         kubectl apply --filename=httpd.v2.yml --record=true
7         kubectl apply --filename=httpd.v1.yml --record=true

滚动更新采用渐进的方式逐步替换旧版本Pod。如果更新不如预期,可以通过回滚操作恢复到更新前的状态

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐