Kubernetes 理解筆記之“控制器模型” Deployment


本文是自己在理解 Deployment 過程中的筆記,重在理解,對於細節可能並不十分詳盡,但會涉及一些實踐。



補充:Kubernetes 中的“對象”和“控制器模式”

1、容器編排

在 Kubernetes 中,Pod 對象作爲容器的進一步組合和封裝,用來更好地描述應用,而對於這些對象的”編排“(調度、安排、管理)邏輯則是由控制器(Controller)來完成,也就是說容器編排的核心就是利用”控制器模式“來最終操作 Pod 對象,要麼就是創建、更新一些 Pod(或者其他的 API 對象、資源),要麼就是刪除一些已經存在的 Pod(或者其他的 API 對象、資源)。

2、控制器模式

核心就是”控制循環“。用代碼表示:

// 針對一種待編排的對象 X,它有一個對應的控制器:
for {
  // 實際狀態,往往來自於 Kubernetes 集羣本身
  實際狀態 := 獲取集羣中對象X的實際狀態(Actual State)
  // 期望狀態,一般來自於用戶提交的 YAML 文件
  期望狀態 := 獲取集羣中對象X的期望狀態(Desired State)
  if 實際狀態 == 期望狀態{
    什麼都不做
  } else {
    執行編排動作,將實際狀態調整爲期望狀態
  }
}

3、“一切皆對象”

Kubernetes 的控制器其實也是一種對象,設計原理就是“用一種對象管理另一種對象”。所以,既然也是 API 對象,就會有各個字段,使用也就可以 YAML 配置操作,屬性實際上都是由上半部分的控制器定義(包括期望狀態),加下半部分的被控制對象的模板組成的。
例如 Deployment :
Deployment YAML

Deployment 理解

1、Deployment 能幹什麼?

一個承接應用部署的雲平臺必須具備的能力,首先想到的應該就是”作業副本水平擴展/收縮“和”版本升級控制“了,這點在 Kubernetes 中便是通過 Deployment 這個控制器對象實現。

2、Deployment 如何實現功能?

Deployment 實際上是一個兩層控制器,實際操作的是 ReplicaSet 對象,然後由 ReplicaSet 來操作 Pod 對象實現編排。

如圖,首先它通過 ReplicaSet 的個數來描述應用的版本,每改動一次 Pod 模板就創建一個新的 ReplicaSet;然後,它再通過 ReplicaSet 的屬性(比如 replicas 的值),來保證 Pod 的副本數量。
注:一個 ReplicaSet 對象,其實就是由副本數目的定義和一個 Pod 模板組成的。(它的定義其實是 Deployment 的一個子集),如下:

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: nginx-set
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9

Deployment 使用實例

以一個 nginx 服務器來實現水平擴展和升級操作,YAML 文件(nginx-deployment.yaml)如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: 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

1、部署及查看命令

# 部署
$ kubectl create -f nginx-deployment.yaml


# 查看 Deployment 狀態信息,看到剛開始還沒有完全部署
$ kubectl get deployments
NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3         0         0            0           1s

# 實時查看 Deployment 對象的狀態變化
$ kubectl rollout status deployment/nginx-deployment
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
deployment.apps/nginx-deployment successfully rolled out

# 查看 Deployment 狀態信息,完全部署完成
$ kubectl get deployments
NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3         3         3            3           20s

# 查看 Deployment 的 Events,瞭解流程
$ kubectl describe deployment nginx-deployment

2、將副本數從3個擴展到4個

# 擴展
$ kubectl scale deployment nginx-deployment --replicas=4
deployment.apps/nginx-deployment scaled

3、將 nginx 版本從1.7.9升級到1.9.1

第一種:修改了 Deployment 的 Pod 模板,“滾動更新”就會被自動觸發

$ kubectl edit deployment/nginx-deployment
... 
    spec:
      containers:
      - name: nginx
        image: nginx:1.9.1 # 1.7.9 -> 1.9.1
        ports:
        - containerPort: 80
...
deployment.extensions/nginx-deployment edited

第二種:直接修改 nginx-deployment 所使用的的鏡像

$ kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
deployment.extensions/nginx-deployment image updated

其他:控制滾動升級的策略

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
...
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1

在上面這個 RollingUpdateStrategy 的配置中,maxSurge 指定的是除了 DESIRED 數量之外,在一次“滾動”中,Deployment 控制器還可以創建多少個新 Pod;而 maxUnavailable 指的是,在一次“滾動”中,Deployment 控制器可以刪除多少箇舊 Pod。

4、將 nginx 版本進行回滾

# 回滾上一個版本
$ kubectl rollout undo deployment/nginx-deployment
deployment.extensions/nginx-deployment

# 回滾到指定版本
# (1)先查看
$ kubectl rollout history deployment/nginx-deployment # --revision=2 可以查看對應版本具體的API細節
deployments "nginx-deployment"
REVISION    CHANGE-CAUSE
1           kubectl create -f nginx-deployment.yaml --record
2           kubectl edit deployment/nginx-deployment
3           kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
# (2)再選版本回滾
$ kubectl rollout undo deployment/nginx-deployment --to-revision=2
deployment.extensions/nginx-deployment

5、多次執行更新操作,但只升級一次

# 讓這個 Deployment 進入了一個“暫停”狀態
$ kubectl rollout pause deployment/nginx-deployment
deployment.extensions/nginx-deployment paused

# --- 
# 隨意使用 kubectl edit 或者 kubectl set image 指令,修改這個 Deployment 的內容了
# ---

# 把這個 Deployment“恢復”回來,觸發“滾動更新”
$ kubectl rollout resume deploy/nginx-deployment
deployment.extensions/nginx-deployment resumed

參考:

《深入剖析Kubernetes | 極客時間》張磊,容器編排和Kubernetes作業管理 16 17

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章