k8s工作負載資源之deployment


首先我們要理解:一個應用跑在k8s集群上了,那么這個應用就是一個工作負載(workloads)。

在k8s中會用pod的來承載這個應用,那么負責管理這個pod的東西就叫工作負載資源(workload resources

我們可以簡單理解為是這樣的:

image-20210918102050547

工作負載資源又支持jj自定義或使用第三方資源,這里我們先認識內置的,k8s內置工作負載資源包含如下:

  • deployment
  • replicaset
  • statefulset
  • daemonset
  • jobs
  • cronjob
  • TTL Controller for Finished Resources
  • ReplicationController (逐步被ReplicaSet替代)

那讓我們從最常用的deployment開始吧。

一個 Deployment 為 Pods和 ReplicaSets提供聲明式的更新能力,我們從下面幾個方面開始上手:

  1. 創建 Deployment 將 ReplicaSet 上線。 ReplicaSet 在后台創建 Pods。 檢查 ReplicaSet 的上線狀態,查看其是否成功。
  2. **通過更新 Deployment 的 Pod模板(TemplateSpec),聲明 Pod 的新狀態 。 **新的 ReplicaSet 會被創建,Deployment 以受控速率將 Pod 從舊 ReplicaSet 遷移到新 ReplicaSet。 每個新的 ReplicaSet 都會更新到 Deployment 的修訂版本。
  3. 如果 Deployment 與你的預期不符,可以回滾到較早的 Deployment 版本。 每次回滾都會更新到 Deployment 修訂的新版本。
  4. 通過Deployment 擴大應用規模承擔更多負載
  5. 暫停 Deployment ,對 PodTemplateSpec 做修改然后恢復執行,讓pod更新到新版本。

deployment創建

說了這么多還不如手動寫一個deployment的yml聲明實在(如果你喜歡json也可以是json格式,本質上還是將yml轉換為json格式請求的api)。

下面deployment創建了一個replicaset,這個replicaset將會啟動三個nginx的pod:

nginx-deployment.yml

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

通過kubectl apply 將聲明文件轉換為api提交給apiserver

$ kubectl apply -f nginx-deployment.yml 
deployment.apps/nginx-deployment created

查看deployment資源創建的對象nginx-deployment(這里的對象與編程語言中對象同義)

$ kubectl get deployment
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3/3     3            3           67m

查看nginx-deplyment創建的replicat對象nginx-deployment-767cf44bff

$kubectl get rs
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-767cf44bff   3         3         3       68m

最后是nginx-deployment-767cf44bff創建的三個pod對象

$ kubectl get pod 

NAMESPACE     NAME                                READY   STATUS    RESTARTS   AGE
default       nginx-deployment-767cf44bff-9fj8q   1/1     Running   0          13m
default       nginx-deployment-767cf44bff-f746l   1/1     Running   0          13m
default       nginx-deployment-767cf44bff-ktbzl   1/1     Running   0          13m

也可以通過rollout status 查看 Deployment 上線狀態。

$kubectl rollout status deployment/nginx-deployment
deployment "nginx-deployment" successfully rolled out

這就是deployment資源創建對象的關系圖:

image-20210918111755912

現在我們主要來看一下創建的這個nginx-deployment聲明。

image-20210918154910640

我們把yml文件分為兩個大部分(紅色):

  • 屬性。

    • apiVersion - 創建該對象所使用的 Kubernetes API 的版本
    • kind - 想要創建的對象的類別
    • metadata - 幫助唯一性標識對象的一些數據,包括一個 name 字符串、UID 和可選的 namespace
  • 規格 spec(specification)

    • replicas - 期望的pod副本數量
    • selector - pod標簽選擇器
    • template - pod模板

    我們在selector中匹配包含app=nginx標簽的pod,pod模板中又為新創建的pod打上app=nginx的標簽,這樣就形成了控制閉環。

我們通過可以show-labels查看pod的標簽

$ kubectl get pod  --show-labels
NAME                                READY   STATUS    RESTARTS   AGE   LABELS
nginx-deployment-767cf44bff-9fj8q   1/1     Running   0          81m   app=nginx,pod-template-hash=767cf44bff
nginx-deployment-767cf44bff-f746l   1/1     Running   0          81m   app=nginx,pod-template-hash=767cf44bff
nginx-deployment-767cf44bff-ktbzl   1/1     Running   0          81m   app=nginx,pod-template-hash=767cf44bff

為什么pod中又有一個pod-template-hash標簽?

eployment 控制器將 pod-template-hash 標簽添加到 Deployment 所創建的每一個 ReplicaSet 中。我們來看一下rs的selector描述:

$ kubectl describe rs
Name:           nginx-deployment-767cf44bff
Namespace:      default
Selector:       app=nginx,pod-template-hash=767cf44bff

pod-template-hash 標簽是通過對 ReplicaSet 的 PodTemplate 進行哈希處理,此標簽可確保 Deployment 的子 ReplicaSets 不沖突,所生成的哈希值被添加到 ReplicaSet的selector、Pod 模板labels、以及 ReplicaSet 旗下的任何 Pod 中。這樣deployment下的replicaset只能控制自己的pod。恩,妙哉。

不同工作負載資源所創建的對象,spec是不同的。比如在Deployment中spec可以包含如下字段,這個可以在Kubernetes API中找到。

image-20210918144005483

大多數字段都包含了一個默認值,除非有特殊需求,大多數時候很難被用到。如果需要的時候你再谷歌一下也不遲。到這里deployment工作負載的第一個用例已經成了。


deployment更新

僅當 Deployment Pod 模板(即 .spec.template字段)發生改變時,例如模板的標簽或容器鏡像被更新, 才會觸發 Deployment 上線。

其他更新(如對 Deployment 執行擴縮容的操作)不會觸發上線動作。

image-20210920204824833

  1. 我們可以通過kubectl set 命令更新現有工作負責資源
$ kubectl set image deployment/nginx-deployment nginx-web=nginx:1.17 --record
deployment.apps/nginx-deployment image updated

--record 用於記錄kubectl對資源的操作。便於后期需要時回滾。下面會說到。

kubectl set -h 查詢set支持更新的內容。

Available Commands:

  • env Update environment variables on a pod template
  • image Update image of a pod template
    resources Update resource requests/limits on objects with pod templates
  • selector Set the selector on a resource
  • serviceaccount Update ServiceAccount of a resource
  • subject Update User, Group or ServiceAccount in a RoleBinding/ClusterRoleBinding
  1. 使用kubectl edit編輯deployment后自動更新
$ kubectl edit deployment/nginx-deployment --record
deployment.apps/nginx-deployment edited
  1. 直接更新deployment yml文件

個人覺得最好的方式是更新yml聲明文件,通過kubectl apply 應用即可,這樣你只要管理好你的的nginx-deployment.yml做到心中有數

當我們更新后查看rs狀態,此時deployment 創建了一個新的nginx-deployment replicaset並投入使用。

$ kubectl get rs
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-64f9765d86   4         4         4       4h11m
nginx-deployment-6cf9cc9c9d   0         0         0       5h6m

這里順便看一下deployment中pod滾動更新策略

我們可以通過kubectl describe deployment 查看RollingUpdateStrategy字段,即在滾動更新時最大不可用pod數為1/4,最大可用pod數為期望副本數1.25倍(多25%)。

RollingUpdateStrategy: 25% max unavailable, 25% max surge

假如我們將 deployment_A 中4個副本(pod)更新到deployment_B(也是4副本),其中的某個數據pod狀態如下

$ kubectl get pod 
NAME                                READY   STATUS              RESTARTS   AGE
nginx-deployment-64f9765d86-c9rlj   0/1     ContainerCreating   0          2s
nginx-deployment-64f9765d86-wngmx   0/1     ContainerCreating   0          2s
nginx-deployment-7fcdcb4b75-lmsmm   1/1     Running             0          4h6m
nginx-deployment-7fcdcb4b75-m99tx   1/1     Terminating         0          4h5m
nginx-deployment-7fcdcb4b75-tghb2   1/1     Running             0          4h5m
nginx-deployment-7fcdcb4b75-xfs2m   1/1     Running             0          4h6m

即只有1個在停止,正在創建2個新pod(即將有5個可用),詳細滾動過程可通過kubectl descibe deployment中events查看。

盡量不要更新模板中labels,會造成pod孤立。在某些API版本已經被禁止了。


deployment回滾

deployment回滾和更新一樣,Pod 模板部分會被回滾。

我們通過 rollout history 來查看某個deployment的歷史版本。即之前通過--record所記錄的。

$ kubectl  rollout history   deployment/nginx-deployment 
deployment.apps/nginx-deployment 
REVISION  CHANGE-CAUSE
1         <none>
2         <none>
3         kubectl apply --filename=nginx-deployment.yml --record=true
4         kubectl apply --filename=nginx-deployment.yml --record=true
5         kubectl set image deployment/nginx-deployment nginx-web=nginx:1.17 --record=true
9         kubectl edit deployment/nginx-deployment --record=true
10        kubectl edit deployment/nginx-deployment --record=true

回滾到第5個版本。

$ kubectl rollout undo deployment/nginx-deployment --to-revision=5
deployment.apps/nginx-deployment rolled back

或者直接回滾到上一個版本。

$ kubectl rollout undo deployment/nginx-deployment

還是如前面所說,回滾只一種更工程化的說法,其實回滾也是一種更新,yml聲明依然是核心。所以我們更應該關注的對deployment的yml文件的版本控制。


deployment縮放

縮放控制的是.spec.replicas,也可通過scale命令操作。

$ kubectl scale deployment/nginx-deployment --replicas=6
deployment.apps/nginx-deployment scaled

水平自動縮放本為暫不涉及,后面文章會詳細討論。可以參考:Horizontal Pod Autoscaler


deployment暫停與恢復

我們可以在觸發更新之前暫停 Deployment,然后做多個修改之后再恢復,進行一次性上線。

還是我們之前的deployment

$ kubectl get deploy
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   4/4     4            4           30m

$ kubectl get rs
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-64f9765d86   4         4         4       30m

暫停deployment

$ kubectl rollout pause deployment/nginx-deployment
error: deployments.apps "nginx-deployment" is already paused

對nginx-deployment做一些更新

  1. 直接修改yml文件,更新鏡像為nginx:1.17,並通過kubectl apply應用更改。
  2. 通過set做資源限制。
$ kubectl set resources deployment/nginx-deployment -c=nginx-web --limits=cpu=50m,memory=100Mi
deployment.apps/nginx-deployment resource requirements updated

此時我們查看rs副本狀態,查看deployment版本信息

$ kubectl get rs 
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-64f9765d86   4         4         4       40m

$ kubectl rollout history deployment/nginx-deployment
deployment.apps/nginx-deployment 
REVISION  CHANGE-CAUSE
1         <none>

可以看到還是之前的rs,deployment並沒有將我們的修改應用到對象中。

現在我們將deployment通過Resume恢復

$ kubectl rollout resume deployment/nginx-deployment
deployment.apps/nginx-deployment resumed

查看rs狀態

$ kubectl get rs 
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-64f9765d86   3         3         3       41m
nginx-deployment-7f4447656b   2         2         0       4s

這會deployment已恢復,並應用了對資源對象的更新。


參考:

k8s官方文檔Deployment


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM