摘要
总结一下kubernetes对接Ceph过程中遇到的问题,持续更新中 ……
一、环境准备
实验环境有点特殊,先部署了一套超融合环境,openstack(M版)+ceph(L版),且全部容器化。之后在openstack平台上起了3台Centos7.1虚机,并在这3台虚机上部署了kubernete 1.9.3版本。
二、手工创建Image
找了一些资料,讲的都不是很全,所以这里先讲一下我的理解。这一步操作的目的是在ceph上创建一个块存储,然后通过内核将这个块存储映射给k8s所在的虚机,最后k8s将Pod建在这个块存储上。
所以第一步得把块存储创建出来,在ceph上执行:
rbd create foo2 --size 1024
rbd feature disable foo exclusive-lock, object-map, fast-diff, deep-flatten
之后在物理机上加载内核(Pod将起在的那台物理机上,注意是物理机,不是Node,不是kvm,也不是docker)
sudo modprobe rbd
进入Pod将起的Node(或者说kvm虚机),然后把ceph任意一个osd的/etc/ceph目录拷过来,并安装ceph(yum install ceph或其它方式),最后执行map映射
rbd map foo
检查一下结果
之后执行一下格式化
sudo mkfs.ext4 -m0 /dev/rbd0
三、创建Pod
上一步结束之后,等于已经在ceph上挂了一块盘给了k8s的某个Node节点,这一步就是要在该节点上创建Pod并mount这个盘。
先给这个Node打个tag
kubectl label nodes k8s2 zone=k8s2
从github上下载官方测试用例
git clone https://github.com/kubernetes/examples.git
修改 xxxx/cephJoint/examples/staging/volumes/rbd/rbd.yaml文件如下:
apiVersion: v1
kind: Pod
metadata:
name: busybox
namespace: default
spec:
nodeSelector:
zone: k8s2
containers:
- name: busybox
image: registry.cn-hangzhou.aliyuncs.com/yanfulei/busybox:latest
volumeMounts:
- name: rbdpd
mountPath: /mnt/rbd
command:
- sleep
- "3600"
imagePullPolicy: IfNotPresent
restartPolicy: Always
volumes:
- name: rbdpd
rbd:
monitors:
- '172.16.170.130:6789'
- '172.16.170.131:6789'
- '172.16.170.132:6789'
pool: rbd
image: foo
fsType: ext4
readOnly: true
user: admin
keyring: /etc/ceph/ceph.client.admin.keyring
启动Pod
kubectl create -f rbd.yaml
检查一下启动结果,大概要2分钟左右吧,取决于你前面创建的ceph块有多大,k8s会将这块盘格式化一遍,需要一些时间。
四、问题与思考
上述的挂载方式还存在一个很大的问题,简单来试一下,新创建了一个centos的pod如图:
然后再通过kubectl delete 删掉之后,我们检查一下设备,就会发现挂载到k8s2这个node上的盘已经被回收了。再次用相同的命令启动,会发现挂载失败的错误。
所以说这种对接场景下,Ceph RBD存储的生命周期和Pod是一致的,Pod被删了,数据也没了。所以在生产环境中需要有持久化的对接方式。
五、使用PV和PVC挂载Pod
具体过程不想发了,yaml到处都是,大致过程就是建一个PV,建一个PVC,最后Pod建在PVC上面。当Pod删掉之后,PV和PVC都在。重建Pod之后,容器里挂的盘依然不变,甚至容器从Centos换成ubuntu等,盘还是那个盘,盘里的东西还是原来的东西。
六、使用Kubernetes StorageClass
解决了持久化问题之后,又有一个新的需要思考的问题,生产环境中不可能手工先在ceph上建一个RBD块,再通过内核mount给Node吧,那该怎么让k8s自动调度分配存储空间?这时候就需要使用k8s的StorageClass功能了。
先创建一个StorageClass
[root@k8s1 rbd]# cat rbd-storage-class.yaml
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: rbd
provisioner: kubernetes.io/rbd
parameters:
monitors: 172.16.170.130:6789
adminId: admin
adminSecretName: ceph-secret
adminSecretNamespace: default
pool: rbd
userId: admin
userSecretName: ceph-secret
再创建一个PV
[root@k8s1 rbd]# cat rbd-dyn-pv-claim.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: ceph-rbd-dyn-pv-claim
spec:
accessModes:
- ReadWriteOnce
storageClassName: rbd
resources:
requests:
storage: 1Gi
最后创建一个Pod
[root@k8s1 rbd]# cat rbd-dyn-pvc-pod1.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
test: rbd-dyn-pvc-pod
name: ceph-rbd-dyn-pv-pod1
spec:
containers:
- name: ceph-rbd-dyn-pv-busybox1
image: registry.cn-hangzhou.aliyuncs.com/yanfulei/busybox
command: ["sleep", "60000"]
volumeMounts:
- name: ceph-dyn-rbd-vol1
mountPath: /mnt/ceph-dyn-rbd-pvc/busybox
readOnly: false
volumes:
- name: ceph-dyn-rbd-vol1
persistentVolumeClaim:
claimName: ceph-rbd-dyn-pv-claim
这时候就不再依赖nodeSelector调度了,通过kubectl describe看到Pod已经被调度到了k8s3上
之后登入k8s3节点看一下容器磁盘,发现已经成功挂了一块1G的盘给Pod