k8s-deployment

張鐵牛發表於2021-12-15

1. 簡介

一個 DeploymentPodsReplicaSets 提供宣告式的更新能力。

使用者負責描述 Deployment 中的 目標狀態,而 Deployment 控制器(Controller)以受控速率更改實際狀態, 使其變為期望狀態。你可以定義 Deployment 以建立新的 ReplicaSet,或刪除現有 Deployment, 並通過新的 Deployment 收養其資源。

ReplicaSet 的目的是維護一組在任何時候都處於執行狀態的 Pod 副本的穩定集合。 因此,它通常用來保證給定數量的、完全相同的 Pod 的可用性。

也就是 Deployment 通過管理 ReplicaSet 來確保任何時間都有指定數量的 Pod 副本在執行。

2. quick start

2.1 建立deploy

如果沒有現成的模板,可以使用 --dry-run 快速生成一個deploy資源模板

$ kubectl create deploy nginx-test --image=nginx --dry-run=client --replicas=3  -oyaml -n test1

# 輸出內容如下
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: nginx-test
  name: nginx-test
  namespace: test1
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx-test
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx-test
    spec:
      containers:
      - image: nginx
        name: nginx
        resources: {}
status: {}

新建一個deploy模板 deploy-nginx.yaml,內容如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    # 自定義標籤
    app: nginx-deploy-test
  # 資源名稱
  name: nginx-test-1
  namespace: test1
spec:
  # pod 副本數量
  replicas: 3
  # 模板選擇器
  selector:
    matchLabels:
      # 選擇下方宣告的 template
      app: nginx-test
  template:
    metadata:
      labels:
        app: nginx-test
    spec:
      containers:
      - image: nginx
        name: nginx

建立deploy

$ kubectl create -f deploy-nginx.yaml

在該例中:

  • 建立名為nginx-test-1(由 .metadata.name 欄位標明)的 deployment
  • 該deployment建立三個(由 replicas 欄位標明)Pod副本
  • selector 欄位定義 Deployment 如何查詢要管理的 Pods。 在這裡,選擇在 Pod 模板中定義的標籤(app: nginx-test)。 不過,更復雜的選擇規則是也可能的,只要 Pod 模板本身滿足所給規則即可。
  • template欄位包含以下子欄位:
    • Pod 被使用 labels 欄位打上 app: nginx-test 標籤。
    • Pod 模板約定(即 .template.spec 欄位) Pods nginx 容器。
    • 建立一個容器並使用 name 欄位將其命名為 nginx

說明:

spec.selector.matchLabels 欄位是 {key,value} 鍵值對對映。 在 matchLabels 對映中的每個 {key,value} 對映等效於 matchExpressions 中的一個元素, 即其 key 欄位是 “key”,operator 為 “In”,values 陣列僅包含 “value”。 在 matchLabelsmatchExpressions 中給出的所有條件都必須滿足才能匹配。

2.2 檢視deploy

檢視deploy 基本資訊

# kubectl get -f deploy-nginx.yaml
$ kubectl get deploy -n test1

NAME           READY   UP-TO-DATE   AVAILABLE   AGE
nginx-test-1   3/3     3            3           4m20s

檢視deploy 詳細資訊

# kubectl get -f deploy-nginx.yaml -o wide
$ kubectl get deploy -n test1 -o wide

NAME           READY   UP-TO-DATE   AVAILABLE   AGE     CONTAINERS   IMAGES   SELECTOR
nginx-test-1   3/3     3            3           4m54s   nginx        nginx    app=nginx-test

檢視deploy 詳情資訊

# kubectl describe deploy/nginx-test-1 -n test1
$ kubectl describe -f deploy-nginx.yaml

Name:                   nginx-test-1
Namespace:              test1
CreationTimestamp:      Sun, 12 Dec 2021 22:38:12 +0800
Labels:                 app=nginx-deploy-test
Annotations:            deployment.kubernetes.io/revision: 1
Selector:               app=nginx-test
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:  app=nginx-test
  Containers:
   nginx:
    Image:        nginx
    Port:         <none>
    Host Port:    <none>
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
  Progressing    True    NewReplicaSetAvailable
OldReplicaSets:  <none>
NewReplicaSet:   nginx-test-1-795d659f45 (3/3 replicas created)
Events:
  Type    Reason             Age    From                   Message
  ----    ------             ----   ----                   -------
  Normal  ScalingReplicaSet  6m58s  deployment-controller  Scaled up replica set nginx-test-1-795d659f45 to 3

