什麼是Deployment
在Pod:Kubernetes中的最小調度對象這個章節介紹了Pod,Pod是Kubernetes創建或部署的最小單位,但是Pod是被設計爲相對短暫的一次性實體,Pod可以被驅逐(當節點資源不足時)、隨着集羣的節點崩潰而消失。Kubernetes提供了Controller(控制器)來管理Pod,Controller可以創建和管理多個Pod,提供副本管理、滾動升級和自愈能力,其中最爲常用的就是Deployment。
圖1 Deployment
一個Deployment可以包含一個或多個Pod副本,每個Pod副本的角色相同,所以系統會自動爲Deployment的多個Pod副本分發請求。
Deployment集成了上線部署、滾動升級、創建副本、恢復上線的功能,在某種程度上,Deployment實現無人值守的上線,大大降低了上線過程的複雜性和操作風險。
創建Deployment
以下示例爲創建一個名爲nginx的Deployment負載,使用nginx:latest鏡像創建兩個Pod,每個Pod佔用100m core CPU、200M內存。
apiVersion: apps/v1 # 注意這裏與Pod的區別,Deployment是apps/v1而不是v1
kind: Deployment # 資源類型爲Deployment
metadata:
name: nginx # Deployment的名稱
spec:
replicas: 2 # Pod的數量,Deployment會確保一直有2個Pod運行
selector: # Label Selector
matchLabels:
app: nginx
template: # Pod的定義,用於創建Pod,也稱爲Pod template
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx:latest
name: container-0
resources:
limits:
cpu: 100m
memory: 200Mi
requests:
cpu: 100m
memory: 200Mi
imagePullSecrets:
- name: default-secret
從這個定義中可以看到Deployment的名稱爲nginx,spec.replicas定義了Pod的數量,即這個Deployment控制2個Pod;spec.selector是Label Selector(標籤選擇器),表示這個Deployment會選擇Label爲app=nginx的Pod;spec.template是Pod的定義,內容與Pod中的定義完全一致。
將上面Deployment的定義保存到deployment.yaml文件中,使用kubectl創建這個Deployment。
使用kubectl get查看Deployment和Pod,可以看到READY值爲2/2,前一個2表示當前有2個Pod運行,後一個2表示期望有2個Pod,AVAILABLE爲2表示有2個Pod是可用的。
$ kubectl create -f deployment.yaml
deployment.apps/nginx created
$ kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
nginx 2/2 2 2 4m5s
Deployment如何控制Pod
繼續查詢Pod,如下所示。
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-7f98958cdf-tdmqk 1/1 Running 0 13s
nginx-7f98958cdf-txckx 1/1 Running 0 13s
如果刪掉一個Pod,您會發現立馬會有一個新的Pod被創建出來,如下所示,這就是前面所說的Deployment會確保有2個Pod在運行,如果刪掉一個,Deployment會重新創建一個,如果某個Pod故障或有其他問題,Deployment會自動拉起這個Pod。
$ kubectl delete pod nginx-7f98958cdf-txckx
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-7f98958cdf-tdmqk 1/1 Running 0 21s
nginx-7f98958cdf-tesqr 1/1 Running 0 21s
看到有如下兩個名爲nginx-7f98958cdf-tdmqk和nginx-7f98958cdf-tesqr的Pod, 其中nginx是直接使用Deployment的名稱,-7f98958cdf-tdmqk和-7f98958cdf-tesqr是kubernetes隨機生成的後綴。
您也許會發現這兩個後綴中前面一部分是相同的,都是7f98958cdf,這是因爲Deployment不是直接控制Pod的,Deployment是通過一種名爲ReplicaSet的控制器控制Pod,通過如下命令可以查詢ReplicaSet,其中rs是ReplicaSet的縮寫。
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-7f98958cdf 2 2 2 1m
這個ReplicaSet的名稱爲nginx-7f98958cdf,後綴-7f98958cdf也是隨機生成的。
Deployment控制Pod的方式如圖2所示,Deployment控制ReplicaSet,ReplicaSet控制Pod。
圖2 Deployment通過ReplicaSet控制Pod
如果使用kubectl describe命令查看Deployment的詳情,您就可以看到ReplicaSet,如下所示,可以看到有一行NewReplicaSet: nginx-7f98958cdf (2/2 replicas created),而且Events裏面事件確是把ReplicaSet的實例擴容到2個。在實際使用中您也許不會直接操作ReplicaSet,但瞭解Deployment通過控制ReplicaSet來控制Pod會有助於您定位問題。
**$ kubectl describe deploy nginx**
Name: nginx
Namespace: default
CreationTimestamp: Sun, 16 Dec 2018 19:21:58 +0800
Labels: app=nginx
...
**NewReplicaSet: nginx-7f98958cdf (2/2 replicas created)**
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 5m deployment-controller Scaled up replica set nginx-7f98958cdf to 2
升級
在實際應用中,升級是一個常見的場景,Deployment能夠很方便的支撐應用升級。
Deployment可以設置不同的升級策略,有如下兩種。
- RollingUpdate:滾動升級,即逐步創建新Pod再刪除舊Pod,爲默認策略。
- Recreate:替換升級,即先把當前Pod刪掉再重新創建Pod。
Deployment的升級可以是聲明式的,也就是說只需要修改Deployment的YAML定義即可,比如使用kubectl edit命令將上面Deployment中的鏡像修改爲nginx:alpine。修改完成後再查詢ReplicaSet和Pod,發現創建了一個新的ReplicaSet,Pod也重新創建了。
$ kubectl edit deploy nginx
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-6f9f58dffd 2 2 2 1m
nginx-7f98958cdf 0 0 0 48m
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-6f9f58dffd-tdmqk 1/1 Running 0 21s
nginx-6f9f58dffd-tesqr 1/1 Running 0 21s
Deployment可以通過maxSurge和maxUnavailable兩個參數控制升級過程中同時重新創建Pod的比例,這在很多時候是非常有用,配置如下所示。
spec:
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
type: RollingUpdate
- maxSurge:與Deployment中spec.replicas相比,可以有多少個Pod存在,默認值是25%,比如spec.replicas爲 4,那升級過程中就不能超過5個Pod存在,即按1個的步伐升級,實際升級過程中會換算成數字,且換算會向上取整。這個值也可以直接設置成數字。
- maxUnavailable:與Deployment中spec.replicas相比,可以有多少個Pod失效,也就是刪除的比例,默認值是25%,比如spec.replicas爲4,那升級過程中就至少有3個Pod存在,即刪除Pod的步伐是1。同樣這個值也可以設置成數字。
在前面的例子中,由於spec.replicas是2,如果maxSurge和maxUnavailable都爲默認值25%,那實際升級過程中,maxSurge允許最多3個Pod存在(向上取整,21.25=2.5,取整爲3),而maxUnavailable則不允許有Pod Unavailable(向上取整,20.75=1.5,取整爲2),也就是說在升級過程中,一直會有2個Pod處於運行狀態,每次新建一個Pod,等這個Pod創建成功後再刪掉一箇舊Pod,直至Pod全部爲新Pod。
回滾
回滾也稱爲回退,即當發現升級出現問題時,讓應用回到老的版本。Deployment可以非常方便的回滾到老版本。
例如上面升級的新版鏡像有問題,可以執行kubectl rollout undo命令進行回滾。
$ kubectl rollout undo deployment nginx
deployment.apps/nginx rolled back
Deployment之所以能如此容易的做到回滾,是因爲Deployment是通過ReplicaSet控制Pod的,升級後之前ReplicaSet都一直存在,Deployment回滾做的就是使用之前的ReplicaSet再次把Pod創建出來。Deployment中保存ReplicaSet的數量可以使用revisionHistoryLimit參數限制,默認值爲10。