带有Ceph RBD的Kubernetes的持久存储

时间:2020-02-23 14:40:14  来源:igfitidea点击:

如何使用Ceph RBD进行Kubernetes动态持久卷供应?
Kubernetes(K8S)是一种用于自动化部署,扩展和管理Docker应用程序的开源系统。
在Kubernetes中部署有状态应用程序时的关键要求之一是数据持久性。
在本教程中,我们将查看如何在kubernetes上创建存储类,这些存储类使用RBD(Ceph块设备)从外部Ceph群集提供持久卷。

Ceph块设备是瘦的,可调整大小的,并在Ceph集群中划分的多个OSD中的数据。
Ceph阻止设备利用RadoS功能,例如快照,复制和一致性。
Ceph的Rados块设备(RBD)使用内核模块或者Librbd库与OSD交互。

在开始此练习之前,我们应该有一个工作的外部Ceph集群。
使用Ceph的大多数Kubernetes部署将涉及使用车。
本教程假定我们拥有一个部署的Ceph Ansible,Ceph部署或者手动部署的Ceph存储群集。

第1步:在Kubernetes上部署Ceph Profisioner

登录Kubernetes群集,并创建一个列表文件,用于部署RBD Provisioner,这是Kubernetes 1.5+的无树动态配置文件。

$vim ceph-rbd-provisioner.yml

将以下内容添加到文件中。
注意我们的部署使用RBAC,因此我们将在创建服务帐户和部署Ceph RBD Provisioner之前创建群集角色和绑定。

--
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: rbd-provisioner
  namespace: kube-system