檢視pod情況

$ kubectl get po -n test1

NAME                            READY   STATUS    RESTARTS   AGE
nginx-test-1-795d659f45-7rlq7   1/1     Running   0          15m
nginx-test-1-795d659f45-dfjfb   1/1     Running   0          15m
nginx-test-1-795d659f45-m45qn   1/1     Running   0          15m

檢視deploy上線狀態

$ kubectl rollout status deploy/nginx-test-1 -n test1

deployment "nginx-test-1" successfully rolled out

2.3 修改deploy

說明: 僅當 Deployment Pod 模板(即 .spec.template)發生改變時,例如模板的標籤或容器映象被更新, 才會觸發 Deployment 上線。 其他更新(如對 Deployment 執行擴縮容的操作)不會觸發上線動作。

  1. 直接修改資源模板,修改完直接apply即可

    $ kubectl apply -f deploy-nginx.yaml
    
  2. 使用命令修改,修改完儲存即可

    $ kubectl edit deploy/nginx-test-1 -n test1
    
  3. 修改映象版本

    • --record=true 記錄當前操作,後續會用到
    $ kubectl set image deploy/nginx-test-1 nginx=nginx:1.16.1 -n test1 --record=true
    

2.4 刪除deploy

  1. 使用命令刪除

    $ kubectl delete deploy/nginx-test-1 -n test1
    
  2. 使用資原始檔

    $ kubectl delete -f deploy-nginx.yaml
    

3. 更新服務版本

3.1 建立deploy

deploy-nginx.yaml deploy 模板資訊如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx-deploy-test
  name: nginx-test-1
  namespace: test1
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx-test
  template:
    metadata:
      labels:
        app: nginx-test
    spec:
      containers:
      - image: nginx:1.16.1
        name: nginx

3.2 修改deploy檔案更新

# 修改模板檔案中的映象版本號
$ sed -i 's/nginx:1.16.1/nginx:latest/g' deploy-nginx.yaml
# 應用修改後的模板檔案
# --record的作用是將當前命令記錄到 revision 記錄中,這樣就可以知道每個 revison 對應的是哪個配置檔案。
$ kubectl apply -f deploy-nginx.yaml --record

我們從圖中可以看到pod執行過程是等待新的pod啟動完成,在進行銷燬舊的pod,這樣就完成了叢集的滾動更新工作

更新完成後我們也可以檢視一下迭代資訊和修訂歷史詳細資訊

3.2 使用edit命令更新

$ kubectl edit deploy/nginx-test-1 -n test1

deployment.apps/nginx-test-1 edited

一般臨時修改一下部署資訊會使用一下edit。

一般不太推薦使用edit進行編輯,推出即儲存。雖然版本更新成功了,history也有保留,但是最終的修改記錄沒有持久化到模板檔案中。

3.3 使用set image 命令更新

# nginx=nginx:1.16.1 <container-name>=<image-name>:<version>
$ kubectl set image deploy/nginx-test-1 -n test1 nginx=nginx:1.16.1 --record

能比edit更新強點,至少可以很清楚的在history中檢視版本更新的情況

4. 回滾服務版本

我們使用上面的更新應用時k8s都會記錄一個revision(版本),這樣我們就可以通過這個版本記錄回滾到特定的版本中

  1. 回滾到上一個版本

    $ kubectl rollout undo deploy/nginx-test-1  -n test1
    
  2. 回滾到指定版本

    $ kubectl rollout undo deploy/nginx-test-1 --to-revision=3 -n test1
    

rollout命令引數如下

$ kubectl rollout -h
Manage the rollout of a resource.

 Valid resource types include:

  *  deployments
  *  daemonsets
  *  statefulsets

Examples:
  # Rollback to the previous deployment
  kubectl rollout undo deployment/abc

  # Check the rollout status of a daemonset
  kubectl rollout status daemonset/foo

Available Commands:
  history     顯示 rollout 歷史
  pause       標記提供的 resource 為中止狀態
  restart     Restart a resource
  resume      繼續一個停止的 resource
  status      顯示 rollout 的狀態
  undo        撤銷上一次的 rollout

Usage:
  kubectl rollout SUBCOMMAND [options]

預設配置下,k8s 只會保留最近的幾個 revision,可以在 Deployment 配置檔案中通過 revisionHistoryLimit 屬性增加 revision 數量。(同時rs和我們rollout中記錄的版本號相同,可以理解為rollout中顯示的REVISION版本號實際上就是rs中的版本)

