這篇文章已超過一年。較舊的文章可能包含過時的內容。請檢查頁面中的資訊自發布以來是否已變得不正確。

使用 Kubernetes Pet Sets 和 Datera Elastic Data Fabric 的 FlexVolumes 擴展有狀態應用程式

簡介

Kubernetes 中的持久卷是基礎,因為客戶從無狀態工作負載轉向執行有狀態應用程式。雖然 Kubernetes 一直以來都支援 MySQL、Kafka、Cassandra 和 Couchbase 等有狀態應用程式,但 Pet Sets 的引入顯著改善了這種支援。特別是,排序佈建和啟動程序的步驟,以及透過 Pet Sets 擴展和持久關聯的能力,提供了自動擴展「寵物」(需要一致處理和持久放置的應用程式) 的能力。

Datera 是用於雲端部署的彈性區塊儲存,已透過 FlexVolume 框架與 Kubernetes 無縫整合。基於容器的首要原則,Datera 允許應用程式資源佈建與底層實體基礎架構解耦。這為有狀態應用程式帶來了清晰的契約(又名,不依賴或直接了解底層實體基礎架構)、宣告式格式,以及最終的可攜性。

雖然 Kubernetes 允許透過 yaml 組態高度彈性地定義底層應用程式基礎架構,但 Datera 允許將該組態傳遞到儲存基礎架構以提供持久性。透過 Datera AppTemplates 的概念,在 Kubernetes 環境中,有狀態應用程式可以自動擴展。

部署持久儲存

持久儲存是使用 Kubernetes PersistentVolume 子系統定義的。PersistentVolume 是卷外掛程式,用於定義獨立於使用它的 Pod 生命週期的卷。它們實作為 NFS、iSCSI 或雲端供應商特定的儲存系統。Datera 為 PersistentVolume 開發了一個卷外掛程式,可以在 Datera Data Fabric 上為 Kubernetes Pod 佈建 iSCSI 區塊儲存。

Datera 卷外掛程式由 minion 節點上的 kubelet 呼叫,並透過其 REST API 將呼叫中繼到 Datera Data Fabric。以下是使用 Datera 外掛程式的 PersistentVolume 範例部署

 apiVersion: v1

 kind: PersistentVolume

 metadata:

   name: pv-datera-0

 spec:

   capacity:

     storage: 100Gi

   accessModes:

     - ReadWriteOnce

   persistentVolumeReclaimPolicy: Retain

   flexVolume:

     driver: "datera/iscsi"

     fsType: "xfs"

     options:

       volumeID: "kube-pv-datera-0"

       size: “100"

       replica: "3"

       backstoreServer: "[tlx170.tlx.daterainc.com](http://tlx170.tlx.daterainc.com/):7717”

此 manifest 定義了一個 100 GB 的 PersistentVolume,如果 Pod 請求持久儲存,則在 Datera Data Fabric 中佈建。

[root@tlx241 /]# kubectl get pv

NAME          CAPACITY   ACCESSMODES   STATUS      CLAIM     REASON    AGE

pv-datera-0   100Gi        RWO         Available                       8s

pv-datera-1   100Gi        RWO         Available                       2s

pv-datera-2   100Gi        RWO         Available                       7s

pv-datera-3   100Gi        RWO         Available                       4s

組態

Datera PersistenceVolume 外掛程式安裝在所有 minion 節點上。當 Pod 落在 minion 節點上,且有效聲明綁定到先前佈建的持久儲存時,Datera 外掛程式會將請求轉發到 Datera Data Fabric 以建立卷。PersistentVolume manifest 中指定的所有選項都會在佈建請求時傳送給外掛程式。

一旦在 Datera Data Fabric 中佈建卷,卷就會作為 iSCSI 區塊裝置呈現給 minion 節點,而 kubelet 會掛載此裝置,供容器(在 Pod 中)存取。

使用持久儲存

Kubernetes PersistentVolume 與使用 PersistentVolume Claims 的 Pod 一起使用。一旦定義了聲明,它就會綁定到符合聲明規格的 PersistentVolume。上面定義的 PersistentVolume 的典型聲明如下所示

kind: PersistentVolumeClaim

apiVersion: v1

metadata:

 name: pv-claim-test-petset-0

spec:

 accessModes:

   - ReadWriteOnce

 resources:

   requests:

     storage: 100Gi

當定義此聲明並將其綁定到 PersistentVolume 時,資源可以與 Pod 規格一起使用

[root@tlx241 /]# kubectl get pv

NAME          CAPACITY   ACCESSMODES   STATUS      CLAIM                            REASON    AGE

pv-datera-0   100Gi      RWO           Bound       default/pv-claim-test-petset-0             6m

pv-datera-1   100Gi      RWO           Bound       default/pv-claim-test-petset-1             6m

pv-datera-2   100Gi      RWO           Available                                              7s

pv-datera-3   100Gi      RWO           Available                                              4s


