[Kubernetes]深刻理解StatefulSet

前面我寫的一系列博客,若是你可以耐心看到這一篇,那你應該對一個概念就不是太陌生了:Deployment.
爲何提這個概念呢,這就要說到Deployment的一個不足了.Deployment不足以覆蓋全部的應用編排問題,由於在它看來,一個應用的全部Pod,是徹底同樣的,因此它們之間就沒有順序,也無所謂運行在哪臺宿主機上.須要時,Deployment就經過Pod模板建立新的Pod,不須要時,就"殺掉"任意一個Pod.
可是在實際場景中,並非全部應用都知足這樣的要求.好比:主從關係,主備關係,還有就是數據存儲類應用,多個實例一般會在本地磁盤上保存一份數據,而這些實例一旦被殺掉,即便重建出來,實例與數據之間的對應關係也已經丟失,從而致使應用失敗.
這種實例之間有不對等關係,或者有依賴關係的應用,被稱爲"有狀態應用"(Stateful Application)
爲了能對"有狀態應用"作出支持,Kubernetes在Deployment基礎上,擴展出了:StatefulSet.
nginx

StatefulSet設計

StatefulSet將真實世界裏的應用狀態,抽象爲了兩種狀況:web

  • 1,拓撲狀態.這種狀況是說,應用的多個實例之間不是徹底對等的關係.這些應用實例,必須按照某些順序啓動,好比某個應用的主節點A要先於B啓動,那麼當我把A和B兩個節點刪除以後,從新建立出來時,也要是這個順序才行.而且,新建立出來的A和B,必須和原來的A和B網絡標識同樣,這樣原先的訪問者才能使用一樣的方法,訪問到這個新Pod.
  • 2,存儲狀態.這種狀況是說,應用的多個實例分別綁定了不一樣的存儲數據.對於這些應用實例來講,Pod A第一次讀取到的數據,和隔了十分鐘以後再次讀取到的數據,應該是同一份,哪怕在此期間Pod A被從新建立過.
因此,StatefulSet的核心功能,就是經過某種方式,記錄這些狀態,而後在Pod被從新建立時,可以爲新Pod恢復這些狀態.
Headless Service

在深刻了解StatefulSet以前,我們先來說講Headless Service.
咱們知道,Service是Kubernetes項目中用來將一組Pod暴露給外界訪問的一種機制,好比,一個Deployment有3個Pod,那麼我就能夠定義一個Service,而後用戶只要能訪問到這個Service,就能訪問到某個具體的Pod.
可是,這個Service是怎麼被訪問到的呢?
api

第一種方式,以Service的VIP(Virtual IP,即:虛擬IP)方式.好比:當我訪問192.168.0.1這個Service的IP地址時,它就是一個VIP.在實際中,它會把請求轉發到Service代理的具體Pod上.
第二種方式,就是以Service的DNS方式.在這裏又分爲兩種處理方法:第一種是Normal Service.這種狀況下,當訪問DNS記錄時,解析到的是Service的VIP.第二種是Headless Service.這種狀況下,訪問DNS記錄時,解析到的就是某一個Pod的IP地址.
能夠看到,Headless Service不須要分配一個VIP,而是能夠直接以DNS記錄的方式解析出被代理Pod的IP地址.這樣設計有什麼好處呢?
這樣設計可使Kubernetes項目爲Pod分配惟一"可解析身份".而有了這個身份以後,只要知道了一個Pod的名字以及它對應的Service的名字,就能夠很是肯定地經過這條DNS記錄訪問到Pod的IP地址.
服務器

再回到StatefulSet

介紹完Headless Service以後,我們再回來說講,StatefulSet的核心功能,是如何在Pod被從新建立時,可以爲新Pod恢復這些狀態.網絡

爲了詳細講解,如今編寫一個StatefulSet的YAML文件,以下:app

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: "nginx"
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.9.1
        ports:
        - containerPort: 80
          name: web

能夠看到,在這個YAML文件中,多了一個serviceName=nginx字段.這個字段的做用,就是告訴StatefulSet控制器,在執行控制循環時,要使用nginx這個Headless Service來保證Pod的"可解析身份."這樣,在建立Pod過程當中,StatefulSet給它所管理的全部Pod名字,進行編號,使得每一個Pod實例不重複.而更重要的是,這些Pod的建立,也是嚴格按照編號順序來進行的.
這樣的意思就是說,當有主從關係時,有明確前後關係時,StatefulSet經過這種機制,使得前後建立順序成爲可能.
less

整個StatefulSet流程

接下來回顧一下整個流程.
首先,StatefulSet的控制器直接管理的是Pod,而StatefulSet區分這些實例的方式,就是經過在Pod的名字裏面加上事先約定好的編號.
其次,Kubernetes經過Headless Service,爲這些有編號的Pod,在DNS服務器中生成帶有一樣編號的DNS記錄.只要StatefulSet可以保證這些Pod名字裏的編號不變,那麼Service中DNS記錄也就不會變.
最後,StatefulSet還爲每個Pod分配並建立一個一樣編號的PVC.這樣就能夠保證每一個Pod都擁有一個獨立的Volume.在這種狀況下,即便Pod被刪除,它所對應的PVC和PV依然會留下來,因此當這個Pod被從新建立出來以後,Kubernetes會爲它找到一樣編號的PVC,掛載這個PVC對應的Volume,從而獲取到之前保存在Volume中的數據.
svg

其實StatefulSet就是一種特殊的Deployment,只不過它的每一個Pod都被編號了.正是因爲這種機制,使得具備主從關係的建立成爲可能.學習

關於StatefulSet相關內容到這裏就介紹的差很少了.
以上內容來自我學習<深刻剖析Kubernetes>專欄文章以後的一些看法,有偏頗之處,還望指出.
感謝您的閱讀~
設計

相關文章
相關標籤/搜索