1. 程式人生 > 其它 >《深入剖析kubernetes》學習筆記(3)——各類控制器

《深入剖析kubernetes》學習筆記(3)——各類控制器

技術標籤:k8s學習筆記kubernetesdocker控制器

目錄

《深入剖析kubernetes》學習筆記(3)——各類控制器

16. 控制器模式

  • kube-controller-manager元件,位於kubernetes架構下的master節點中,是一系列控制器的集合,在kubernetes原始碼的pkg/controller目錄下,該目錄下定義了一系列控制器
  • k8s所有控制器,都遵循相同的編排模式,即控制迴圈(control loop),虛擬碼為:
  for {
      實際狀態 := 獲取叢集中物件 X 的實際狀態(Actual State)
      期望狀態 := 獲取叢集中物件 X 的期望狀態(Desired State)
      if 實際狀態 == 期望狀態{
          什麼都不做
      } else {
          執行編排動作,將實際狀態調整為期望狀態
      }
  }
  • 調諧(Reconcile)
    • 是指實際狀態與期望狀態相比較,並對實際狀態進行調整以達到期望狀態的過程。
    • 調諧的過程,則被稱作“Reconcile Loop”(調諧迴圈)或者“Sync Loop”(同步迴圈)
  • 補充理解,“控制器模式”和“事件驅動”的差別
    • 可以類比select和epoll

17. 作業副本與水平擴充套件——deployment

  • 滾動更新是指將一個叢集中正在執行的多個 Pod 版本,交替地逐一升級的過程
  • 牢記Deployment 的兩層控制關係
    • Deployment 控制 ReplicaSet,一個ReplicaSet對應一個版本,
    • ReplicaSet根據replicas的值來控制 Pod的副本數
  • deployment可根據spec.RollingUpdateStrategy欄位定義滾動更新策略 ,設定同一時刻擴充套件/收縮的數量
  • deployment定義中spec.revisionHistoryLimit,可以設定保留歷史版本的數量
    ,若為0,則無法進行滾動更新
  • deployment滾動更新常用命令
    kubectl create -f <deployment-name>.yaml --record //record表示記錄操作歷史
    kubectl get deployments //檢視deployment狀態
    kubectl rollout status deployment/<deployment-name> //檢視deployment狀態變化
    kubectl get rs //檢視deployment控制的ReplicaSet
    kubectl edit deployment/<deployment-name> //編輯ETCD中的API物件
    kubectl describe deployment <deployment-name> //檢視deployment詳情,event記錄了滾動更新流程
    kubectl set image deployment/<deployment-name> <container-name>=<image-name>:<image-tag> //直接修改deployment所用映象
    kubectl rollout undo deployment/<deployment-name> //回滾deployment到上一個版本
    kubectl rollout history deployment/<deployment-name> //檢視歷史版本操作記錄
    kubectl rollout pause deployment/<deployment-name> //暫停deployment,此時操作不會新增replicaSet
    kubectl rollout resume deploy/<deployment-name> //恢復deployment
  • 兩種應用釋出的方式
    • 金絲雀釋出(Canary Deployment),優先發布一臺或少量機器升級,等驗證無誤後再更新其他機器。優點是使用者影響範圍小,不足之處是要額外控制如何做自動更新
    • 藍綠髮布(Blue-Green Deployment),2組機器,藍代表當前的V1版本,綠代表已經升級完成的V2版本。通過LB將流量全部匯入V2完成升級部署。優點是切換快速,缺點是影響全部使用者。
  • deployment假設了其下的所有pod都是相同、平等的,無所謂順序、無所謂執行的宿主機,這是deployment的缺陷,很多場景不能覆蓋

18. 理解StatefulSet(1)

  • Deployment控制器模式所能控制的Pod預設是需要保持無狀態的,故需要StatefulSet來管理“有狀態應用例項”,kubernetes將狀態分為兩種:
    • 拓撲狀態,即某些服務例項需要按照特定的順序來啟動,它們的拓撲結構上產生的依賴和狀態
    • 儲存狀態,即不同的服務例項需要不同的儲存資料,比如資料庫的主從關係等
  • 拓撲狀態,主要是為了實現Pod的建立、重啟都按照固定的順序進行,因此需要
    • (1)為Pod進行編號,來保證Pod操作順序
    • (2)既然Pod之間是有拓撲關係的,那麼各Pod提供的服務或是有差異的,因此有必要為每個Pod建立唯一的穩定的"網路標識"(DNS記錄),作為它的訪問入口
  • StatefulSet可以為Pod生成帶編號的,例如web-0, web-1,並嚴格按照標號順序建立(滾動更新時,按編號相反順序更新)。
  • Headless Service(即在定義Service時,指定ClusterIP=none)
    • 直接用lable選擇器就可以定位到對應的Pod例項
    • 為其所代理的所有 Pod 的 IP 地址繫結上固定格式的DNS記錄...svc.cluster.local,服務方即可根據該DNS名字解析得到對應的Pod IP進行訪問
    • 即使執行中某個Pod重啟導致IP變化,新IP也能重新繫結到該DNS上(sevice的能力),從而不會對應用產生影響
  • 定義StatefulSet的yaml時,比deployment多一個servicename=<service-name>的欄位,用來告訴StatefulSet控制器,用對應的Headless Service為Pod生成唯一DNS記錄

