跳至主要内容

Basic - Creating a Deployment

什麼是 Deployment

在 Kubernetes 中,Deployment 是一種高層次的 API 資源,用於管理應用程式的部署和擴展。它提供了一種聲明式的方法來定義應用程式的所需狀態,並由 Kubernetes 控制平面自動執行所需的更改,確保集群中的實際狀態匹配所需狀態。


Deployment 的核心功能

  1. 管理 Pod 的生命週期
    • Deployment 會管理基於 Pod 的應用程式,確保指定數量的 Pod 副本運行,並監控其健康狀態。
  2. 滾動更新與回滾
    • 滾動更新:允許逐步更新應用程式,無需停機。
    • 回滾:如果更新失敗,可以快速恢復到之前的穩定版本。
  3. 自動化擴展與縮減
    • Deployment 支援透過 Horizontal Pod Autoscaler (HPA) 自動調整 Pod 的數量。
  4. 容錯恢復
    • 如果某些 Pod 發生故障,Deployment 會自動重新創建或替換,確保應用程式的穩定運行。

實作一個 Deployment

定義並製作一個 Deployment

  1. 我們定義兩個 deployment,為了要讓這兩個 Pod 的版本個別擁有一個 Replica Set,這一就能自由實現自動縮放
deployment.yaml
# 定義第一個 Deployment,用於管理版本 v1 的應用
apiVersion: apps/v1 # API 版本,Deployment 使用的是 apps/v1 版本。
kind: Deployment # 資源類型為 Deployment,用於部署和管理 Pod。
metadata:
name: v1-deployment # Deployment 的名稱,唯一標識該資源。
labels:
type: demo-v1 # 自定義標籤,用於標識此 Deployment 為 demo-v1 類型。
spec:
replicas: 3 # 需要運行的 Pod 副本數量,設為 3。
selector: # 定義 Deployment 如何選擇管理的 Pod。
matchLabels:
type: demo-v1 # 匹配具有 `type: demo-v1` 標籤的 Pod。
template: # Pod 的模板,用於創建 Pod。
metadata:
labels:
type: demo-v1 # Pod 的標籤,需與 selector 的條件一致。
spec:
containers: # 定義 Pod 中的容器。
- name: v1 # 容器名稱,標識為 "v1"。
image: hello-world:v1.0.0 # 容器使用的映像,版本為 v1.0.0。
ports:
- containerPort: 8080 # 定義容器內部開放的服務端口。
---
# 定義第二個 Deployment,用於管理版本 v2 的應用
apiVersion: apps/v1
kind: Deployment
metadata:
name: v2-deployment # Deployment 的名稱,唯一標識該資源。
labels:
type: demo-v2 # 自定義標籤,用於標識此 Deployment 為 demo-v2 類型。
spec:
replicas: 2 # 需要運行的 Pod 副本數量,設為 2。
selector:
matchLabels:
type: demo-v2 # 匹配具有 `type: demo-v2` 標籤的 Pod。
template:
metadata:
labels:
type: demo-v2 # Pod 的標籤,需與 selector 的條件一致。
spec:
containers:
- name: v2 # 容器名稱,標識為 "v2"。
image: hello-world:v2.0.0 # 容器使用的映像,版本為 v2.0.0。
ports:
- containerPort: 8080
  1. 透過 kubectl 來執行他
kubectl.exe apply -f deployment.yaml
---

deployment.apps/v1-deployment created
deployment.apps/v2-deployment created
  1. 我們可以透過指令或是 dashboard 看見他們成功被創立,而且 pod 數量 v1 是 3 個,v2 是 2 個
kubectl.exe get all
---

NAME READY STATUS RESTARTS AGE
pod/v1-deployment-76f7b58999-544kx 1/1 Running 0 39s
pod/v1-deployment-76f7b58999-plxqm 1/1 Running 0 39s
pod/v1-deployment-76f7b58999-w9qsf 1/1 Running 0 39s
pod/v2-deployment-96fc9cb46-7h4f7 1/1 Running 0 39s
pod/v2-deployment-96fc9cb46-jjzpw 1/1 Running 0 39s

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 86d

NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/v1-deployment 3/3 3 3 39s
deployment.apps/v2-deployment 2/2 2 2 39s

NAME DESIRED CURRENT READY AGE
replicaset.apps/v1-deployment-76f7b58999 3 3 3 39s
replicaset.apps/v2-deployment-96fc9cb46 2 2 2 39s

hello-world-deployments

更新 Deployment 實現水平擴展

  1. 我們可以透過更改 yaml 檔裡面的 replicas 數量來實現擴展,kubenetes 會自動幫我們調整
deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: v1-deployment
labels:
type: demo-v1
spec:
# 我們可以將Pod Replicas設定為2
replicas: 2
selector:
matchLabels:
type: demo-v1
template:
metadata:
labels:
type: demo-v1
spec:
containers:
- name: v1
image: hello-world:v1.0.0
ports:
- containerPort: 8080
---
...V2沒有更動省略...
  1. 透過指令執行他,我們可以觀察到只有 v1 有改變
kubectl.exe apply -f deployment.yaml
---

