文章目录
目前官方Ceph csi版本已经支持Kubernetes 1.23,但是如果我们直接使用最新的ceph csi。在创建cephfs的时候会出现storageclass 创建pvc pending的状态。并且错误日志会提示persistentvolume-controller waiting for a volume to be created, either by external provisioner “cephfs.csi.ceph.com” or manually created by system administrator。因为我们默认yum的ceph deploy会默认给我们安装N版本的ceph,但是最新的Ceph csi版本已经到了Q版本,需要根据实际情况调整版本信息
这个报错的解决方法,修改ceph csi版本,测试得出v3.5.1可以兼容N版本。或者将Ceph集群升级为最新版
已知可用于平台
Ceph CSI驱动程序目前仅在Kubernetes环境中开发和测试。
v3.6.1 | Kubernetes | v1.21、v1.22、v1.23 |
v3.6.0 | Kubernetes | v1.21、v1.22、v1.23 |
v3.5.1 | Kubernetes | v1.21、v1.22、v1.23 |
v3.5.0 | Kubernetes | v1.21、v1.22、v1.23 |
v3.4.0 | Kubernetes | v1.21、v1.22、v1.23 |
Ceph csi组件介绍
ceph-csi组件-作用介绍
(1)create pvc时,external-provisioner组件监听到pvc创建事件后,负责拼接请求,然后调用ceph-csi的CreateVolume方法来创建存储;
(2)delete pvc时,pv对象状态由bound变为release,external-provisioner监听到pv更新事件后,负责拼接请求,调用ceph-csi的DeleteVolume方法来删除存储。
(3)create pod cliam pvc时,kubelet会调用ceph-csi组件将创建好的存储从ceph集群挂载到pod所在的node上,然后再挂载到pod相应的目录上;
(4)delete pod cliam pvc时,kubelet会调用ceph-csi组件相应方法,解除存储在pod目录上的挂载,再解除存储在node上的挂载。
ceph-csi组件-服务组成
ceph-csi含有rbdType、cephfsType、livenessType三大类型服务,可以通过启动参数指定一种服务来进行启动。
而rbdType、cephfsType类型的服务可以继续细分,包括了NodeServer、ControllerServer与IdentityServer三种具体的服务,其中NodeServer与ControllerServer只能选其一进行启动,IdentityServer会伴随着NodeServer或ControllerServer的启动而启动。
环境说明
本次环境信息如下
请务必确定好版本号,必须为N版,新版本需要参考官方最新csi-ceph
版本下载地址
#官方下载(后期官方会改名) wget https://github.com/ceph/ceph-csi/archive/refs/tags/v3.5.1.zip #abcdocker代理下载地址 wget https://d.frps.cn/file/tools/ceph-csi/cephfs/v3.5.1.zip
替换镜像
#由于官方镜像大部分都是海外k8s.io类型的,可能无法直接使用,所以我们需要替换 #解压压缩包,进入相关镜像目录 [root@k8s-01 cephfs]# cd ceph-csi-3.5.1/deploy/cephfs/kubernetes/ #替换镜像 sed -i s#k8s.gcr.io/sig-storage/csi-provisioner:v3.1.0#registry.cn-beijing.aliyuncs.com/abcdocker/csi-provisioner:v3.1.0#g csi-cephfsplugin-provisioner.yaml sed -i s#k8s.gcr.io/sig-storage/csi-resizer:v1.3.0#registry.cn-beijing.aliyuncs.com/abcdocker/csi-resizer:v1.3.0#g csi-cephfsplugin-provisioner.yaml sed -i s#k8s.gcr.io/sig-storage/csi-snapshotter:v4.2.0#registry.cn-beijing.aliyuncs.com/abcdocker/csi-snapshotter:v4.2.0#g csi-cephfsplugin-provisioner.yaml sed -i s#k8s.gcr.io/sig-storage/csi-attacher:v3.4.0#registry.cn-beijing.aliyuncs.com/abcdocker/csi-attacher:v3.4.0#g csi-cephfsplugin-provisioner.yaml sed -i s#quay.io/cephcsi/cephcsi:v3.5.1#registry.cn-beijing.aliyuncs.com/abcdocker/cephcsi:v3.5.1#g csi-cephfsplugin-provisioner.yaml sed -i s#k8s.gcr.io/sig-storage/csi-node-driver-registrar:v2.4.0#registry.cn-beijing.aliyuncs.com/abcdocker/csi-node-driver-registrar:v2.4.0#g csi-cephfsplugin-provisioner.yaml sed -i s#quay.io/cephcsi/cephcsi:v3.5.1#registry.cn-beijing.aliyuncs.com/abcdocker/cephcsi:v3.5.1#g csi-cephfsplugin.yaml sed -i s#k8s.gcr.io/sig-storage/csi-node-driver-registrar:v2.4.0#registry.cn-beijing.aliyuncs.com/abcdocker/csi-node-driver-registrar:v2.4.0#g csi-cephfsplugin.yaml
安装Ceph-csi
为sidecar容器和节点插件部署RBAC:
cd ceph-csi-3.5.1/deploy/cephfs/kubernetes/ kubectl create -f csi-provisioner-rbac.yaml kubectl create -f csi-nodeplugin-rbac.yaml
这些清单部署服务帐户、集群角色和集群角色绑定。这些是RBD和CephFS CSI插件共享的,因为它们需要相同的权限。
为sidecar容器和节点插件部署 PodSecurityPolicy资源:
注意:仅当PodSecurityPolicy 准入控制器在您的集群上处于活动状态时才需要这些清单。
cd ceph-csi-3.5.1/deploy/cephfs/kubernetes/ kubectl create -f csi-provisioner-psp.yaml kubectl create -f csi-nodeplugin-psp.yaml
为CSI插件部署ConfigMap:
获取ceph集群相关信息
获取ceph 集群ID
[root@ceph-01 ~]# ceph -s cluster: id: c8ae7537-8693-40df-8943-733f82049642 #这里为集群ID,需要复制保留 health: HEALTH_OK services: mon: 3 daemons, quorum ceph-01,ceph-02,ceph-03 (age 34h) #复制ceph mon节点ip mgr: ceph-03(active, since 34h), standbys: ceph-02, ceph-01 mds: cephfs-abcdocker:1 cephfs:1 {cephfs-abcdocker:0=ceph-03=up:active,cephfs:0=ceph-02=up:active} 1 up:standby osd: 4 osds: 4 up (since 34h), 4 in (since 8w) rgw: 2 daemons active (ceph-01, ceph-02) task status: data: pools: 14 pools, 688 pgs objects: 8.73k objects, 31 GiB usage: 96 GiB used, 84 GiB / 180 GiB avail pgs: 688 active+clean io: client: 36 KiB/s wr, 0 op/s rd, 0 op/s wr
编辑configmap文件
vim ceph-csi-config.yaml apiVersion: v1 kind: ConfigMap data: config.json: |- [ { "clusterID": "c8ae7537-8693-40df-8943-733f82049642", "monitors": [ "192.168.31.20:6789", "192.168.31.21:6789", "192.168.31.22:6789" ] } ] metadata: name: ceph-csi-config
这里不建议configmap名称修改
默认的deployment文件还有一个ceph-config configmap,这个也需要创建
vim ceph-config.yaml apiVersion: v1 kind: ConfigMap data: ceph.conf: | [global] auth_cluster_required = cephx auth_service_required = cephx auth_client_required = cephx # Workaround for http://tracker.ceph.com/issues/23446 fuse_set_user_groups = false # ceph-fuse which uses libfuse2 by default has write buffer size of 2KiB # adding 'fuse_big_writes = true' option by default to override this limit # see https://github.com/ceph/ceph-csi/issues/1928 fuse_big_writes = true # keyring is a required key and its value should be empty keyring: | metadata: name: ceph-config
创建configmap
[root@k8s-01 kubernetes]# kubectl apply -f ceph-csi-config.yaml configmap/ceph-csi-config created [root@k8s-01 kubernetes]# kubectl apply -f configmap.yaml configmap/ceph-config configured [root@k8s-01 kubernetes]# kubectl get cm NAME DATA AGE ceph-csi-config 1 3s kube-root-ca.crt 1 36d
Ceph csi原理组件以及通信原理介绍
external-provisioner(csi-provisioner)
在启动时通过--provisioner指定自身provisioner名称,与StorageClass中的provisioner字段对应。
(1)watch PVC对象,判断PVC是否需要动态创建存储卷,标准如下:
此时调用CSI Plugin的CreateVolume接口,同时创建名为${Provisioner指定的PV前缀}-${PVC uuid}的PV
(2)watch PV对象,判断其是否需要删除,标准如下:
若需要,则调用CSI Plugin的DeleteVolume接口,同时删除PV对象
external-attacher(csi-attacher)
external-snapshotter
(1)watch VolumeSnapshot对象,根据其状态调用CSI Plugin的CreateSnapshot接口
等存储快照生成后,它会将存储快照生成的相关信息放到VolumeSnapshotContent对象中,并和用户提交的VolumeSnapshot做bound
(2)当VolumeSnapsho处于删除状态(DeletionTimestamp非空)时,调用CSI Plugin的DeleteSnapshot接口
external-resizer
watch PVC对象,判断用户在PVC中是否增加了需求的存储空间。如果PVC状态是Bound且.status.Capacity与.spec.Resources.Requests不等,则进行卷扩展:
node-driver-registrar
调用CSI Plugin的接口获取插件信息,通过Kubelet的插件注册机制将CSI Plugin注册到kubelet
livenessprobe
调用CSI Plugin的Probe接口,同时在/healthz暴露HTTP健康检查探针
因此,CSI分为两部分:
CSI插件与CSI sidecar容器的组合
一般会在一个CSI Plugin容器中同时实现所有接口,使其同时作为CSI Controller Server和CSI Node Server
它会和Kubernetes官方提供的CSI sidecar容器组成Pod,每种组合都会完成某种功能:
CSI Controller Server和External CSI SideCar、CSI Node Server和Kubelet通过Unix Socket来通信:
通过CRD管理CSI
对CSI的管理是通过CRD的形式实现的,所以引入了自定义对象类型VolumeAttachment、CSINode、CSIDriver
VolumeAttachmen
VolumeAttachment描述一个Volume的attach/detach信息。可以通过VolumeAttachment对一个Volume在某个节点上的attach状态进行跟踪。
VolumeAttachmentSpec数据结构:
根据Driver name指定由哪个CSI Plugin来进行attach/detach
指定了attach/detach是发生在哪个节点上的
指定了对哪一个PV进行attach/detach。
VolumeAttachmentStatus数据结构:
指示了是否已经attach
如果VolumeAttachment的DeletionTimestamp为空且Attached=false,则external-attacher需要调用CSI Plugin的ControllerPublish做attach 如果VolumeAttachment的DeletionTimestamp不为空且Attached=true,则external-attacher需要调用CSI Plugin的ControllerUnPublish做detach
CSIDriver
CSIDriver描述了部署的CSI Plugin、定义了Kubernetes调用CSI Plugin的行为,需要管理员根据插件类型进行创建
CSIDriverSpec数据结构:
定义一个Plugin是否支持Attach功能。
不需要Attach操作时,该标签就是False,说明无需部署external-attacher,也不需要VolumeAttachment对象。
例子:调用CreateVolume接口时,CreateVolumeRequest中VolumeCapability决定了是文件系统直接挂载还是块设备挂载。块存储需要Attach操作,但文件存储不需要Attach操作,例如NFS没有挂载、格式化的概念,只需要mount远端文件系统到本地即可
定义了调用CSI Plugin的NodePublishVolume接口时是否带上Pod信息(PodName、PodUID、PodNamespace)。
默认为false,即CSI Plugin无法获知Pod信息
该CSI Plugin支持哪些VolumeLifecycleMode
包括Persistent和Ephemeral两种
若为true,表示希望调度器调度时考虑节点的存储容量
Volume挂载前是否允许更改属主、权限的定义
CSI Plugin可能需要Pod的Service Account Token
若为true,表示CSI Plugin希望不断被调用NodepublishVolume接口,以更新挂载到Pod中的Volume的相关变化。
不过只能更新Volume的contents,running状态Pod的挂载点是不能改变的
CSINode
CSINode是集群中的节点信息,由Node上的node-driver-registrar在启动时创建。
因此,可以只定义集群中一部分节点拥有CSINode。
CSINodeSpec由一组CSIDriver信息组成。每一个新的CSI Plugin注册后,都会在其中添加自身信息
每个CSI Plugin可添加的CSIDriver信息包括:
节点最多可以attach多少个Volume
该CSINode支持哪些TopologyKeys。进行支持拓扑感知的provisioning时,将会根据这些TopologyKeys从Node获取values,会传递给CSI Plugin
如果CSI Plugin不支持拓扑,可以置为null。
Csi原理部分需要详细查看请前往https://article.itxueyuan.com/vO01wa
部署 CSI Sidecar 容器:
kubectl create -f csi-cephfsplugin-provisioner.yaml 部署配置的部署,其中包括 CSI CephFS 的 external-provisioner、external-attacher。
部署 CSI CephFS 驱动程序:
kubectl create -f csi-cephfsplugin.yaml #部署一个包含两个容器的守护程序集:CSI node-driver-registrar 和 CSI CephFS 驱动程序。
查看csi pod
[root@k8s-01 kubernetes]# kubectl get pod NAME READY STATUS RESTARTS AGE csi-cephfsplugin-4qcf7 3/3 Running 0 19m csi-cephfsplugin-982v6 3/3 Running 0 19m csi-cephfsplugin-bgq6t 3/3 Running 0 19m csi-cephfsplugin-cfpqp 3/3 Running 0 19m csi-cephfsplugin-gxctq 3/3 Running 1 (19m ago) 19m csi-cephfsplugin-provisioner-7b58b6d568-7fq7x 6/6 Running 0 11m csi-cephfsplugin-provisioner-7b58b6d568-8snn8 6/6 Running 0 11m csi-cephfsplugin-provisioner-7b58b6d568-x8b4c 6/6 Running 0 11m
Ceph创建cephfs
CephFS 需要两个Pools - i4t_data和i4t_metadata, 分别存储文件数据和文件元数据
ceph osd pool create i4t_data 16 16 ceph osd pool create i4t_metadata 16 16
注:一般 metadata pool 可以从相对较少的 PGs 启动, 之后可以根据需要增加 PGs. 因为 metadata pool 存储着 CephFS 文件的元数据, 为了保证安全, 最好有较多的副本数. 为了能有较低的延迟, 可以考虑将 metadata 存储在 SSDs 上.
创建一个 CephFS, 名字为 i4tfs:
这里的i4tfs名称以及i4t_metadata i4t_data都需要保留,storageclass需要使用
ceph fs new i4tfs i4t_metadata i4t_data
创建Storageclass
首先我们需要创建一个secret,csi会通过pod访问ceph集群,但是访问集群需要一个用户,我这里就使用admin用户了
获取amdin key
[root@ceph-01 ~]# ceph auth get-key client.admin AQB1RtxhH/YeHhAAxID/JplTyq77Oa1Pso7HNQ==
使用stringData不需要base64加密
vim secret.yaml apiVersion: v1 kind: Secret metadata: name: csi-cephfs-secret stringData: userID: admin userKey: AQB1RtxhH/YeHhAAxID/JplTyq77Oa1Pso7HNQ== adminID: admin adminKey: AQB1RtxhH/YeHhAAxID/JplTyq77Oa1Pso7HNQ==
创建seceet检查
[root@k8s-01 kubernetes]# kubectl apply -f secret.yaml secret/csi-cephfs-secret created [root@k8s-01 kubernetes]# kubectl get secret NAME TYPE DATA AGE csi-cephfs-secret Opaque 4 5s
创建storageclass
vim i4t_storageclass.yaml apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: csi-cephfs-sc provisioner: cephfs.csi.ceph.com parameters: clusterID: c8ae7537-8693-40df-8943-733f82049642 fsName: i4tfs #cephfs名称,上面创建 pool: i4t_data #cephfs pool名称 # mounter: fuse #挂载方式 csi.storage.k8s.io/provisioner-secret-name: csi-cephfs-secret csi.storage.k8s.io/provisioner-secret-namespace: default csi.storage.k8s.io/controller-expand-secret-name: csi-cephfs-secret csi.storage.k8s.io/controller-expand-secret-namespace: default csi.storage.k8s.io/node-stage-secret-name: csi-cephfs-secret csi.storage.k8s.io/node-stage-secret-namespace: default reclaimPolicy: Delete allowVolumeExpansion: true mountOptions: - discard #对于支持 Delete 回收策略的卷插件,删除动作会将 PersistentVolume 对象从 Kubernetes 中移除,同时也会从外部基础设施(如 AWS EBS、GCE PD、Azure Disk 或 Cinder 卷)中移除所关联的存储资产。 动态供应的卷会继承其 StorageClass 中设置的回收策略,该策略默认 为 Delet #只有当 PVC 的存储类中将 allowVolumeExpansion 设置为 true 时,你才可以扩充该 PVC 申领
需要注意的是,storageclass需要和上面创建的secret名称对应上csi-cephfs-secret以及命名空间
创建sc并查看
[root@k8s-01 kubernetes]# kubectl apply -f i4t_storageclass.yaml storageclass.storage.k8s.io/csi-cephfs-sc created [root@k8s-01 kubernetes]# kubectl get sc NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE csi-cephfs-sc cephfs.csi.ceph.com Delete Immediate true 3s
创建pvc测试
编写pvc文件测试
vim pvc.yaml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: abcdocker-fs-data spec: accessModes: - ReadWriteMany resources: requests: storage: 1Gi storageClassName: csi-cephfs-sc #pvc名称为abcdocker-fs-data #资源大小为1G #ReadWriteMany # PV以read-write挂载到多个节点,cephfs特有访问模式
检查pvc
[root@k8s-01 kubernetes]# kubectl apply -f pvc.yal persistentvolumeclaim/abcdocker-fs-data created
我们可以看到,创建好pvc后会自动将我们pvc绑定到pv节点上
[root@k8s-01 kubernetes]# kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE abcdocker-fs-data Bound pvc-f931e74a-991b-440e-9180-9c7c283bf4a2 1Gi RWX csi-cephfs-sc 4s
可以顺便看一下pv
[root@k8s-01 kubernetes]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pvc-f931e74a-991b-440e-9180-9c7c283bf4a2 1Gi RWX Delete Bound default/abcdocker-fs-data csi-cephfs-sc 55s
挂载Pod测试
cat >nginx.yaml<<EOF apiVersion: apps/v1 kind: Deployment metadata: name: nginx-abcdocker spec: replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:latest ports: - containerPort: 80 name: web volumeMounts: - name: www mountPath: /usr/share/nginx/html subPath: html volumes: - name: www persistentVolumeClaim: claimName: abcdocker-fs-data #填写pvc名称 EOF
进入到nginx容器1中创建静态文件
[root@k8s-01 kubernetes]# kubectl get pod|grep nginx-abcdocker nginx-abcdocker-7bb898c45c-48t9k 1/1 Running 0 64s nginx-abcdocker-7bb898c45c-7mvtw 1/1 Running 0 64s [root@k8s-01 kubernetes]# kubectl exec -it nginx-abcdocker-7bb898c45c-48t9k bash kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead. root@nginx-abcdocker-7bb898c45c-48t9k:/# root@nginx-abcdocker-7bb898c45c-48t9k:/# echo "abcdocker" >>/usr/share/nginx/html/index.html
到nginx 2中查看
[root@k8s-01 kubernetes]# kubectl get pod|grep nginx-abcdocker nginx-abcdocker-7bb898c45c-48t9k 1/1 Running 0 2m19s nginx-abcdocker-7bb898c45c-7mvtw 1/1 Running 0 2m19s [root@k8s-01 kubernetes]# kubectl exec -it nginx-abcdocker-7bb898c45c-7mvtw bash kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead. root@nginx-abcdocker-7bb898c45c-7mvtw:/# cat /usr/share/nginx/html/index.html abcdocker
相关文章:
- Kubernetes(k8s) 1.24 csi-ceph rbd使用手册
- Prometheus Grafana使用Ceph持久化并监控k8s集群
- Kubernetes 滚动更新及回滚
- 持久化存储 StorageClass