rules:
  - apiGroups: [""]
    resources: ["persistentvolumes"]
    verbs: ["get", "list", "watch", "create", "delete"]
  - apiGroups: [""]
    resources: ["persistentvolumeclaims"]
    verbs: ["get", "list", "watch", "update"]
  - apiGroups: ["storage.k8s.io"]
    resources: ["storageclasses"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["events"]
    verbs: ["create", "update", "patch"]
  - apiGroups: [""]
    resources: ["services"]
    resourceNames: ["kube-dns","coredns"]
    verbs: ["list", "get"]
  - apiGroups: [""]
    resources: ["endpoints"]
    verbs: ["get", "list", "watch", "create", "update", "patch"]
--
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: rbd-provisioner
  namespace: kube-system
subjects:
  - kind: ServiceAccount
    name: rbd-provisioner
    namespace: kube-system
roleRef:
  kind: ClusterRole
  name: rbd-provisioner
  apiGroup: rbac.authorization.k8s.io
--
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: rbd-provisioner
  namespace: kube-system
rules:
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get"]
- apiGroups: [""]
  resources: ["endpoints"]
  verbs: ["get", "list", "watch", "create", "update", "patch"]
--
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: rbd-provisioner
  namespace: kube-system
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: rbd-provisioner
subjects:
- kind: ServiceAccount
  name: rbd-provisioner
  namespace: kube-system
--
apiVersion: apps/v1
kind: Deployment
metadata:
  name: rbd-provisioner
  namespace: kube-system
spec:
  replicas: 1
  selector:
    matchLabels:
      app: rbd-provisioner
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: rbd-provisioner
    spec:
      containers:
      - name: rbd-provisioner
        image: "quay.io/external_storage/rbd-provisioner:latest"
        env:
        - name: PROVISIONER_NAME
          value: ceph.com/rbd
      serviceAccount: rbd-provisioner

应用文件以创建资源。

$kubectl apply -f ceph-rbd-provisioner.yml
clusterrole.rbac.authorization.k8s.io/rbd-provisioner created
clusterrolebinding.rbac.authorization.k8s.io/rbd-provisioner created
role.rbac.authorization.k8s.io/rbd-provisioner created
rolebinding.rbac.authorization.k8s.io/rbd-provisioner created
deployment.apps/rbd-provisioner created

确认RBD卷配置器POD正在运行。

$kubectl get pods -l app=rbd-provisioner -n kube-system
NAME                               READY   STATUS    RESTARTS   AGE
rbd-provisioner-75b85f85bd-p9b8c   1/1     Running   0          3m45s

第2步:获取Ceph Admin密钥并在Kubernetes上创建秘密

登录Ceph群集并获取rbd配置程序使用的管理员密钥。

$sudo ceph auth get-key client.admin

保存由上面的命令打印出来的管理员用户键的值。
我们将在Kubernetes中添加密钥作为秘密。

$kubectl create secret generic ceph-admin-secret \
    --type="kubernetes.io/rbd" \
    --from-literal=key='<key-value>' \
    --namespace=kube-system

其中<key-value>是ceph admin键。
我们可以使用以下命令确认创建。

$kubectl get secrets ceph-admin-secret -n kube-system 
NAME                TYPE                DATA   AGE
ceph-admin-secret   kubernetes.io/rbd   1      5m

第3步:为Kubernetes和客户端键创建Ceph池

接下来是为Kubernetes创建一个新的Cepho池。

$sudo ceph ceph osd pool create <pool-name> <pg-number>
# Example
$sudo ceph ceph osd pool create k8s 100

有关更多详细信息,请选中我们的教程:在Ceph存储群集中创建一个池

然后创建一个新的客户端密钥,可以访问创建的池。

$sudo ceph auth add client.kube mon 'allow r' osd 'allow rwx pool=<pool-name>'
# Example
$sudo ceph auth add client.kube mon 'allow r' osd 'allow rwx pool=k8s'

其中k8s是ceph中创建的池的名称。

然后,我们可以将池与应用程序关联并初始化。

sudo ceph osd pool application enable <pool-name> rbd
sudo rbd pool init <pool-name>

获取ceph上的客户端密钥。

$sudo ceph auth get-key client.kube

在Kubernetes上创建客户机密

kubectl create secret generic ceph-k8s-secret \
  --type="kubernetes.io/rbd" \
  --from-literal=key='<key-value>' \
  --namespace=kube-system

其中<key-value>是Ceph客户端密钥。

第4步:创建RBD存储类

StorageClass提供了一种方法来描述我们在Kubernetes中提供的"类别"的存储空间。
我们将创建一个名为Ceph-RBD的StorageClass。

$vim ceph-rbd-sc.yml

要添加到文件中的内容:

--
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: ceph-rbd
provisioner: ceph.com/rbd
parameters:
  monitors: 10.10.10.11:6789, 10.10.10.12:6789, 10.10.10.13:6789
  pool: k8s-uat
  adminId: admin
  adminSecretNamespace: kube-system
  adminSecretName: ceph-admin-secret
  userId: kube
  userSecretNamespace: kube-system
  userSecretName: ceph-k8s-secret
  imageFormat: "2"
  imageFeatures: layering

其中:Ceph-RBD是要创建的StorageClass的名称.10.10.10.11,10.10.10.12和10.10.10.13是Ceph监视器的IP地址。
我们可以用命令列出它们:

$sudo ceph -s
  cluster:
    id:     7795990b-7c8c-43f4-b648-d284ef2a0aba
    health: HEALTH_OK
 
  services:
    mon: 3 daemons, quorum cephmon01,cephmon02,cephmon03 (age 32h)
    mgr: cephmon01(active, since 30h), standbys: cephmon02
    mds: cephfs:1 {0=cephmon01=up:active} 1 up:standby
    osd: 9 osds: 9 up (since 32h), 9 in (since 32h)
    rgw: 3 daemons active (cephmon01, cephmon02, cephmon03)
 
  data:
    pools:   8 pools, 618 pgs
    objects: 250 objects, 76 KiB
    usage:   9.6 GiB used, 2.6 TiB/2.6 TiB avail
    pgs:     618 active+clean

在使用正确的Ceph监视器的正确值修改文件后,应用配置:

$kubectl apply -f ceph-rbd-sc.yml
storageclass.storage.k8s.io/ceph-rbd created

列表可用StorageClasses:

kubectl get sc
NAME       PROVISIONER       RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
ceph-rbd   ceph.com/rbd      Delete          Immediate           false                  17s
cephfs     ceph.com/cephfs   Delete          Immediate           false                  18d

第5步:在Kubernetes上创建测试索赔和POD

要确认一切正常工作,让我们创建一个测试持久卷索赔。

$vim ceph-rbd-claim.yml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: ceph-rbd-claim1
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: ceph-rbd
  resources:
    requests:
      storage: 1Gi

应用列表文件以创建索赔。

$kubectl apply -f ceph-rbd-claim.yml
persistentvolumeclaim/ceph-rbd-claim1 created

如果它成功绑定,则应显示绑定状态。

$kubectl get pvc
NAME              STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
ceph-rbd-claim1   Bound    pvc-c6f4399d-43cf-4fc1-ba14-cc22f5c85304   1Gi        RWO            ceph-rbd       43s

很好!..我们可以在Ceph RBD后端创建动态持久卷声明。
请注意,我们在索赔之前,我们不必手动创建持久卷。
多么酷啊?
..

然后,我们可以使用我们创建的索赔部署测试Pod。
首先创建一个文件以保存数据:

$vim rbd-test-pod.yaml

添加:

--
kind: Pod
apiVersion: v1
metadata:
  name: rbd-test-pod
spec:
  containers:
  - name: rbd-test-pod
    image: busybox
    command:
      - "/bin/sh"
    args:
      - "-c"
      - "touch /mnt/RBD-SUCCESS && exit 0 || exit 1"
    volumeMounts:
      - name: pvc
        mountPath: "/mnt"
  restartPolicy: "Never"
  volumes:
    - name: pvc
      persistentVolumeClaim:
        claimName: ceph-rbd-claim1

创建Pods:

$kubectl apply -f rbd-test-pod.yaml
pod/rbd-test-pod created

如果我们描述了POD,我们将看到卷的成功附件。

$kubectl describe pod rbd-test-pod
.....
vents:
  Type    Reason                  Age        From                     Message
  ----    ------                  ----       ----                     ------
  Normal  Scheduled               <unknown>  default-scheduler        Successfully assigned default/rbd-test-pod to rke-worker-02
  Normal  SuccessfulAttachVolume  3s         attachdetach-controller  AttachVolume.Attach succeeded for volume "pvc-c6f4399d-43cf-4fc1-ba14-cc22f5c85304"