revisionHistoryLimit(歷史版本記錄):Deployment revision history儲存在它控制的ReplicaSets中。預設儲存記錄10個     .spec.revisionHistoryLimit 是一個可選配置項,用來指定可以保留的舊的ReplicaSet數量。
    該理想值取決於心Deployment的頻率和穩定性。如果該值沒有設定的話,預設所有舊的Replicaset或會被保留,將資源儲存在etcd中,是用kubectl get rs檢視輸出。
    每個Deployment的該配置都儲存在ReplicaSet中,然而,一旦刪除的舊的RepelicaSet,Deployment就無法再回退到那個revison了。   
    如果將該值設定為0,所有具有0個replica的ReplicaSet都會被刪除。在這種情況下,新的Deployment rollout無法撤銷,因為revision history都被清理掉了。 PS:為了儲存版本升級的歷史,需要再建立Deployment物件時,在命令中使用"record"選項

一般配合revisionHistoryLimit使用的strategy (更新策略)

strategy(更新策略):  
    .spec.strategy 指定新的Pod替換舊的Pod的策略。 .spec.strategy.type 可以是"Recreate"或者是 "RollingUpdate"。"RollingUpdate"是預設值。  
    Recreate: 重建式更新,就是刪一個建一個。類似於ReplicaSet的更新方式,即首先刪除現有的Pod物件,然後由控制器基於新模板重新建立新版本資源物件。   
    rollingUpdate:滾動更新,簡單定義 更新期間pod最多有幾個等。可以指定maxUnavailable 和 maxSurge 來控制 rolling update 程式。   
    maxSurge:.spec.strategy.rollingUpdate.maxSurge 是可選配置項,用來指定可以超過期望的Pod數量的最大個數。該值可以是一個絕對值(例如5)或者是期望的Pod數量的百分比(例如10%)。當MaxUnavailable為0時該值不可以為0。通過百分比計算的絕對值向上取整。預設值是1。   
    例如,該值設定成30%,啟動rolling update後新的ReplicatSet將會立即擴容,新老Pod的總數不能超過期望的Pod數量的130%。舊的Pod被殺掉後,新的ReplicaSet將繼續擴容,舊的ReplicaSet會進一步縮容,確保在升級的所有時刻所有的Pod數量和不會超過期望Pod數量的130%。   
    maxUnavailable:.spec.strategy.rollingUpdate.maxUnavailable 是可選配置項,用來指定在升級過程中不可用Pod的最大數量。該值可以是一個絕對值(例如5),也可以是期望Pod數量的百分比(例如10%)。通過計算百分比的絕對值向下取整。  如果.spec.strategy.rollingUpdate.maxSurge 為0時,這個值不可以為0。預設值是1。   
    例如,該值設定成30%,啟動rolling update後舊的ReplicatSet將會立即縮容到期望的Pod數量的70%。新的Pod ready後,隨著新的ReplicaSet的擴容,舊的ReplicaSet會進一步縮容確保在升級的所有時刻可以用的Pod數量至少是期望Pod數量的70%。 PS:maxSurge和maxUnavailable的屬性值不可同時為0,否則Pod物件的副本數量在符合使用者期望的數量後無法做出合理變動以進行更新操作。   
    在配置時,使用者還可以使用Deployment控制器的spec.minReadySeconds屬性來控制應用升級的速度。新舊更替過程中,新建立的Pod物件一旦成功響應就緒探測即被認為是可用狀態,然後進行下一輪的替換。而spec.minReadySeconds能夠定義在新的Pod物件建立後至少需要等待多長的時間才能會被認為其就緒,在該段時間內,更新操作會被阻塞。

完整的revisionHistoryLimit配置如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx-deploy-test
  name: nginx-test-1
  namespace: test1
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx-test
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: nginx-test
    spec:
      containers:
      - image: nginx:latest
        name: nginx

4. 服務副本縮放

  1. 使用scale命令修改

    $ kubectl scale deploy/nginx-test-1 --replicas=2 -n test1
    

  1. 使用edit命令修改

    直接使用edit命令修改 .spec.replicas 屬性值即可

    $ kubectl edit deploy/nginx-test-1 -n test1
    
  2. 直接修改模板中的 .spec.replicas屬性值即可

當然我們也可以設定自動縮放功能,這裡先簡單提及一下,完了專門寫一篇說這個事情。

基於現有 Pods 的 CPU 利用率選擇 要執行的 Pods 個數下限和上限。

$ kubectl autoscale deploy/nginx-test-1 --min=10 --max=15 --cpu-percent=80