在阿裡雲ACK叢集中部署有狀态服務通常使用雲盤資料卷做資料存儲,雲盤本身提供了資料的備份(快照)恢複機制,但是如何将底層能力和K8S服務內建并靈活的提供給應用使用,是雲原生存儲服務需要解決的問題。K8S使用如下兩個特性來實作備份恢複能力:
通過VolumeSnapshot對象實作雲盤的備份(快照功能);
通過PVC中的DataSource功能實作資料的恢複(快照恢複);
由于VolumeSnapshot在K8S 1.16版本處于Alpha狀态,是以ACK叢集目前沒有預設部署快照功能,需要手動安裝插件才能使用;
K8S快照說明:
在Kubernetes中為了實作快照相關功能,通過CRD定義了下面3個相關資源類型:
VolumeSnapshotContent:描述存儲後端的快照執行個體,由系統管理者建立維護,無NameSpace;類比于PV概念;
VolumeSnapshot:聲明一個快照執行個體,由使用者建立維護,屬于特定NameSpace;類比于PVC概念;
VolumeSnapshotClass:定義一個快照類,描述建立快照使用的參數、Controller;類比于StorageClass概念;
快照資源綁定規則:
在使用Snapshot對象時,和pv、pvc一樣,VolumeSnapshot與VolumeSnapshotContent需要首先進行綁定;
VolumeSnapshot如果沒有靜态VolumeSnapshotContent可以綁定,則會建立動态VolumeSnapshotContent;
VolumeSnapshotContent 與 VolumeSnapshot 綁定是一對一;
删除VolumeSnapshotContent 同時會把後端的快照也删除;
1.卷快照模闆
下面是一個VolumeSnapshotClass定義模闆:
apiVersion: snapshot.storage.k8s.io/v1beta1
kind: VolumeSnapshotClass
metadata:
name: default-snapclass
driver: diskplugin.csi.alibabacloud.com
parameters:
forceDelete: "false"
deletionPolicy: Delete
其中:
driver:定義了使用這個快照類的VolumeSnapshot所使用的controller;
deletionPolicy: 表示删除volumeSnapshot的時候,volumeSnapshotContent是否删除;
forceDelete: 表示是否允許在雲盤引用快照的時候删除快照(預設是不允許删除的,因為以快照為資料源建立雲盤時,建立過程會有時延,強制删除可能會造成資料丢失);
下面是一個VolumeSnapshot定義模闆:
apiVersion: snapshot.storage.k8s.io/v1beta1
kind: VolumeSnapshot
metadata:
name: new-snapshot-demo
spec:
volumeSnapshotClassName: default-snapclass
source:
persistentVolumeClaimName: disk-ssd-web-0
persistentVolumeClaimName:定義使用哪個pvc作為快照源;
volumeSnapshotClassName:定義了打快照使用的快照類;
2.通過快照恢複資料
通過雲盤快照建立雲盤是阿裡雲雲盤提供的基礎功能。在容器服務中通過在pvc定義DataSource指定使用哪個快照,動态建立雲盤的時候即可實作使用快照建立雲盤;
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: disk-snapshot
spec:
accessModes:
- ReadWriteOnce
storageClassName: alicloud-disk-ssd
dataSource:
name: new-snapshot-demo
kind: VolumeSnapshot
apiGroup: snapshot.storage.k8s.io
resources:
requests:
storage: 20Gi
storageClassName:定建立pv的存儲類,指向的disk controller需要支援DataSource特性;
dataSource:指定snapshot資源,說明建立雲盤會使用這個快照資料;
插件部署:
叢集準備:
部署csi-snapshotter前,您需要建立一個ACK 1.16版本叢集,并在建立叢集的時候選擇使用CSI插件;
叢集建立部署CRD & Snapshot:
下載下傳snapshotter crd模闆:
https://github.com/kubernetes-sigs/alibaba-cloud-csi-driver/blob/master/deploy/disk/snapshot/crd.yaml下載下傳csi-snapshotter模闆:
https://github.com/kubernetes-sigs/alibaba-cloud-csi-driver/blob/master/deploy/disk/snapshot/csi-snapshotter.yaml部署插件:
$ kubectl apply -f crd.yaml
$ kubectl apply -f csi-snapshotter.yaml
部署完成後叢集中csi插件如下:
# kubectl get crd
NAME CREATED AT
volumesnapshotclasses.snapshot.storage.k8s.io 2020-06-17T09:36:32Z
volumesnapshotcontents.snapshot.storage.k8s.io 2020-06-17T09:36:32Z
volumesnapshots.snapshot.storage.k8s.io 2020-06-17T09:36:32Z
# kubectl get pod -nkube-system |grep csi-snap
csi-snapshotter-d78f57d4d-rmjhp 3/3 Running 0 54m
使用:
下圖是一個使用示例流程圖,分成1、2、3三個步驟:

