当前 CDS 磁盘支持以 FlexVolume 和 CSI 形式(要求集群k8s版本≥1.11)在集群中挂载。FlexVolume 形式支持直接在 Pod 中以 volume 方式挂载,CSI 形式挂载需要创建 PV 和 PVC 存储资源后,再将 PVC 挂载到 Pod 中。两种挂载方案都可以满足容器内特定数据持久化的需求,两者详细的区别请参考 kubernetes 官方文档:
- Volumes
- Persistent Volumes
准备工作
用户做好以下准备,才能在容器中挂载 CDS 实例:
- 注册百度账号,并完成实名认证;
- 创建一个 CCE K8S 集群。
注意:集群节点所处地域和可用区相同的 CDS 磁盘已创建,CDS 磁盘状态为未挂载。
创建容器集群
- 创建一个容器集群,操作步骤参考创建集群。
- 下载命令行客户端 kubectl,并连接集群,操作步骤参考通过kubectl连接Kubernetes集群。
操作指南
通过 PV/PVC 方式挂载
1. 安装 CSI CDS 插件
- 依次选择:容器引擎 CCE -> Helm 模版 -> 百度云模版
- 通过模版名称 cce-csi-cds-plugin 搜索模版
- 点击安装并填写相应的参数
参数说明
- 实例名称:插件实例名称,例:cds;
- 部署集群:选择需要部署 CDS CSI 插件的集群;
- 命名空间:管理实例的 helm 元数据的命名空间,例:kube-system;
- kubernetets 版本:填写实际部署集群的版本,目前支持:1.20、1.18、1.16、1.13;
- nodes:如果部署集群的节点的时候,指定了 kubelet 的数据目录,需要填写具体使用的数据目录到该列表,否则保持默认即可;
- region: 填写部署的集群所在的region,包括:bj(北京), su(苏州), gz(广州), bd(保定), hkg(香港), fwh(武汉);
2. 将 CDS 挂载到 Pod 中
通过PV/PVC方式使用CDS,具体分为两种方式:
- 静态挂载:需要用户提前在百度智能云中创建好CDS(操作方法参考CDS文档),然后通过CDS的volume id在集群中创建PV和PVC资源。
- 动态挂载:用户在集群中声明PVC时,自动创建出CDS磁盘并且动态关联至PV。
静态挂载的方式需要用户提供的CDS磁盘处于未挂载状态,并且确保填入正确的volume id。动态挂载在部分场景下可能会更加方便,但是需要注意动态挂载时将会自动创建CDS磁盘并且计费,动态创建的CDS将会随着用户删除PVC时被联动删除(需要将对应storageClass的reclaimPolicy参数设置为delete),但是如果用户在没有删除PVC的情况下直接删除了CCE集群,则需要手动对这些CDS进行处理。
静态挂载
创建PV/PVC
使用kubectl,执行 kubectl create -f pv-cds.yaml 完成PV的创建
对应的pv-cds.yaml文件如下所示:
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-cds
namespace: "default"
spec:
accessModes:
- ReadWriteOnce
capacity:
storage: 5Gi
csi:
driver: "csi-cdsplugin"
volumeHandle: "v-xxxx"
fsType: "ext4"
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: failure-domain.beta.kubernetes.io/zone
operator: In
values:
- zoneA
persistentVolumeReclaimPolicy: Retain
注意:
- yaml中volumeHandle字段对应的是cds volume id(短 id)。
- yaml中fsType字段不填写时默认值为ext4。Filesystem模式下,若fsType与cds中实际文件系统类型不匹配,将导致挂载失败;若cds中尚无文件系统,则挂载时自动格式化cds为fsType指定的文件系统。
- yaml中nodeAffinity中需要指定cds所在可用区,保证挂载该cds的pod只会被调度到与cds磁盘同可用区的node上。
创建PV后,输入kubectl get pv可以看见一个available状态的PV,如下所示:
$ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv-cds 5Gi RWO Retain Available 22s
建立一个能够与该PV绑定的PVC
使用kubectl,执行 kubectl create -f pvc-cds.yaml完成PVC的创建
对应的pvc-cds.yaml文件如下所示:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: csi-cds-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
绑定前,PVC为pending状态
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
cds-pvc Pending 2s
绑定后,PV和PVC状态变为Bound
$ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv-cds 5Gi RWO Retain Bound default/csi-cds-pvc 4s
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
csi-cds-pvc Bound pv-cds 5Gi RWO 36s
有关PV和PVC的更多设置和字段说明,见k8s官方文档
创建POD
在Pod spec内指定相应的PVC名称即可,使用kubectl,执行 kubectl create -f demo-cds-rc.yaml 完成rc的创建 对应的demo-cds-rc.yaml文件如下所示:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-server-deployment
labels:
test: ws
spec:
replicas: 1
selector:
matchLabels:
se: ws
template:
metadata:
labels:
se: ws
name: web-server
spec:
containers:
- name: web-server
image: nginx
volumeMounts:
- mountPath: /var/lib/www/html
name: csi-cds-pvc
volumes:
- name: csi-cds-pvc
persistentVolumeClaim:
claimName: csi-cds-pvc
Pod创建后,可以读写容器内的/var/lib/www/html路径来访问相应的cds存储上的内容。
由于创建PV和PVC时只支持accessModes为ReadWriteOnce,该PVC可以被一节点上的Pod挂载读写。
释放PV/PVC
完成存储资源的使用后,可以释放PVC和PV资源,使用以下命令可以释放PVC
$ kubectl delete -f pvc-cds.yaml
释放PVC后,原来与之绑定的PV状态会变为Release,如下所示:
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv-cds 5Gi RWO Retain Released default/csi-cds-pvc 4m
输入以下指令释放PV资源
$ kubectl delete -f pv-cds.yaml
动态挂载
创建 StorageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: hp1 #名字可以自定义
provisioner: csi-cdsplugin
allowVolumeExpansion: true
parameters:
paymentTiming: "Postpaid" #Prepaid or Postpaid
storageType: "hp1" #支持cloud_hp1, hp1, hdd
reservationLength: "3" #Prepaid 模式下需要填写
reclaimPolicy: Delete #支持 Delete、Retain 默认值为 Delete
StorageClass 参数说明:
storageType
用于设置动态创建的 CDS 盘的类型,支持:cloud_hp1 (通用型SSD),hp1 (高性能云磁盘),hdd (通用型HDD),具体可参考 BCC OpenAPI 创建 CDS 盘接口中的 storageType 参数的说明:https://cloud.baidu.com/doc/BCC/s/Ujwvyo1ta
paymentTiming
用于设置付费方式是:预付费 or 后付费
reservationLength
磁盘的保留时间,预付费模式下需要填写,单位为月
创建 PVC
在 PVC Spec 中指定上面创建的 StorageClass 名称,则在创建PVC时,会自动生成相应的PV进行绑定。
使用kubectl,执行 kubectl create -f csi-pvc-cds.yaml 完成PVC的创建。
假设创建的StorageClass名称为hp1,对应的 csi-pvc-cds.yaml 文件如下所示:
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: csi-pvc-cds
spec:
accessModes:
- ReadWriteOnce
storageClassName: hp1
resources:
requests:
storage: 5Gi
PVC参数说明: PVC 中 resource request的 storge,对于不同StorageClass中不同storageType有相关限制。 hp1: 5~32765GB cloud_hp1: 50~32765GB hdd:5~32765GB
创建PVC后,可以看见相应的PV自动创建,PVC状态变为Bound,即PVC已经与新创建的PV绑定。
$ kubectl create -f csi-pvc-cds.yaml
persistentvolumeclaim "csi-pvc-cds" created
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
csi-pvc-cds Bound pvc-1ab36e4d1d2711e9 5Gi RWX hp1 4s
$ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-1ab36e4d1d2711e9 5Gi RWX Delete Bound default/csi-pvc-cds hp1 7s
在Pod内挂载PVC
在Pod spec内指定相应的PVC名称即可,使用kubectl,执行 kubectl create -f dynamic-cds-pod.yaml 完成资源的创建。对应的dynamic-cds-pod.yaml文件如下所示:
apiVersion: v1
kind: Pod
metadata:
name: test-pvc-pod
labels:
app: test-pvc-pod
spec:
containers:
- name: test-pvc-pod
image: nginx
volumeMounts:
- name: cds-pvc
mountPath: "/cds-volume"
volumes:
- name: cds-pvc
persistentVolumeClaim:
claimName: csi-pvc-cds
Pod创建后,可以读写容器内的/cds-volume路径来访问相应的cds存储上的内容。
释放PVC时动态销毁绑定PV
删除PVC时,与之绑定的动态PV是否会被自动删除由自定义的 StorageClass 中 reclaimPolicy 决定;reclaimPolicy 支持 Delete、Retain 默认值为 Delete。
- Delete:删除 PVC 会自动删除 PV,并且动态申请的 CDS 会被自动释放
- Retain:删除 PVC 时 PV 状态会变成 Released,不会自动删除 PV,对应自动创建的 CDS 需要到 CDS console上手动释放
$ kubectl delete pvc csi-pvc-cds
persistentvolumeclaim "csi-pvc-cds" deleted
$ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM
pvc-1ab36e4d1d2711e9 40Gi RWO Retain Released default/csi-pvc-cds hp1 3m
在 StatefuleSet 里通过 claimTemple 批量使用 pvc 的场景,需要前置步骤为创建 StorageClass
以 sts-claim.yaml为例
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
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 5Gi
storageClassName: hp1
创建 sts-claim.yaml,同时会自动创建 PVC:
$ kubectl apply -f sts-claim.yaml
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 3m
web-1 1/1 Running 0 2m
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
www-web-0 Bound pvc-a1e885701d2f11e9 5Gi RWO hp1 6m
www-web-1 Bound pvc-c91edb891d2f11e9 5Gi RWO hp1 5m
多可用区集群使用cds
(1)StorageClass指定zone方式
目前 cds不支持跨可用区,如果cce集群中有多个可用区的机器,动态创建cds需要通过设置StorageClass中allowedTopologies字段和volumeBindingMode等指定可用区实现;使用已有cds时,须指定PV的nodeAffinity参数实现可用区亲和性。
CCE集群默认会为集群节点打上可用区标签:
$ kubectl get nodes --show-labels NAME STATUS ROLES AGE VERSION LABELS 192.168.80.15 Ready <none> 13d v1.8.12 beta.kubernetes.io/arch=amd64,beta.kubernetes.
io/instance-type=BCC,beta.kubernetes.io/os=linux,failure-domain.beta.kubernetes.io/region=bj,failure-domain.
beta.kubernetes.io/zone=zoneC,kubernetes.io/hostname=192.168.80.15
其中 failure-domain.beta.kubernetes.io/zone=zoneC 标签说明该集群节点处于C可用区。
1)多可用区集群使用 cds 例子
StorageClass-Multi-Zone-Temple.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: hp1-zonec
provisioner: csi-cdsplugin
parameters:
paymentTiming: "Postpaid"
storageType: "hp1"
reservationLength: "3"
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
allowedTopologies:
- matchLabelExpressions:
- key: failure-domain.beta.kubernetes.io/zone
values:
- zoneC
Sts-Multi-Zone-Temple.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: sts-multi-zone
spec:
serviceName: "nginx"
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 40Gi
storageClassName: hp1-zonec
(2)设置 StorageClass的Volume Binding Mode 通过指定WaitForFirstConsumer和配置PersistentVolume 的模式来解决此问题,指定绑定模式为WaitForFirstConsumer,K8S会先进行调度 Pod,随后创建 CDS。
1)使用示例
StorageClass-WaitForFirstConsumer-Temple.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: csi-cds
provisioner: csi-cdsplugin
volumeBindingMode: WaitForFirstConsumer
parameters:
dynamicVolume: "true"
cdsSizeInGB: "40"
paymentTiming: "Postpaid"
storageType: "hp1"
reclaimPolicy: Delete
Sts-WaitForFirstConsumer-Temple.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
serviceName: "nginx"
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 5Gi
storageClassName: csi-cds
具体详情请看相关文档 StorageClass
注意:
- 如果需要销毁 cce集群并且使用了本文中的 csi-provisioner 同时 storageClass中reclaimPolicy设置为 Delete,请先 delete pvc,否则可能会存在cds 无法自动释放。
在单个Pod中挂载多块CDS
注意:
- 在Pod Spec的volumes字段中,每块CDS只能被声明一次。
- 在Pod Spec的volumeMounts字段中,每块CDS对应的volume可以被引用多次。
- 对于Deployment/ReplicaSet等资源,replicas域只能设置为1。
下面的示例 cds-multi-mount-example.yaml 将文件中声明的四块CDS磁盘分别挂载到Pod mysql-nginx内的my-nginx和my-mysql两个容器的相应路径下,其中test-data和test-data-2两个volume对应的CDS为两个容器共享,而nginx-data和db-data两个volume对应的CDS分别只挂载在各自容器中。
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql-nginx
spec:
replicas: 1
selector:
matchLabels:
app: mysql-nginx
template:
metadata:
name: mysql-nginx
labels:
app: mysql-nginx
spec:
containers:
- name: my-nginx
image: nginx
volumeMounts:
- name: nginx-data
mountPath: /nginx-data
- name: test-data
mountPath: /test-data
- name: test-data-2
mountPath: /test-data-2
ports:
- containerPort: 80
- name: my-mysql
image: mysql:5.7
volumeMounts:
- name: db-data
mountPath: /db-data
- name: test-data
mountPath: /test-data
- name: test-data-2
mountPath: /test-data-2
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
value: M6jshva8hTXAGnin
volumes:
- name: db-data
flexVolume:
driver: "baidubce/cds"
fsType: "ext4"
options:
volumeID: "v-Hd8MUXA7"
- name: nginx-data
flexVolume:
driver: "baidubce/cds"
fsType: "ext4"
options:
volumeID: "v-OWEHtlSI"
- name: test-data
flexVolume:
driver: "baidubce/cds"
fsType: "ext4"
options:
volumeID: "v-9PhGVoMu"
- name: test-data-2
flexVolume:
driver: "baidubce/cds"
fsType: "ext4"
options:
volumeID: "v-SxjD482V"
flexVolume字段说明:
- fsType:CDS磁盘的文件系统,如果是新建的CDS磁盘,将会自动格式化该CDS磁盘为该文件系统
- volumeID:CDS磁盘ID,您可以从百度智能云控制台的页面获取
使用 kubectl create -f cds-multi-mount-example.yaml 创建相应的资源,相应的CDS磁盘将会被挂载到文件中声明的各个目录下。Pod在集群内发生漂移时,这些CDS磁盘将会跟随Pod一同迁移。
扩容 CDS PV
扩容CDS PV功能要求集群 Kubernetes版本 ≥ 1.16,同时只针对动态创建的CDS PV生效。
扩容CDS PV的操作步骤如下:
- 确认对应的storageClass中已经添加 allowVolumeExpansion: true 配置。
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: hp1
allowVolumeExpansion: true #允许磁盘扩容
...
- 修改与PV绑定的PVC中 spec.resources.requests 中的磁盘容量为目标容量,触发扩容。
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: csi-pvc-cds
spec:
accessModes:
- ReadWriteOnce
storageClassName: hp1
resources:
requests:
storage: 8Gi #修改为目标磁盘大小
- 默认情况下CDS CSI插件仅支持离线扩容,即需要在PVC未被Pod挂载时才会执行实际扩容动作。完成PVC容量request修改后,如果此时该PVC未被任何Pod挂载,则会触发CDS磁盘扩容操作,否则会等待挂载该PVC的Pod停止后才开始扩容。具体扩容进度可以通过kubectl describe pvc <pvcName>查看对应的Events了解。
如果需要在PVC被Pod挂载状态下进行在线扩容,可以通过kubectl -n kube-system edit deployment csi-cdsplugin-controller-server,给csi-cdsplugin容器的添加启动参数--enable-online-expansion,来启用在线扩容功能。但需要特别注意的是,同时进行磁盘读写和磁盘扩容可能导致*数据损坏*,非必要场景不建议开启在线扩容功能。
通过FlexVolume方式挂载
注意:
- CDS 同一时间只能挂载在一台bcc实例上。
- CDS 同一时间只能被一个Pod声明使用。
- 对于 Deployment/ReplicaSet 等资源,replicas 域只能设置为1。
1. 安装 CDS FlexVolume 插件
将如下内容保存为 cds-flexVolume.yaml ,执行 kubectl create -f cds-flexVolume.yaml 安装 cds flexVolume 插件。
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: cds-flex-volume-ds
namespace: kube-system
spec:
selector:
matchLabels:
app: cds-flex-volume-ds
template:
metadata:
name: cds-flex-volume-ds
labels:
app: cds-flex-volume-ds
spec:
hostNetwork: true
priorityClassName: system-node-critical
nodeSelector:
beta.kubernetes.io/os: linux
containers:
- image: hub.baidubce.com/jpaas-public/cds-flex-volume:latest
imagePullPolicy: Always
name: cds-flex-volume-ds
resources:
requests:
cpu: 20m
memory: 20Mi
limits:
cpu: 200m
memory: 200Mi
securityContext:
privileged: true
volumeMounts:
- name: flexvolume-mount
mountPath: /flexmnt
- name: log-volume
mountPath: /log-volume
volumes:
- name: flexvolume-mount
hostPath:
path: /usr/libexec/kubernetes/kubelet-plugins/volume/exec
- name: log-volume
hostPath:
path: /var/log
等待对应的 Pod 处于 Running 状态后,插件安装完成。
2. 将 CDS 磁盘挂载到 Pod 中
安装 CDS flexVolume 插件后,下面的示例 cds-example.yaml 将文件中声明的 CDS 磁盘挂载到 Pod 内 my-nginx 容器的 /data 路径下。
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
replicas: 1
selector:
matchLabels:
app: my-nginx
template:
metadata:
name: my-nginx
labels:
app: my-nginx
spec:
containers:
- name: my-nginx
image: nginx
volumeMounts:
- name: cds-data
mountPath: /data
ports:
- containerPort: 80
volumes:
- name: cds-data
flexVolume:
driver: "baidubce/cds"
fsType: "ext4"
options:
volumeID: "v-hTXAGtin"
flexVolume字段说明:
- fsType:CDS磁盘的文件系统,如果是新建的CDS磁盘,将会自动格式化该CDS磁盘为该文件系统
- volumeID:CDS磁盘ID,您可以从百度智能云控制台的页面获取
使用 kubectl create -f cds-example.yaml 创建相应的资源,相应的CDS磁盘将会被挂载到my-nginx容器内的/data目录下。Pod在集群内发生漂移时,该CDS磁盘将会跟随Pod一同迁移。