[root@tlx241 /]# kubectl get pvc

NAME                     STATUS    VOLUME        CAPACITY   ACCESSMODES   AGE

pv-claim-test-petset-0   Bound     pv-datera-0   0                        3m

pv-claim-test-petset-1   Bound     pv-datera-1   0                        3m

Pod 可以像下面這樣使用 PersistentVolume Claim

apiVersion: v1

kind: Pod

metadata:

 name: kube-pv-demo

spec:

 containers:

 - name: data-pv-demo

   image: nginx

   volumeMounts:

   - name: test-kube-pv1

     mountPath: /data

   ports:

   - containerPort: 80

 volumes:

 - name: test-kube-pv1

   persistentVolumeClaim:

     claimName: pv-claim-test-petset-0

結果是一個 Pod 使用 PersistentVolume Claim 作為卷。它進而將請求傳送到 Datera 卷外掛程式,以在 Datera Data Fabric 中佈建儲存。

[root@tlx241 /]# kubectl describe pods kube-pv-demo

Name:       kube-pv-demo

Namespace:  default

Node:       tlx243/172.19.1.243

Start Time: Sun, 14 Aug 2016 19:17:31 -0700

Labels:     \<none\>

Status:     Running

IP:         10.40.0.3

Controllers: \<none\>

Containers:

 data-pv-demo:

   Container ID: [docker://ae2a50c25e03143d0dd721cafdcc6543fac85a301531110e938a8e0433f74447](about:blank)

   Image:   nginx

   Image ID: [docker://sha256:0d409d33b27e47423b049f7f863faa08655a8c901749c2b25b93ca67d01a470d](about:blank)

   Port:    80/TCP

   State:   Running

     Started:  Sun, 14 Aug 2016 19:17:34 -0700

   Ready:   True

   Restart Count:  0

   Environment Variables:  \<none\>

Conditions:

 Type           Status

 Initialized    True

 Ready          True

 PodScheduled   True

Volumes:

 test-kube-pv1:

   Type:  PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)

   ClaimName:   pv-claim-test-petset-0

   ReadOnly:    false

 default-token-q3eva:

   Type:        Secret (a volume populated by a Secret)

   SecretName:  default-token-q3eva

   QoS Tier:  BestEffort

Events:

 FirstSeen LastSeen Count From SubobjectPath Type Reason Message

 --------- -------- ----- ---- ------------- -------- ------ -------

 43s 43s 1 {default-scheduler } Normal Scheduled Successfully assigned kube-pv-demo to tlx243

 42s 42s 1 {kubelet tlx243} spec.containers{data-pv-demo} Normal Pulling pulling image "nginx"

 40s 40s 1 {kubelet tlx243} spec.containers{data-pv-demo} Normal Pulled Successfully pulled image "nginx"

 40s 40s 1 {kubelet tlx243} spec.containers{data-pv-demo} Normal Created Created container with docker id ae2a50c25e03

 40s 40s 1 {kubelet tlx243} spec.containers{data-pv-demo} Normal Started Started container with docker id ae2a50c25e03

持久卷在 minion 節點 (在本例中為 tlx243) 上呈現為 iSCSI 裝置

[root@tlx243 ~]# lsscsi

[0:2:0:0]    disk    SMC      SMC2208          3.24  /dev/sda

[11:0:0:0]   disk    DATERA   IBLOCK           4.0   /dev/sdb


[root@tlx243 datera~iscsi]# mount  ``` grep sdb

/dev/sdb on /var/lib/kubelet/pods/6b99bd2a-628e-11e6-8463-0cc47ab41442/volumes/datera~iscsi/pv-datera-0 type xfs (rw,relatime,attr2,inode64,noquota)

在 Pod 中執行的容器會看到此裝置掛載在 manifest 中指定的 /data

[root@tlx241 /]# kubectl exec kube-pv-demo -c data-pv-demo -it bash

root@kube-pv-demo:/# mount  ``` grep data

/dev/sdb on /data type xfs (rw,relatime,attr2,inode64,noquota)

使用 Pet Sets

通常,Pod 被視為無狀態單元,因此如果其中一個 Pod 不健康或被取代,Kubernetes 只會處置它。相反地,PetSet 是一組有狀態的 Pod,它具有更強烈的身分概念。PetSet 的目標是透過為應用程式的個別執行個體分配身分來解耦此依賴關係,這些身分不錨定於底層實體基礎架構。

PetSet 需要 {0..n-1} 個寵物 (Pets)。每個寵物都有一個確定的名稱 PetSetName-Ordinal 和一個唯一的身分。每個寵物最多有一個 Pod,每個 PetSet 最多有一個具有給定身分的寵物。PetSet 確保在任何給定時間都有指定數量的具有唯一身分的「寵物」正在執行。寵物的身分由以下組成

  • 穩定的主機名稱,在 DNS 中可用
  • 序數索引
  • 穩定的儲存:連結到序數和主機名稱

使用 PersistentVolume Claim 的典型 PetSet 定義如下所示

# A headless service to create DNS records

apiVersion: v1

kind: Service

metadata:

 name: test-service

 labels:

   app: nginx

spec:

 ports:

 - port: 80

   name: web

 clusterIP: None

 selector:

   app: nginx

---

apiVersion: apps/v1alpha1

kind: PetSet

metadata:

 name: test-petset

spec:

 serviceName: "test-service"

 replicas: 2

 template:

   metadata:

     labels:

       app: nginx

     annotations:

       [pod.alpha.kubernetes.io/initialized:](http://pod.alpha.kubernetes.io/initialized:) "true"

   spec:

     terminationGracePeriodSeconds: 0

     containers:

     - name: nginx

       image: [gcr.io/google\_containers/nginx-slim:0.8](http://gcr.io/google_containers/nginx-slim:0.8)

       ports:

       - containerPort: 80

         name: web

       volumeMounts:

       - name: pv-claim

         mountPath: /data

 volumeClaimTemplates:

 - metadata:

     name: pv-claim

     annotations:

       [volume.alpha.kubernetes.io/storage-class:](http://volume.alpha.kubernetes.io/storage-class:) anything

   spec:

     accessModes: ["ReadWriteOnce"]

     resources:

       requests:

         storage: 100Gi

我們有以下可用的 PersistentVolume Claims

[root@tlx241 /]# kubectl get pvc

NAME                     STATUS    VOLUME        CAPACITY   ACCESSMODES   AGE

pv-claim-test-petset-0   Bound     pv-datera-0   0                        41m

pv-claim-test-petset-1   Bound     pv-datera-1   0                        41m

pv-claim-test-petset-2   Bound     pv-datera-2   0                        5s

pv-claim-test-petset-3   Bound     pv-datera-3   0                        2s

當佈建此 PetSet 時,會實例化兩個 Pod

[root@tlx241 /]# kubectl get pods

NAMESPACE     NAME                        READY     STATUS    RESTARTS   AGE

default       test-petset-0               1/1       Running   0          7s

default       test-petset-1               1/1       Running   0          3s

以下是先前實例化的 PetSet test-petset 的外觀

[root@tlx241 /]# kubectl describe petset test-petset

Name: test-petset

Namespace: default

Image(s): [gcr.io/google\_containers/nginx-slim:0.8](http://gcr.io/google_containers/nginx-slim:0.8)

Selector: app=nginx

Labels: app=nginx

Replicas: 2 current / 2 desired

Annotations: \<none\>

CreationTimestamp: Sun, 14 Aug 2016 19:46:30 -0700

Pods Status: 2 Running / 0 Waiting / 0 Succeeded / 0 Failed

No volumes.

No events.

一旦實例化 PetSet (例如下方的 test-petset),在增加副本數量 (即使用該 PetSet 啟動的 Pod 數量) 後,會實例化更多 Pod,並且更多 PersistentVolume Claims 會綁定到新的 Pod

[root@tlx241 /]# kubectl patch petset test-petset -p'{"spec":{"replicas":"3"}}'

"test-petset” patched


[root@tlx241 /]# kubectl describe petset test-petset

Name: test-petset

Namespace: default

Image(s): [gcr.io/google\_containers/nginx-slim:0.8](http://gcr.io/google_containers/nginx-slim:0.8)

Selector: app=nginx

Labels: app=nginx

Replicas: 3 current / 3 desired

Annotations: \<none\>

CreationTimestamp: Sun, 14 Aug 2016 19:46:30 -0700

Pods Status: 3 Running / 0 Waiting / 0 Succeeded / 0 Failed

No volumes.

No events.


[root@tlx241 /]# kubectl get pods

NAME                        READY     STATUS    RESTARTS   AGE

test-petset-0               1/1       Running   0          29m

test-petset-1               1/1       Running   0          28m

test-petset-2               1/1       Running   0          9s

現在 PetSet 在套用修補程式後正在執行 3 個 Pod。

當修補上述 PetSet 定義以擁有更多一個副本時,它會在系統中引入更多一個 Pod。這反過來導致在 Datera Data Fabric 上佈建更多一個卷。因此,卷會在 PetSet 擴展時動態佈建並附加到 Pod。

為了支援持久性和一致性的概念,如果 Pod 從一個 minion 移到另一個 minion,卷確實會附加 (掛載) 到新的 minion 節點,並從舊的 minion 解除附加 (卸載),以維持對資料的持久存取。

結論

這示範了 Kubernetes 與 Pet Sets 編排有狀態和無狀態工作負載。雖然 Kubernetes 社群正在努力擴展 FlexVolume 框架的功能,但我們很高興這個解決方案使 Kubernetes 能夠在資料中心更廣泛地運行。

加入並貢獻:Kubernetes Storage SIG