deployment.apps/v1-deployment configured
deployment.apps/v2-deployment unchanged
  1. 透過 rollout status 我們可以查看 deployment 資源管理的狀態,如果設定錯誤或是更新失敗,狀態將會等待直到 timeout
kubectl.exe rollout status deployment v1-deployment
---

deployment "v1-deployment" successfully rolled out
  1. 另外我們也可以透過指令來修改 replicas 的數量
kubectl.exe scale deployment v1-deployment --replicas 2
---

deployment.apps/v1-deployment scaled
  1. 從指令和 dashboard 都可以看出 v1 只剩下兩個 pod
kubectl.exe get all
---

NAME READY STATUS RESTARTS AGE
pod/v1-deployment-76f7b58999-544kx 1/1 Running 0 20m
pod/v1-deployment-76f7b58999-plxqm 1/1 Running 0 20m
pod/v2-deployment-96fc9cb46-7h4f7 1/1 Running 0 20m
pod/v2-deployment-96fc9cb46-jjzpw 1/1 Running 0 20m

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 86d

NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/v1-deployment 2/2 2 2 20m
deployment.apps/v2-deployment 2/2 2 2 20m

NAME DESIRED CURRENT READY AGE
replicaset.apps/v1-deployment-76f7b58999 2 2 2 20m
replicaset.apps/v2-deployment-96fc9cb46 2 2 2 20m

hello-world-v1-deployments-scale

使用 Rollout 來查看裡使版本並回滾

  1. 首先,只有在 spec.template 更改時才能被記住,我們可以在 yaml 中增加 annotations 來說明這次修改的原因,或是事後透過指令增加 annotation
deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: v1-deployment
labels:
type: demo-v1
# 手動添加描述本次變更的原因
annotations:
kubernetes.io/change-cause: "Scaled replicas to 2"
spec:
replicas: 2
selector:
matchLabels:
type: demo-v1
template:
metadata:
labels:
type: demo-v1
spec:
containers:
- name: v1
image: hello-world:v1.0.0
ports:
- containerPort: 8080
---
...V2沒有更動省略...
kubectl annotate deployment v1-deployment kubernetes.io/change-cause="Scaled replicas to 2"
---

deployment.apps/v1-deployment
REVISION CHANGE-CAUSE
1 Scaled replicas to 2
  1. 透過指令查看紀錄的原因
kubectl.exe rollout history deployment v1-deployment
---

deployment.apps/v1-deployment
REVISION CHANGE-CAUSE
1 Scaled replicas to 2
  1. 在上一篇的 pod 之中再多包版一個 image,叫做 V1.0.1,內容不用更改
docker build -t hello-world:v1.0.1 --build-arg VERSION=v1 .
---

[+] Building 2.8s (15/15) FINISHED
=> [internal] load build definition from dockerfile 0.0s
...中間省略...
=> => naming to docker.io/library/hello-world:v1.0.1
  1. 修改 yaml,讓版本從 v1.0.0 升版到 v1.0.1
deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: v1-deployment
labels:
type: demo-v1
annotations:
# 修改註解
kubernetes.io/change-cause: "Updated image to hello-world:v1.0.1"
spec:
replicas: 2
selector:
matchLabels:
type: demo-v1
template:
metadata:
labels:
type: demo-v1
spec:
containers:
- name: v1
# 升版到v1.0.1
image: hello-world:v1.0.1
ports:
- containerPort: 8080
---
...V2沒有更動省略...
  1. 執行 kubectl 指令來執行他
kubectl.exe apply -f deployment.yaml
---

deployment.apps/v1-deployment configured
deployment.apps/v2-deployment unchanged
  1. 查看歷史紀錄就能看到不同的版本產生出來
kubectl.exe rollout history deployment v1-deployment
---

deployment.apps/v1-deployment
REVISION CHANGE-CAUSE
1 Scaled replicas to 2
2 Updated image to hello-world:v1.0.1
  1. 我們也能透過指令查看版本號的詳細資訊,透過--revision=要查看的版本號
kubectl.exe rollout history deployment v1-deployment --revision=2
---

deployment.apps/v1-deployment with revision #2
Pod Template:
Labels: pod-template-hash=c79c7bdd6
type=demo-v1
Annotations: kubernetes.io/change-cause: Updated image to hello-world:v1.0.1
Containers:
v1:
Image: hello-world:v1.0.1
Port: 8080/TCP
Host Port: 0/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
  1. 此時我們想要回滾到 v1.0.0 這個版本,我們可以透過指令直接回去,加上--to-revision=版本號,可以指定回滾的版本號,沒有加就回上一個
kubectl.exe rollout undo deployment v1-deployment
---

deployment.apps/v1-deployment rolled back
  1. 查看版本號是不是回到 V1.0.0,如果是的話就恭喜你成功囉~
kubectl.exe describe deployments.apps v1-deployment
---

Name: v1-deployment
...中間省略...
Pod Template:
Labels: type=demo-v1
Containers:
v1:
Image: hello-world:v1.0.0
Port: 8080/TCP
Host Port: 0/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
...後面省略...