kubernetes 之持久化存储ceph(2)

一、创建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中的容器中。

发表评论

电子邮件地址不会被公开。 必填项已用*标注