--- title: K8S lab5(Deployment) tags: k8s --- K8S lab5(Deployment) === [TOC] ## What is Deployment Deployment 為 Pod 與 Replicaset 提供了一個宣告式的設定 及更新方式。 Deployment 運行應用程序的多個副本,並會自動替換失敗或無響應的 Pod。 通過這種方式,Deployment 有助於確保部屬的 AP 有一個或多個 Pod 可用於服務用戶請求。 Deployment由 Kubernetes Deployment Controller 管理。 Deployment 使用 Pod 模板,其中包含其 Pod 的規範。 Pod 規範決定了每個 Pod 的外觀:哪些應用程序應該在其容器中運行,Pod 應該掛載哪些 Volumes,它的 Label 等等。 當 Deployment 的 Pod 模板發生變化時,會一次自動創建一個新的 Pod。 ## Why Deployment - Create a Deployment to rollout a ReplicaSet - Declare the new state of the Pods - Rollback to an earlier Deployment revision - Scale up the Deployment to facilitate more load - Pause the rollout of a Deployment - Use the status of the Deployment - Clean up older ReplicaSets ## How Deployment ### Deployment 範例 ```yaml= apiVersion: apps/v1 kind: Deployment metadata: name: nginx spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.7.9 ports: - containerPort: 80 ``` 參數說明: - `meta.name`: Deplyment 名稱 - `spec.replicas`: 會建幾個 pod (此範例為:3個) - `spec.selector`: 指定選擇哪些 label 的 pod - `spec.template`: 定義 Pod 的資訊 - `spec.template.metadata`: 定義 pod Label - `spec.template.spec`: 定義 pod 規格,Ex: Containers、Volumes等 ### 建立 Deposit Deployment 1. 製作 deployment.yml ```yaml= apiVersion: apps/v1 kind: Deployment metadata: name: lab-my-deposit spec: replicas: 3 selector: matchLabels: app: lab-my-deposit template: metadata: labels: app: lab-my-deposit spec: containers: - name: my-deposit image: <dockerhub-id>/deposit:v1.0.0 ports: - containerPort: 8080 volumeMounts: - name: app-config mountPath: /app/config readOnly: true volumes: - name: app-config configMap: name: <configmap-name> ``` 2. 刪除舊的Pod ```shell= kubectl delete pods <pod-name> -n <namespace-name> ``` 3. 部屬 Deployment ```shell= kubectl apply -f <path-to-deployment.yml> -n <namespace-name> ``` 4. 加上註解 使用`kubectl annote` 指令,為這次的創立或是更新增加註解 ```shell= kubectl annotate deployment/<depolyment-name> kubernetes.io/change-cause="註解內容" -n <namespace-name> ``` 查看 Deployment 紀錄 ```shell= kubectl rollout history deployment/<depolyment-name> -n <namespace-name> ``` ``` $ kubectl rollout history deployment/lab-my-deposit -n my-namespace deployment.apps/lab-my-deposit REVISION CHANGE-CAUSE 1 create lab-my-deposit ``` 5. 確認 Deployment ```shell= kubectl get deployments -n <namespace-name> ``` ``` $ kubectl get deployments -n my-namespace NAME READY UP-TO-DATE AVAILABLE AGE lab-my-deposit 3/3 3 3 4m56s ``` 6. 確認 Pod ```shell= kubectl get pods -n <namespace-name> ``` ``` $ kubectl get pods -n my-namespace NAME READY STATUS RESTARTS AGE lab-my-deposit-744598d9fb-hkvkr 1/1 Running 0 6m34s lab-my-deposit-744598d9fb-m8vhg 1/1 Running 0 6m34s lab-my-deposit-744598d9fb-s45l6 1/1 Running 0 6m34s ```  7. 測試 API 使用相同 namespace 的 net-tool 進行測試 ``` /app # curl --location --request GET "http://<deposit-service-ip>:8080/api/version" {"version":"v1.0.3"} ``` 總共打了4次,分別可以在三個 Pod 上找到 Log    ### 更新 Deposit Deployment 1. 更新 image 請將新版的程式碼 pull 下來後,包成 jar 後建成 image 並 push 到 dockerhub **ps.版號記得調整,範例為v1.0.0 -> v.1.0.1** **可參考前面lab** 2. 調整 Deployment 調整`spec.template.spec.containers.images` ```yaml= apiVersion: apps/v1 kind: Deployment metadata: name: lab-my-deposit spec: replicas: 3 selector: matchLabels: app: lab-my-deposit template: metadata: labels: app: lab-my-deposit spec: containers: - name: my-deposit image: <dockerhub-id>/deposit:v1.0.1 ports: - containerPort: 8080 volumeMounts: - name: app-config mountPath: /app/config readOnly: true volumes: - name: app-config configMap: name: <configmap-name> ``` 3. 部屬 Deployment ```shell= kubectl apply -f <path-to-deployment.yml> -n <namespace-name> ``` 4. 加上註解 ```shell= kubectl annotate deployment/<depolyment-name> kubernetes.io/change-cause="註解內容" -n <namespace-name> ``` 查看 Deployment 紀錄 ```shell= kubectl rollout history deployment/<depolyment-name> -n <namespace-name> ``` ``` $ kubectl rollout history deployment/lab-my-deposit -n my-namespace deployment.apps/lab-my-deposit REVISION CHANGE-CAUSE 1 create lab-my-deposit 2 update lab-my-deposit to v1.0.1 ``` 5. 確認 Deployment ```shell= kubectl get deployments -n <namespace-name> ``` ``` $ kubectl get deployments -n my-namespace NAME READY UP-TO-DATE AVAILABLE AGE lab-my-deposit 3/3 3 3 4m56s ``` 6. 查看 ReplicaSet - ReplicaSet 是用來確保在資源允許的前提下,運行的 pod 的數量會跟使用者所指令的一致 使用以下指令可以查看 ReplicaSet ```shell= kubectl get rs -n <namespace-name> ``` ``` kubectl get rs -n my-namespace NAME DESIRED CURRENT READY AGE lab-my-deposit-744598d9fb 0 0 0 91m lab-my-deposit-7dcf8f6bd9 3 3 3 90m ``` 可以看到在新的 ReplicaSet 中有三個 Pod 正在運行且舊的 ReplicaSet 已經沒有 Pod 了。 7. 確認 Pod ```shell= kubectl get pods -n <namespace-name> ``` ``` $ kubectl get pods -n my-namespace NAME READY STATUS RESTARTS AGE lab-my-deposit-7dcf8f6bd9-49jt7 1/1 Running 0 6m51s lab-my-deposit-7dcf8f6bd9-5m6v8 1/1 Running 0 6m41s lab-my-deposit-7dcf8f6bd9-jfl9c 1/1 Running 0 6m45s ``` 可以之前建立的 pod 比較會發現,pod name 已經不一樣了,並且也有維持在 deployment.yml 中設定的數量。 8. 測試 API ``` /app # curl --location --request GET "http://10.8.11.8:8080/api/version" {"version":"v1.0.3","datetime":"2022/03/15 18:33:46"} ``` ### 更新 Pod 情境: 當 ConfigMap 更新時,Pod 需要重啟才能用新的 Config 以往: 要人工將 pod 刪除並新建一個 Pod Deployment: 使用 `kubectl restart` 指令 1. 調整 ConfigMap 此處是將 data.application.version 從 v1.0.3 -> v1.0.1 ```yaml= apiVersion: v1 kind: ConfigMap metadata: name: <config-name> data: application.yml: |- server: port: 8080 shutdown: graceful spring: application: name: deposit management: endpoint: shutdown: enabled: true endpoints: web: exposure: include: '*' endpoints: shutdown: enabled: true version: 'v1.0.1' backend-endpoint: 'http://<external-service-name>:8080/api/customer' ``` 2. 部屬 ConfigMap ```shell= kubectl apply -f <path-to-config> -n <namespace-name> ``` 3. 確認 ConfigMap ```shell= kubectl get configmaps -n <namespace-name> <configmap-name> -o yaml ``` ``` $ kubectl get configmaps -n my-namespace deposit-config -o yaml apiVersion: v1 data: application.yml: |- server: port: 8080 shutdown: graceful spring: application: name: deposit management: endpoint: shutdown: enabled: true endpoints: web: exposure: include: '*' endpoints: shutdown: enabled: true version: 'v1.0.1' backend-endpoint: 'http://my-external-service:8080/api/customer' kind: ConfigMap ...以下略 ``` 4. 將 Pod 重啟 ```shell= kubectl rollout restart deployment/<deployment-name> ``` 5. 調整註解 ```shell= kubectl annotate deployment/<depolyment-name> kubernetes.io/change-cause="註解內容" -n <namespace-name> ``` 6. 查看 ReplicaSet ``` kubectl get rs -n <namespace-name> ``` ``` $ kubectl get rs -n my-namespace NAME DESIRED CURRENT READY AGE lab-my-deposit-6ddbc9b55 3 3 3 52m lab-my-deposit-744598d9fb 0 0 0 141m lab-my-deposit-7dcf8f6bd9 0 0 0 141m ``` 已經有新的 ReplicaSet 了 6. 透過describe查看Deploy更換pod的行為 ```shell= kubectl describe deployment -n <namespace-name> <deployment-name> ``` ``` Name: lab-my-deposit-deployment Namespace: default CreationTimestamp: Wed, 16 Mar 2022 15:18:23 +0800 Labels: <none> Annotations: deployment.kubernetes.io/revision: 2 kubernetes.io/change-cause: update version1.0.1 Selector: app=deposit-app 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=deposit-app Containers: my-deposit: Image: asaeeen/deposit1:v1.0.1 Port: 8080/TCP Host Port: 0/TCP Environment: <none> Mounts: /app/config from app-config (ro) Volumes: app-config: Type: ConfigMap (a volume populated by a ConfigMap) Name: deposit-config Optional: false Conditions: Type Status Reason ---- ------ ------ Available True MinimumReplicasAvailable Progressing True NewReplicaSetAvailable OldReplicaSets: <none> NewReplicaSet: lab-my-deposit-deployment-589bb7c95 (3/3 replicas created) Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ScalingReplicaSet 12m deployment-controller Scaled up replica set lab-my-deposit-deployment-c5b476d66 to 3 Normal ScalingReplicaSet 3m54s deployment-controller Scaled up replica set lab-my-deposit-deployment-589bb7c95 to 1 Normal ScalingReplicaSet 3m50s deployment-controller Scaled down replica set lab-my-deposit-deployment-c5b476d66 to 2 Normal ScalingReplicaSet 3m50s deployment-controller Scaled up replica set lab-my-deposit-deployment-589bb7c95 to 2 Normal ScalingReplicaSet 3m47s deployment-controller Scaled down replica set lab-my-deposit-deployment-c5b476d66 to 1 Normal ScalingReplicaSet 3m47s deployment-controller Scaled up replica set lab-my-deposit-deployment-589bb7c95 to 3 Normal ScalingReplicaSet 3m45s deployment-controller Scaled down replica set lab-my-deposit-deployment-c5b476d66 to 0 ``` 可從Events可觀察出:在替換時是會將新的pod啟用後,在殺掉一個舊的pod,如此往復,直到新的set裡面的pod數量達到預期的數量,預設StrategyType為RollingUpdate所形成的行為。 RollingUpdate:  RollingUpdateStrategy: maxUnavailable: 最大不可用數量 預設為25%,即更新過程中不可用的 Pod 的個數上限 maxSurge : 最大峰值數量 6. 測試 API ``` /app # curl --location --request GET "http://10.8.11.8:8080/api/version" {"version":"v1.0.1","datetime":"2022/03/17 09:59:25"} ``` ### 回溯 Deployment 版本 情境: 當發現這次的上版有問題,或是需要退回之前部屬的版本 可以使用 `kubectl rollout undo` 這個指令達成 1. 查看 Deployment 紀錄 ```shell= kubectl rollout history deployment/<depolyment-name> -n <namespace-name> ``` ``` $ kubectl rollout history -n my-namespace deployment/lab-my-deposit deployment.apps/lab-my-deposit REVISION CHANGE-CAUSE 1 create lab-my-deposit 2 update lab-my-deposit to v1.0.1 3 update configmap ``` 2. 回溯到之前版本 ```shell= kubectl rollout undo deployment/<deployment-name> -n <namespace-name> --to-revision=版本 ``` 3. 查看 Deployment 紀錄 ``` $ kubectl rollout history -n my-namespace deployment/lab-my-deposit deployment.apps/lab-my-deposit REVISION CHANGE-CAUSE 2 update lab-my-deposit to v1.0.1 3 update configmap 4 create lab-my-deposit ``` 可以發現 `create lab-my-deposit` 已經變成最新版了 4. 測試 API ``` /app # curl --location --request GET "http://10.8.11.8:8080/api/version" {"version":"v1.0.1"} ``` 已成功退回之前的版本 <!-- 待更新其他 Strategy k8: create 使用k8 模擬 cannary , blue-green --> ### 刪除 Deployment 1. 刪除 Deployment 指令 ```shell= kubectl delete deployments -n <namespace-name> <deployment-name> ``` 2. 確認 Deployment ```shell= kubectl get deployments -n <namespace-name> ``` ``` $ kubectl get deployments -n my-namespace No resources found in my-namespace namespace. ``` 3. 確認 Pod ```shell= kubectl get pods -n <namespace-name> ``` ``` $ kubectl get pods -n my-namespace NAME READY STATUS RESTARTS AGE net-tool 1/1 Running 0 5d17h ``` 可以發現 Pod 裡面已經沒有 deposit 了 ## 參考 - [Kubernetes - Deployments](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) - [Kubernates - Replicaset](https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/) - [GKE - Deployment ](https://cloud.google.com/kubernetes-engine/docs/concepts/deployment) - [Kubernetes Deployment Strategies](https://www.weave.works/blog/kubernetes-deployment-strategies)
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up