除了建立,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