一、创建ceph存储池
在ceph集群的mon节点上执行以下命令:
ceph osd pool create k8s 64
查看下副本数
# ceph osd pool get k8s size
size: 2
pg的设置参照以下公式:
Total PGs = ((Total_number_of_OSD * 100) / max_replication_count) / pool_count
结算的结果往上取靠近2的N次方的值。比如总共OSD数量是2,复制份数3,pool数量也是1,那么按上述公式计算出的结果是66.66。取跟它接近的2的N次方是64,那么每个pool分配的PG数量就是64。
二、在k8s上操作
1、安装客户端(客户端版本与ceph集群的版本最好一致,不然创建image的时候死活创建不了):
本人是自己镜像的yum源
# yum repolist
Loaded plugins: fastestmirror, priorities
Loading mirror speeds from cached hostfile
252 packages excluded due to repository priority protections
repo id repo name status
!Ceph-noarch Ceph noarch packages 225
!base CentOS-7 - Base 10,011+8
!centos-ceph-luminous CentOS-7 - Ceph Luminous 0+225
!docker-ce-stable/x86_64 Docker CE Stable - x86_64 52
!epel Extra Packages for Enterprise Linux 7 - x86_64 13,264+19
!extras CentOS-7 - Extras 419
!updates CentOS-7 - Updates
给yum增加一个Ceph源(这里以网易源为例,未测试)。
tee /etc/yum.repos.d/ceph.repo <<-'EOF'
[Ceph]
name=Ceph packages for $basearch
baseurl=http://mirrors.163.com/ceph/rpm-jewel/el7/$basearch
enabled=1
gpgcheck=0
type=rpm-md
gpgkey=https://mirrors.163.com/ceph/keys/release.asc
priority=1
[Ceph-noarch]
name=Ceph noarch packages
baseurl=http://mirrors.163.com/ceph/rpm-jewel/el7/noarch
enabled=1
gpgcheck=0
type=rpm-md
gpgkey=https://mirrors.163.com/ceph/keys/release.asc
priority=1
[ceph-source]
name=Ceph source packages
baseurl=http://mirrors.163.com/ceph/rpm-jewel/el7/SRPMS
enabled=1
gpgcheck=0
type=rpm-md
gpgkey=https://mirrors.163.com/ceph/keys/release.asc
priority=1
EOF
安装依赖
yum install -y yum-utils && \
yum-config-manager --add-repo https://dl.fedoraproject.org/pub/epel/7/x86_64/ && \
yum install --nogpgcheck -y epel-release && \
rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7 && \
rm -f /etc/yum.repos.d/dl.fedoraproject.org*
三、静态PV
创建ceph secret
在ceph mon节点运行 ceph auth get-key client.admin 命令获取admin的key。定义一个ceph secret文件。
# ceph auth get-key client.admin | base64 >> key
cat key
QVFEYVRrVmRXSW1KRkJBQTR2MkphcUkxVFVxRHhDQ1V0SVhGS2c9PQ==
apiVersion: v1
kind: Secret
metadata:
name: ceph-secret
data:
key: QVFEYVRrVmRXSW1KRkJBQTR2MkphcUkxVFVxRHhDQ1V0SVhGS2c9PQ==
注意: 文件中的key需要在ceph mon节点使用 ceph auth get-key client.admin | base64 命令对获取的key进行base64。
保存定义的文件,如 ceph-secret.yaml , 之后创建一个secret:
# kubectl create -f ceph-secret.yaml
secret "ceph-secret" created
# kubectl get secret
NAME TYPE DATA AGE
ceph-secret kubernetes.io/rbd 1 91m
创建Persistent Volume
# rbd create --pool k8s ceph-image -s 128
# rbd feature disable k8s/ceph-image object-map fast-diff deep-flatten
创建一个PV对象,使用下面文件的定义:
# vim ceph-static-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: ceph-static-pv
spec:
capacity:
storage: 2Gi
accessModes:
- ReadWriteOnce
rbd:
monitors:
monitors:
- k8s-master1:6789
- k8s-master2:6789
- k8s-master3:6789
pool: k8s
image: ceph-image
user: admin
secretRef:
name: ceph-secret
fsType: ext4
readOnly: false
persistentVolumeReclaimPolicy: Recycle
注意: 我们这里直接使用了ceph默认的pool rbd, 由于文件中使用了ceph-image,所以需要在ceph集群中创建该镜像。
保存定义的PV文件,如ceph-pv.yaml,并创建一个PV:
# kubectl create -f ceph-static-pv.yaml
persistentvolume "ceph-pv" created
查看PV的状态是否正常,如果获取的状态是Available则说明该PV处于可用状态,并且没有被PVC绑定。
# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
ceph-pv 1Gi RWO Recycle Available 56s
创建Persistent Volume Claim
PVC需要指定访问模式和存储的大小,当前只支持这两个属性,一个PVC绑定到一个PV上。一旦PV被绑定到PVC上就不能被其它的PVC所绑定。它们是一对一的关系。但是多个Pod可以使用同一个PVC进行卷的挂载。
PVC的定义文件如下:
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: ceph-claim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
保存定义的文件,并基于该文件创建PVC,并检查其状态,如果状态为Bound则说明该PVC已经绑定到PV,如果状态为Pending或Failed则表示PVC绑定PV失败,可用通过查看PVC事件或者kubernetes各个组件日志进行错误排查。
# kubectl create -f ceph-task-claim.yaml
persistentvolumeclaim "ceph-claim" created
# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
ceph-claim Bound ceph-static-pv 2Gi RWO 7s
创建Pod
定义一个Pod,在Pod里面启动一个container,并使用PVC去挂载Ceph RBD卷为读写模式。
apiVersion: v1
kind: Pod
metadata:
name: ceph-pod2
spec:
containers:
- name: ceph-busybox
image: busybox
command: ["sleep", "60000"]
volumeMounts:
- name: ceph-vol1
mountPath: /usr/share/busybox
readOnly: false
volumes:
- name: ceph-vol1
persistentVolumeClaim:
claimName: ceph-claim
保存Pod的定义文件,如: ceph-pod.yaml。并创建该Pod。之后查看Pod的状态,如果Running则表示卷挂载成功,Pod正常运行。 这样便可以做个简单的操作,进行到该Pod的容器中,向 /usr/share/busybox 目录写入一些数据,之后删除该Pod,在创建一个新的Pod,看之前的数据是否还存在:)
# kubectl create -f ceph-static-pod.yaml
pod/ceph-pod2 created
kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
ceph-pod2 1/1 Running 0 20s 10.139.54.211 app31.add.bjdt.qihoo.net
四、动态PV
创建RBD pool
虽然ceph提供了默认的pool rbd,但是建议创建一个新的pool为kubernetes持久化使用。在ceph的monitors节点创建一个名为 kube 的pool.
# ceph osd pool create kube 64
# ceph auth get-or-create client.kube mon 'allow r' osd 'allow class-read object_prefix rbd_children, allow rwx pool=kube' -o ceph.client.kube.keyring
创建ceph secret
与静态创建的ceph-secret是同一个,这里就不在重复创建。
创建kube用户的ceph secret
在ceph monitors节点运行命令 ceph auth get-key client.kube 获取kube用户的key。并对该用户key进行base64用于下面的文件。
# ceph auth get-key client.kube | base64 > key2
# cat key2
QVFEMjNVWmRIcVc1SUJBQXVmZmdDMXlKNjZ0YlJrRmxMUnhOa0E9PQ==
apiVersion: v1
kind: Secret
metadata:
name: ceph-kube-secret
namespace: default
data:
key: QVFEMjNVWmRIcVc1SUJBQXVmZmdDMXlKNjZ0YlJrRmxMUnhOa0E9PQ==
type:
kubernetes.io/rbd
保存定义的ceph secret文件,如ceph-kube-secret.yaml。执行如下命令创建secret:
# kubectl create -f ceph-d-secret.yaml
secret/ceph-kube-secret created
查看secret是否创建成功。
# kubectl get secret ceph-kube-secret
NAME TYPE DATA AGE
ceph-kube-secret kubernetes.io/rbd 1 2m
创建动态RBD StorageClass
在创建StorageClass资源前,先介绍下StorageClass的概念: StorageClass 为管理员提供了描述存储 class 的方法。 不同的 class 可能会映射到不同的服务质量等级或备份策略,或由群集管理员确定的任意策略。 Kubernetes 本身不清楚各种 class 代表的什么。这个概念在其他存储系统中有时被称为“配置文件”。StorageClass不仅仅使用与ceph RBD还可以用于 Cinder , NFS , Glusterfs 等等。
vim rbd-storage-class.yaml
好了,下面我们来创一个动态的storage class。定义文件如下:
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: dynamic
annotations:
storageclass.beta.kubernetes.io/is-default-class: "true"
provisioner: kubernetes.io/rbd
parameters:
monitors: k8s-master1:6789,k8s-master2:6789,k8s-master3:6789
adminId: admin
adminSecretName: ceph-secret
pool: kube
userId: kube
userSecretName: ceph-kube-secret
fsType: ext4
imageFormat: "1"
保存文件,并创建storage class。
# kubectl create -f rbd-storage-class.yaml
storageclass "dynamic" created
检查storage class是否创建成功。
# kubectl get storageclass
NAME PROVISIONER AGE
dynamic (default) kubernetes.io/rbd 54s
创建Persistent Volume Claim
具体的描述细节请看创建静态PV时,对PVC的描述。或查看官方文档。下面我们直接定义PVC文件。
vim static-ceph-pvc.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: ceph-claim1
spec:
spec:
accessModes:
- ReadOnlyMany
resources:
requests:
storage: 1Gi
保存定义的文件,并创建该PVC。
# kubectl create -f static-ceph-pvc.yaml
persistentvolumeclaim "ceph-claim" created
检查PVC是否创建成功,并查看PVC的状态,如果PVC的状态为Bound则表示已经绑定到PV了。这里详细的说下,在kubernetes中一个指定访问模式和存储大小的PVC只能绑定到指定访问权限和存储大小的PV上,但是这样需要集群管理员手动的创建PV。这样就很麻烦,为了减少管理员的工作。管理员可以创建一个storageclass的资源,当指定规格的PVC请求的时候,StorageClass会动态的给该PVC提供一个PV。 我们查看下该PVC是否被该StorageClass绑定一个符合需求的PV上。我们执行下面的命令:
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
ceph-claim Bound ceph-static-pv 2Gi RWO 44m
ceph-claim1 Bound pvc-0f02394a-204e-4995-b22c-3f21ee4d124f 1Gi ROX dynamic 9s
我们看到 ceph-claim1 这个PVC已经绑定到了 pvc-c32aca7e-38cd-11e8-af69-f0921c10a7bc 这个PV,而该PV是由名为 dynamic 的storageclass动态创建的。
创建Pod
我们定义一个Pod来将刚刚创建的PVC挂载到该Pod的容器中去。我们定义的Pod的文件内容如下:
vim static-ceph-pod2
apiVersion: v1
kind: Pod
metadata:
name: static-ceph-pod2
spec:
containers:
- name: ceph-busybox
image: busybox
command: ["sleep", "60000"]
volumeMounts:
- name: ceph-vol1
mountPath: /usr/share/busybox
readOnly: false
volumes:
- name: ceph-vol1
persistentVolumeClaim:
claimName: ceph-claim1
保存定义Pod的文件,我们创建一个Pod:
kubectl create -f static-ceph-pod2
# kubectl get pod static-ceph-pod2
NAME READY STATUS RESTARTS AGE
static-ceph-pod2 1/1 Running 0 40s
ok, 已经成功的将该PVC挂载到了Pod中的容器中。