19. 理解StatefulSet(2)

  • 為了實現StatefulSet對儲存狀態的管理,kubernetes提供了以下兩個設計
    • Persistent Volume Claim(PVC)用於指定持久化卷訪問宣告,這是一個關於訪問需求的描述物件
    • Persistent Volume(PV)持久化卷用於提供具體的持久化訪問能力
  • PV和PVC的概念非常類似於介面和實現:PV是具體的實現,而PVC則充當介面。
  • StatefulSet管理儲存狀態時,需額外新增volumeCliameTemplates欄位
    • 內部定義與一般的PVC定義一致
    • 表示該StatefulSet管理的所有Pod,都會宣告一個PVC,該PVC的定義來自於volumeCliameTemplates欄位
    • 每個Pod的PVC都會被分配一個編號<PVC-name>-<Pod-name>
  • 當某個Pod被刪除後重啟,仍能訪問到原先PVC裡的內容,原因是:
    • Pod對應的PVC所對應的PV裡的內容不會被刪除,而是持久化儲存著
    • Pod被刪除後,StatefulSet會留意到對應Pod停止,便會重啟建立對應編號的Pod
    • Pod重啟後,便會嘗試重新關聯相同編號的PVC,進而找到與該PVC繫結的PV
  • 理解StatefulSet核心思路
    • StatefulSet可以看作一種特殊的Deployment
    • 為了區分各Pod,以保證Pod建立、重啟的順序,在建立Pod時,為每一個Pod打上了一個獨特的編號(StatefulSet名-序號)
    • 為了保證每個Pod的訪問入口的唯一穩定,利用Headless Service,為每一個Pod分配唯一併且穩定的“網路標識”(DNS名字)
    • 為了確保每個Pod對應的儲存內容不丟失,利用PV和PVC,為每一個Pod分配唯一併且穩定的”儲存空間標識“(PVC名字)

21. 守護程序DaemonSet

  • 基本概念
    • DaemonSet也是一種特殊的Controller,類似於作業系統中的守護程序,作用是在kubernetes叢集上執行一些Daemon Pod,並確保在叢集中的每一個節點上都有且只有一個這樣的Daemon Pod
    • 當有新的節點加入 Kubernetes 集群后,該 Pod 會自動地在新節點上被創建出來;而當舊節點被刪除後,它上面的 Pod 也相應地會被回收掉。
    • 應用場景包括網路外掛、儲存外掛的Agent元件,以及各種監控、日誌元件等。
  • DaemonSet是如何保證在每個節點上有且唯一的?
    • 採用控制器模式,遍歷Etcd中的所有Node,檢查每個Node中是否有對應的Pod,如果沒有就新建一個,有多餘的刪除掉。
  • 在指定Node上新建立Pod的方法?
    • 在Pod定義中加上NodeSelector欄位或者NodeAffinity欄位(推薦nodeAffinity,因nodeSelector已接近廢棄)
    • DaemonSet Controller會在建立 Pod 的時候,自動在這個 Pod 的 API 物件裡,加上 nodeAffinity 定義
  • 如何在還沒有完全進入Ready狀態的kubernetes叢集上部署DaemonSet?
    • 一個節點在沒進入Ready時,會被加上各類taint(汙點)標記,例如若某節點未安裝網路外掛,則會被加上名為node.kubernetes.io/network-unavailable,效果為NoSchedule的“汙點”
    • DaemonSet依靠sepc.toleration的宣告,可以允許對某個帶有unschedulable的taint的節點進行排程。
    • 補充:master節點上預設會有node.kubernetes.io/network-unavailable的“汙點”
  • DaemonSet的版本管理依靠ControllerRevision實現。(ControllerRevision作為k8s中的通用版本管理物件,StatefulSet也使用它進行版本管理)

22. 離線業務:Job和CronJob

  • 線上業務和離線業務
    • Deployment、StatefulSet,以及 DaemonSet都屬於“線上業務”,或者叫長作業(Long running task)
    • 一次性執行的任務,叫“離線業務”,或者叫計算作業(Batch job)
  • Job物件管理的Pod,其spec.restartPolicy只能被設定為Never或者OnFailure,(在Deployment中只能被設定為Always),從而確保pod計算完成後不會被重啟。
  • job物件的spec.backoffLimit 欄位裡定義了重試次數上限,避免失敗後無限重啟
  • 在 Job 物件中,負責並行控制的引數有兩個
    • spec.parallelism,定義一個 Job 在同一時刻最多可以啟動多少個 Pod 同時執行;
    • spec.completions,定義 Job 至少要完成的 Pod 數目,即 Job 的最小完成數。
  • 定時任務CronJob
    • CronJob 與 Job 的關係,正如同 Deployment 與 Pod 的關係一樣。CronJob 是一個專門用來管理 Job 物件的控制器。