引言
傳統的運維中,往往需要管理者手動先在存儲叢集配置設定空間,然後才能挂載到應用中去。Kubernetes 的最新版中,dynamic provisioning 更新到了 beta ,并支援多種存儲服務的動态預配置,進而可以更有效地利用存儲環境中的存儲容量,達到按需使用存儲空間的目的。本文将介紹 dynamic provisioning 這一特性,并以 GlusterFS 為例,說明存儲服務與 k8s 的對接。
dynamic provisioning:
存儲是容器編排中非常重要的一部分。Kubernetes 從 v1.2 開始,提供了 dynamic provisioning 這一強大的特性,可以給叢集提供按需配置設定的存儲,并能支援包括 AWS-EBS、GCE-PD、Cinder-Openstack、Ceph、GlusterFS 等多種雲存儲。非官方支援的存儲也可以通過編寫 plugin 方式支援。
在沒有 dynamic provisioning 時,容器為了使用 Volume,需要預先在存儲端配置設定好,這個過程往往是管理者手動的。在引入 dynamic provisioning 之後,Kubernetes 會根據容器所需的 volume 大小,通過調用存儲服務的接口,動态地建立滿足所需的存儲。
Storageclass:
管理者可以配置 storageclass,來描述所提供存儲的類型。以 AWS-EBS 為例,管理者可以分别定義兩種 storageclass:slow 和 fast。slow 對接 sc1(機械硬碟),fast 對接 gp2(固态硬碟)。應用可以根據業務的性能需求,分别選擇兩種 storageclass。
Glusterfs:
一個開源的分布式檔案系統,具有強大的橫向擴充能力,通過擴充能夠支援數 PB 存儲容量和處理數千用戶端。GlusterFS 借助 TCP/IP 或 InfiniBandRDMA 網絡将實體分布的存儲資源聚集在一起,使用單一全局命名空間來管理資料。
Heketi:
Heketi(https://github.com/heketi/heketi),是一個基于 RESTful API 的 GlusterFS 卷管理架構。
Heketi 可以友善地和雲平台整合,提供 RESTful API 供 Kubernetes 調用,實作多 glusterfs 叢集的卷管理。另外,heketi 還有保證 bricks 和它對應的副本均勻分布在叢集中的不同可用區的優點。
部署基于 GlusterFS 的 dynamic provisioning
1、安裝 GlusterFS。可以參見官方文檔,在此不贅述。
2、部署 heketi。本文将以容器化的形式部署 heketi。heketi 的 yaml 如下:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: heketi
labels:
app: heketi
spec:
replicas: 1
template:
metadata:
labels:
app: heketi
spec:
containers:
- name: heketi
image:caicloud: heketi
ports:
- containerPort: 8080
volumeMounts:
- mountPath: /etc/heketi
name: heketi-volume
- mountPath: /root/.ssh
name: ssh-volume
volumes:
- name: ssh-volume
hostPath:
path: /root/.ssh # This node must be able to ssh to other nodes.
- name: heketi-volume
hostPath:
path: /root/heketi
nodeName: {{heketi_node}} # Pinned to node
等 heketi 開始成功運作後,需要将 glusterfs 叢集的配置載入,可以通過 curl api 的形式,也可以通過 heketi 的用戶端來載入,如 ./heketi-cli load --json=new-cluster.json。new-cluster.json 中定義了 glusterfs 叢集的各個節點 IP、可用分區等資訊。典型的配置例子:https://github.com/heketi/heketi/blob/master/client/cli/go/topology-sample.json
注意事項:
Heketi 需要使用能夠免密 ssh 到 glusterfs 叢集所有節點的私鑰,并且 heketi 會在 glusterfs 叢集将指定的分區格式化, 并調用 pvcreate 和 lvcreate 将分區組裝成 volume group。
3、部署 StorageClass
apiVersion: storage.k8s.io/v1beta1
kind: StorageClass
metadata:
name: glusterfs-rep3
provisioner: kubernetes.io/glusterfs
parameters:
resturl: "http://192.168.1.111:8081" //heketi位址,也可以填域名
clusterid: "630372ccdc720a92c681fb928f27b53f" // 可選,要使用的叢集id
restuser: "admin" // 可選,authentication 的使用者名
secretNamespace: "default" // 可選,authentication 的密碼所在的 secret 所在的namespace
secretName: "heketi-secret" // 可選,authentication 的密碼所在的 secret
gidMin: "40000" // 能夠使用的最小gid,可選,每個 gluster volume 都有唯一的 gid
gidMax: "50000" // 能夠使用的最大gid,可選
volumetype: "replicate:3" // 可選,glusterfs 的 volume 類型,數字為副本的數量
這裡 volumetype 填了 replicate:3,同理,我們也可以定義其他卷類型的storageclass,比如 disperse:4:2,表示使用糾錯卷(disperse),每 4 份 brick 做 2 份備援。volumetype: none 将會預設使用分布式卷。
4、建立 PVC(Persistent Volume Claim),指定 storageclass,并聲明所需存儲大小。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: gluster-pvc-10G
annotations:
volume.beta.kubernetes.io/storage-class: glusterfs-rep3 // 指定storageclass
spec:
accessModes:
- ReadWriteMany // 可以被多個pod挂載讀寫
resources:
requests:
storage: 10Gi // 指定使用10G大小的存儲
建立 pvc 後,Kubernetes 會調用 heketi 的 create volume API。之後 heketi 将會去檢查 glusterfs 叢集的可用空間。本文指定了 rep3 的 storageclass, 是以需要 3 個節點有至少 10G 的可用磁盤空間。如果滿足條件,Kubernetes 則會建立相應大小的 PV (Persistent Volume),并綁定該 PVC。否則,該 PVC 将一直停留在 pending 狀态。
本文指定了 3 個副本的 gluster 存儲,其實隻要将 annotations 中的 storageclass 換個名字,應用就可以使用其他類型的存儲,非常友善。
5、驗證
PVC 成功綁定 PV 後,可以讓應用使用該 PVC 作為存儲。我們可以建立一個 debian 的 pod,用來驗證,yaml 如下:
apiVersion: v1
kind: Pod
metadata:
name: gluster-tester
spec:
containers:
- name: glusterfs
image: cargo.caicloud.io/caicloud/debian:jessie
volumeMounts:
- mountPath: "/mnt/gluster"
name: test-vol
args:
- tail
- "-f"
- "/dev/null"
volumes:
- name: test-vol
persistentVolumeClaim:
claimName: gluster-pvc-10G
通過 kubectl exec 進入該容器的終端後,就可以在 /mnt/glusterfs 目錄下使用 10G 的 glusterfs 存儲。因為 gluster-pvc-10G 是 ReadWriteMany(可以被多個 pod 挂載讀寫)的,是以可以在其他應用中也使用這個 PVC,達到資料共享的目的。
總結