Kubernetes:更新與回滾

不羈的羅恩發表於2022-03-01

Blog:部落格園 個人

除了建立,Deployment 提供的另一個重要的功能就是更新應用,這是一個比建立複雜很多的過程。想象一下在日常交付中,線上升級是一個很常見的需求,同時應該儘量保證不能因為升級中斷服務。這就要求我們必須使用一定的策略來決定何時建立新的 Pod,何時刪除舊版本的 Pod。kubectl 支援滾動升級的方式,每次更新一個pod,而不是同時刪除整個服務。

前置知識

回顧知識:

kubectl set image

命令格式:

kubectl set image (-f FILENAME | TYPE NAME) CONTAINER_NAME_1=CONTAINER_IMAGE_1 ... CONTAINER_NAME_N=CONTAINER_IMAGE_N

例如:

Examples:
  # Set a deployment's nginx container image to 'nginx:1.9.1', and its busybox container image to 'busybox'.
  kubectl set image deployment/nginx busybox=busybox nginx=nginx:1.9.1
  
  # Update all deployments' and rc's nginx container's image to 'nginx:1.9.1'
  kubectl set image deployments,rc nginx=nginx:1.9.1 --all
  
  # Update image of all containers of daemonset abc to 'nginx:1.9.1'
  kubectl set image daemonset abc *=nginx:1.9.1
  
  # Print result (in yaml format) of updating nginx container image from local file, without hitting the server
  kubectl set image -f path/to/file.yaml nginx=nginx:1.9.1 --local -o yaml

?Tips:支援縮寫,如pod (po), replicationcontroller (rc), deployment (deploy), daemonset (ds), replicaset (rs)。

選項

--all=false: Select all resources, including uninitialized ones, in the namespace of the specified resource types
      --allow-missing-template-keys=true: If true, ignore any errors in templates when a field or map key is missing in
the template. Only applies to golang and jsonpath output formats.
      --dry-run='none': Must be "none", "server", or "client". If client strategy, only print the object that would be
sent, without sending it. If server strategy, submit server-side request without persisting the resource.
      --field-manager='kubectl-set': Name of the manager used to track field ownership.
  -f, --filename=[]: Filename, directory, or URL to files identifying the resource to get from a server.
  -k, --kustomize='': Process the kustomization directory. This flag can't be used together with -f or -R.
      --local=false: If true, set image will NOT contact api-server but run locally.
  -o, --output='': Output format. One of:
json|yaml|name|go-template|go-template-file|template|templatefile|jsonpath|jsonpath-as-json|jsonpath-file.
      --record=false: Record current kubectl command in the resource annotation. If set to false, do not record the
command. If set to true, record the command. If not set, default to updating the existing annotation value only if one
already exists.
  -R, --recursive=false: Process the directory used in -f, --filename recursively. Useful when you want to manage
related manifests organized within the same directory.
  -l, --selector='': Selector (label query) to filter on, not including uninitialized ones, supports '=', '==', and
'!='.(e.g. -l key1=value1,key2=value2)
      --show-managed-fields=false: If true, keep the managedFields when printing objects in JSON or YAML format.
      --template='': Template string or path to template file to use when -o=go-template, -o=go-template-file. The
template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].

示例

建立deployment

先建立一個deployment,ngx-deploy.yaml配置檔案如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.16.0
          ports:
            - containerPort: 80

執行命令:

kubectl create -f ngx-deploy.yaml

使用 watch 方式來觀測 deployment 的狀態變化:

[root@master test]# kubectl get deploy nginx-deployment -w
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   0/2     2            0           14s
nginx-deployment   1/2     2            1           25s
nginx-deployment   2/2     2            2           38s

說明:

  • NAME:deployment 的名字。
  • READY:就是當前有多少個 Pod 處於執行中/期望有多少個 Pod。
  • UP-TO-DATE:達到最新狀態的 Pod 的數量。當 Deployment 在進行更新時,會有新老版本的 Pod 同時存在,這時候這個欄位會比較有用。
  • AVAILABLE:可用的 Pod。上個實驗我們講了健康檢查的相關配置,Pod 執行中和可以提供服務是不同的概念。
  • AGE::deployment 執行的時間。

更新映象

接下來先更新一個nginx映象,版本為1.18:

kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.18.0 --record

說明:

  • --record :將這條命令記錄到了 deployment 的 yaml 的 annotations 裡,可用於回滾映象。

使用watch方式觀察deployment例項變更情況:

[root@master test]# kubectl get deploy nginx-deployment -w
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   2/2     1            2           3m41s
nginx-deployment   3/2     1            3           3m58s
nginx-deployment   2/2     1            2           3m58s
nginx-deployment   2/2     2            2           3m58s

可以通過 get yaml 看到:

[root@master test]# kubectl get deploy nginx-deployment -o yaml
...
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:1.18.0
        imagePullPolicy: IfNotPresent
        name: nginx
        ports:
        - containerPort: 80
          protocol: TCP
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
...

回滾映象

有更新就有回滾。比如新的映象版本有問題,或者配置不對等等,這是部署到生產環境裡經常發生的事情。相對於更新,回滾映象一般都是出現了問題,需要更快地進行處理。Deployment 的回滾機制正是為此而生。

可以通過命令檢視歷史版本:

[root@master test]# kubectl rollout history deployment.v1.apps/nginx-deployment
deployment.apps/nginx-deployment 
REVISION  CHANGE-CAUSE
1         <none>
2         kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.18.0 --record=true

回滾到上一個版本:

kubectl rollout undo deployment.v1.apps/nginx-deployment

可以觀察到已回到上個版本:

[root@master test]# kubectl get deploy nginx-deployment -o yaml
...
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:1.16.0
        imagePullPolicy: IfNotPresent
        name: nginx
        ports:
        - containerPort: 80
          protocol: TCP
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
...

也可回滾到指定版本:

kubectl rollout undo deployment.v1.apps/nginx-deployment --to-revision=2

相關文章