步驟1:建立原始應用,建立雲盤卷儲存資料;
步驟2:建立VolumeSnapshot,這時會自動建立VolumeSnapshotContent和存儲端的快照執行個體;
步驟3:建立新的應用,并配置PVC引用步驟2中建立的快照對象;
通過上述三步實作了:
備份:Volume1中的資料備份到Snapshot1;
恢複:Snapshot1的資料(Volume1的資料)恢複成Volume2卷;
建立VolumeSnapshotClass快照類:
下載下傳VolumeSnapshotClass模闆:
https://github.com/kubernetes-sigs/alibaba-cloud-csi-driver/blob/master/examples/disk/snapshot/snapshotclass.yaml$ kubectl apply -f calss.yaml
apiVersion: snapshot.storage.k8s.io/v1beta1
kind: VolumeSnapshotClass
metadata:
name: default-snapclass
driver: diskplugin.csi.alibabacloud.com
deletionPolicy: Delete
# kubectl get VolumeSnapshotClass
NAME AGE
default-snapclass 4h40m
步驟1:建立原始應用并寫入資料:
$ kubectl apply -f sts.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
selector:
matchLabels:
app: nginx
serviceName: "nginx"
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- name: disk-ssd
mountPath: /data
volumeClaimTemplates:
- metadata:
name: disk-ssd
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "alicloud-disk-snap"
resources:
requests:
storage: 20Gi
往pod中寫入資料:
# kubectl exec -ti web-0 touch /data/test
# kubectl exec -ti web-0 ls /data
lost+found test
步驟2:建立VolumeSnapshot:
$ kubectl apply -f snapshot.yaml
apiVersion: snapshot.storage.k8s.io/v1beta1
kind: VolumeSnapshot
metadata:
name: new-snapshot-demo
spec:
volumeSnapshotClassName: default-snapclass
source:
persistentVolumeClaimName: disk-ssd-web-0
檢查叢集狀态,VolumeSnapshot、VolumeSnapshotContent建立完成,同時到ECS控制台檢視快照執行個體也建立完成:
# kubectl get volumesnapshots.snapshot.storage.k8s.io
NAME AGE
new-snapshot-demo 36m
# kubectl get VolumeSnapshotContent
NAME AGE
snapcontent-222d4dbb-beb4-49e5-8e11-ca6358c62123 36m
步驟3:資料恢複
$ kubectl apply -f sts-snapshot.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
---
apiVersion: apps/v1beta2
kind: StatefulSet
metadata:
name: web-restore
spec:
selector:
matchLabels:
app: nginx
serviceName: "nginx"
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
hostNetwork: true
containers:
- name: nginx
image: nginx
command: ["sh", "-c"]
args: ["sleep 10000"]
volumeMounts:
- name: disk-ssd
mountPath: /data
volumeClaimTemplates:
- metadata:
name: disk-ssd
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: alicloud-disk-ssd
resources:
requests:
storage: 20Gi
dataSource:
name: new-snapshot-demo
kind: VolumeSnapshot
apiGroup: snapshot.storage.k8s.io
在volumeClaimTemplates定義中指定dataSource為VolumeSnapshot類型,且選擇步驟2建立的名字為new-snapshot-demo的VolumeSnapshot。
檢視容器資料,驗證是否恢複成功:
# kubectl exec -ti web-restore-0 ls /data
lost+found test
可見實作了資料的恢複。
本方案隻給出了建立一個快照并進行恢複的場景,後續我們會提供建立定時快照的方案。