在验证了ROOK Ceph的块存储后,撰写了此备忘录

ROOK是Kubernetes的存儲協調器。它負責分散存儲的系統管理、自動伸縮和自動修復。通過使用運營商,可以詳細了解它自動化存儲管理者的任務,包括部署、引導、配置、供應、伸縮、升級、遷移、災難恢復、監視和資源管理。

(Note: The provided translation is in Simplified Chinese)

ROOK 是一個提供多個儲存供應商的儲存編排器,並提供橫跨共同框架。它可以選擇所需的儲存供應商並在 Kubernetes 上以相同方式操作。儲存供應商有以下種類。

    • Ceph

 

    • EdgeFS

 

    • CockroachDB

 

    • Cassandra

 

    • NFS

 

    Yugabyte DB

这个ROOK在本地环境中最有效的利用方式被认为是在Kubernetes集群中。也就是说,在云上的Kubernetes服务中,通过Kubernetes上的Persistent Volume Claim(PVC)的API,与云存储服务配合,为Pod提供持久卷。因此,在云环境中无需体验ROOK的便利性。然而,在本地环境中,由于可以在Kubernetes集群环境中构建存储服务,因此可以以低成本、短时间实现与云环境类似的存储服务使用。

这篇文章是关于在Vagrant上使用Kubernetes 1.17.2对ROOK Ceph的块存储进行验证的记录。ROOK Ceph是一种可与Kubernetes控制器协同工作并能够进行动态供应的软件定义存储系统(SDS)。过去,在部署Kubernetes集群时,通常会依赖外部存储设备,但通过使用ROOK Ceph,可以利用工作节点的本地磁盘来创建存储集群。这样做可以降低硬件基础设施成本。此外,预计通过运维自动化,操作员可以像使用云存储服务一样使用它。

然而,并不仅仅有好的一面。相反地,有一些挑战,比如被Kubernetes版本升级所影响等,因此在引入时需要采取谨慎的态度。

准备ROOK执行环境

我们将对我们之前使用的学习用Kubernetes进行以下改造,以使ROOK可以运行。由于它需要大量资源,所以在一般PC的规格下运行变得困难了。

Vagrantfileの編集

メモリとCPUの追加
ストレージサイズの変更
node2をコピーしてnode3を作成 マスターx1,ワーカーx3 へ

ansible-playbook の hostsファイルの編集

hosts へ node3 を追加、証明書パスの変更
nodesの変数範囲の追加
KubernetesノードのOSをUbuntu18.04へ変更

启动虚拟服务器

为了启动多个节点并添加虚拟机的内部磁盘,需先安装以下Vagrant插件。

vagrant plugin install vagrant-cachier
vagrant plugin install vagrant-disksize

在Vagrant上克隆启动Kubernetes的代码。在1.17-3node分支上,添加了一个增加了内存和核心数量的版本,采用了3节点结构。

git clone -b 1.17-3node https://github.com/takara9/vagrant-kubernetes k8s
cd k8s

用以下的命令启动虚拟服务器。

vagrant up

确认启动

export KUBECONFIG=`pwd`/kubeconfig/config
kubectl get node
NAME     STATUS   ROLES    AGE    VERSION
master   Ready    master   2m5s   v1.17.2
node1    Ready    <none>   92s    v1.17.2
node2    Ready    <none>   93s    v1.17.2
node3    Ready    <none>   93s    v1.17.2

创建外部访问节点

实际上是不正确的,但可以将主节点变成NodePort中继节点以便从外部访问。
通过将主节点分配给主机侧的LAN IP地址和NodePort端口号,可以从K8s集群外部访问。

停止主节点,设定IP地址,然后重新启动。

vagrant halt master

编辑Vagrantfile文件,在计算机连接的局域网侧设置IP地址。

vi Vagrantfile 

由于第154行被注释掉了,所以请去掉“#”使其成为有效的行。

    153     machine.vm.network :private_network,ip: "172.16.20.11"
    154     machine.vm.network :public_network, ip: "192.168.1.91", bridge: "en0: Ethernet"

再次启动主节点。在启动过程中可能会要求选择接口,因此在这里选择有线局域网接口。

vagrant up master
Bringing machine 'master' up with 'virtualbox' provider...
==> master: Checking if box 'ubuntu/xenial64' version '20200121.0.0' is up to date...
==> master: Clearing any previously set forwarded ports...
==> master: Fixed port collision for 22 => 2222. Now on port 2202.
==> master: Clearing any previously set network interfaces...
==> master: Specific bridge 'en0: Ethernet' not found. You may be asked to specify
==> master: which network to bridge to.
==> master: Available bridged network interfaces:
1) enp4s0
2) wlp3s0
3) docker0
==> master: When choosing an interface, it is usually the one that is
==> master: being used to connect to the internet.
    master: Which interface should the network bridge to? 1
==> master: Preparing network interfaces based on configuration...
    master: Adapter 1: nat
    master: Adapter 2: hostonly

Rook Ceph 的部署

按照参考URL(https://rook.io/docs/rook/v1.2/ceph-quickstart.html)的指南,安装ROOK和Ceph,从而能够使用块、文件和对象这三种类型的存储。

git clone --single-branch --branch release-1.2 https://github.com/rook/rook.git 
cd rook/cluster/examples/kubernetes/ceph
kubectl create -f common.yaml
kubectl create -f operator.yaml

在上述中,直到ROOK的Ceph操作员启动为止。作为启动确认,只需以下四个Pod启动完成即可。

kubectl get po -n rook-ceph 
NAME                                  READY   STATUS    RESTARTS   AGE
rook-ceph-operator-6d74795f75-lhf65   1/1     Running   0          5m37s
rook-discover-949bg                   1/1     Running   0          4m42s
rook-discover-m5sz7                   1/1     Running   0          4m42s
rook-discover-zrdhd                   1/1     Running   0          4m42s

在这种情况下,如果使用工作节点的操作系统存储,会因为受到Ceph的压力导致容器的文件系统空间不足,从而影响工作节点的正常运行。因此,需要向工作节点添加虚拟磁盘,并从Ceph中使用它。

以下是使用Ceph的CRD启动Ceph的清单文件。在其中,要将Ceph数据挂载到工作节点的路径/var/lib/rook,可以通过dataDirHostPath: /var/lib/rook进行配置。下面的cluster.yaml是经过编辑并除去注释的,以便清晰明了地表达要点。

apiVersion: ceph.rook.io/v1
kind: CephCluster
metadata:
  name: rook-ceph
  namespace: rook-ceph
spec:
  cephVersion:
    image: ceph/ceph:v14.2.6
    allowUnsupported: false
  dataDirHostPath: /var/lib/rook  # <--- データディレクトリ
  skipUpgradeChecks: false
  continueUpgradeAfterChecksEvenIfNotHealthy: false
  mon:
    count: 3
    allowMultiplePerNode: false  # モニターはノードに一つ
  dashboard:
    enabled: true
    ssl: true
  monitoring:
    enabled: false
    rulesNamespace: rook-ceph
  network:
    hostNetwork: false # ポッドネットワークを使用、パフォーマンスを求める時は再考
  rbdMirroring:
    workers: 0
  crashCollector:
    disable: false
  annotations:
  resources:
    mgr:
      limits:
        cpu: "500m"
        memory: "1024Mi"
      requests:
        cpu: "500m"
        memory: "1024Mi"
  removeOSDsIfOutAndSafeToRemove: false
  storage:
    useAllNodes: true
    useAllDevices: true
    config:
      databaseSizeMB: "1024" # uncomment if the disks are smaller than 100 GB
      journalSizeMB: "1024"  # uncomment if the disks are 20 GB or smaller
      osdsPerDevice: "1" # this value can be overridden at the node or device level
    directories:
    - path: /ceph_data
  disruptionManagement:
    managePodBudgets: false
    osdMaintenanceTimeout: 30
    manageMachineDisruptionBudgets: false
    machineDisruptionBudgetNamespace: openshift-machine-api

建立Worker节点时,需要从Ansible中挂载额外的虚拟磁盘到Worker节点。下面的文件node_storage.yml是用于挂载的playbook的一部分。

- hosts: nodes
  become: yes
  gather_facts: True

  tasks:
    - name: include k8s version
      include_vars: /vagrant/ansible-playbook/versions.yml

    - name: mkfs /dev/sdc
      filesystem:
        fstype: ext4
        dev: /dev/sdc

    - name: Creates directory
      file:
        path: /ceph_data
        state: directory
        owner: root
        group: root
        mode: 0775

    - name: mount /ceph_data
      mount:
        path: /ceph_data
        src: /dev/sdc
        fstype: ext4
        state: mounted

使用之前编辑过的cluster.yaml文件应用配置,启动Ceph。

kubectl create -f cluster.yaml

由于启动需要几分钟时间,建议加上“-w”选项以观察进展情况。最终将进入以下状态。

kubectl get po -n rook-ceph 
NAME                                              READY   STATUS      RESTARTS   AGE
csi-cephfsplugin-9vzmd                            3/3     Running     0          9m3s
csi-cephfsplugin-bzjmk                            3/3     Running     0          9m3s
csi-cephfsplugin-provisioner-565ffd64f5-gjbhc     4/4     Running     0          9m3s
csi-cephfsplugin-provisioner-565ffd64f5-tj7h7     4/4     Running     0          9m3s
csi-cephfsplugin-pv5s9                            3/3     Running     0          9m3s
csi-rbdplugin-cws6k                               3/3     Running     0          9m3s
csi-rbdplugin-jpgjb                               3/3     Running     0          9m3s
csi-rbdplugin-p6zxd                               3/3     Running     0          9m3s
csi-rbdplugin-provisioner-7bb78d6c66-p49kw        5/5     Running     0          9m3s
csi-rbdplugin-provisioner-7bb78d6c66-r687q        5/5     Running     0          9m3s
rook-ceph-crashcollector-node1-7bbb758b85-lxnmj   1/1     Running     0          5m46s
rook-ceph-crashcollector-node2-6c58bddcdd-hc7ck   1/1     Running     0          5m28s
rook-ceph-crashcollector-node3-7c8c9dd5bc-9c5h8   1/1     Running     0          4m44s
rook-ceph-mgr-a-98554f488-8zjft                   1/1     Running     0          5m8s
rook-ceph-mon-a-59c478755b-8tk8d                  1/1     Running     0          5m54s
rook-ceph-mon-b-5d9d488947-4r5xh                  1/1     Running     0          5m46s
rook-ceph-mon-c-6bfd478cc5-hkhx2                  1/1     Running     0          5m28s
rook-ceph-operator-6d74795f75-95nnv               1/1     Running     0          23m
rook-ceph-osd-0-644d5c77d7-mqfwd                  1/1     Running     0          4m45s
rook-ceph-osd-1-54964546d4-xfwwh                  1/1     Running     0          4m44s
rook-ceph-osd-2-78b5c5f8b-nss7l                   1/1     Running     0          4m44s
rook-ceph-osd-prepare-node1-jtk75                 0/1     Completed   0          4m49s
rook-ceph-osd-prepare-node2-c5r2n                 0/1     Completed   0          4m49s
rook-ceph-osd-prepare-node3-jzl2w                 0/1     Completed   0          4m49s
rook-discover-dqm9l                               1/1     Running     0          23m
rook-discover-hvgcf                               1/1     Running     0          23m
rook-discover-mvd7s                               1/1     Running     0          23m

使用工具箱进行测试

当您使用位于同一目录rook/cluster/examples/kubernetes/ceph下的toolbox.yaml时,您可以执行ceph命令。

kubectl create -f toolbox.yaml
deployment.apps/rook-ceph-tools created

kubectl -n rook-ceph get pod -l "app=rook-ceph-tools"
NAME                               READY   STATUS    RESTARTS   AGE
rook-ceph-tools-78b599b6dd-47vdt   1/1     Running   0          11s

将终端连接到pod上,并以交互方式运行ceph命令。

kubectl -n rook-ceph exec -it $(kubectl -n rook-ceph get pod -l "app=rook-ceph-tools" -o jsonpath='{.items[0].metadata.name}') bash

[root@rook-ceph-tools-78b599b6dd-47vdt /]# ceph status
  cluster:
    id:     40b602cc-b666-458f-b3a5-25287d48d6d4
    health: HEALTH_OK

  services:
    mon: 1 daemons, quorum a (age 25m)
    mgr: a(active, since 25m)
    osd: 3 osds: 3 up (since 24m), 3 in (since 24m)

  data:
    pools:   0 pools, 0 pgs
    objects: 0 objects, 0 B
    usage:   17 GiB used, 129 GiB / 145 GiB avail
    pgs:     

[root@rook-ceph-tools-78b599b6dd-47vdt /]# ceph osd status
+----+-------+-------+-------+--------+---------+--------+---------+-----------+
| id |  host |  used | avail | wr ops | wr data | rd ops | rd data |   state   |
+----+-------+-------+-------+--------+---------+--------+---------+-----------+
| 0  | node2 | 5718M | 42.8G |    0   |     0   |    0   |     0   | exists,up |
| 1  | node1 | 5684M | 42.8G |    0   |     0   |    0   |     0   | exists,up |
| 2  | node3 | 5684M | 42.8G |    0   |     0   |    0   |     0   | exists,up |
+----+-------+-------+-------+--------+---------+--------+---------+-----------+

[root@rook-ceph-tools-78b599b6dd-47vdt /]# ceph df
RAW STORAGE:
    CLASS     SIZE        AVAIL       USED       RAW USED     %RAW USED 
    hdd       145 GiB     129 GiB     17 GiB       17 GiB         11.49 
    TOTAL     145 GiB     129 GiB     17 GiB       17 GiB         11.49 

POOLS:
    POOL     ID     STORED     OBJECTS     USED     %USED     MAX AVAIL 

[root@rook-ceph-tools-78b599b6dd-47vdt /]# rados df
POOL_NAME USED OBJECTS CLONES COPIES MISSING_ON_PRIMARY UNFOUND DEGRADED RD_OPS RD WR_OPS WR USED COMPR UNDER COMPR 

total_objects    0
total_used       17 GiB
total_avail      129 GiB
total_space      145 GiB

Ceph的调整

如果虚拟机的操作系统是Ubuntu 16.04,为了避免由于内核问题而出现挂起,需要修改参数。然而,如果使用Ubuntu 18.04,则不需要进行这种调整。由于本文使用的是分支1.17-3node,它使用的是Ubuntu 18.04,所以不需要进行以下调整。

查看默认的可调参数。在Jewel中存在无法获得块存储的问题,需要进行以下更改。

[root@rook-ceph-tools-78b599b6dd-8srn5 /]# ceph osd crush show-tunables 
{
    "choose_local_tries": 0,
    "choose_local_fallback_tries": 0,
    "choose_total_tries": 50,
    "chooseleaf_descend_once": 1,
    "chooseleaf_vary_r": 1,
    "chooseleaf_stable": 1,
    "straw_calc_version": 1,
    "allowed_bucket_algs": 54,
    "profile": "jewel",   <<--- 設定のプロファイルが jewel になっている
    "optimal_tunables": 1,
    "legacy_tunables": 0,
    "minimum_required_version": "jewel", 
    "require_feature_tunables": 1,
    "require_feature_tunables2": 1,
    "has_v2_rules": 0,
    "require_feature_tunables3": 1,
    "has_v3_rules": 0,
    "has_v4_buckets": 1,
    "require_feature_tunables5": 1,
    "has_v5_rules": 0
}

请将设置更改为”hammer”。

[root@rook-ceph-tools-78b599b6dd-8srn5 /]# ceph osd crush tunables hammer
adjusted tunables profile to hammer

确认更改。

[root@rook-ceph-tools-78b599b6dd-8srn5 /]# ceph osd crush show-tunables 
<中略>
    "profile": "hammer",
<以下省略>

现在,Ceph集群的设置已经完成,接下来进入客户端端进行配置。

设置存储类型

设置存储类别以执行动态配置。

cd csi/rbd
kubectl apply -f storageclass.yaml 
cephblockpool.ceph.rook.io/replicapool created
storageclass.storage.k8s.io/rook-ceph-block created

确认已设置的内容。

kubectl get sc
NAME              PROVISIONER                  RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
rook-ceph-block   rook-ceph.rbd.csi.ceph.com   Delete          Immediate           false                  35s

现在,我们已经可以动态地为块存储进行配置了。

验证WordPress启动的操作

接下来,我们将进行动态配置功能的测试。测试中我们将启动WordPress,并确保内容和数据库的两个永久数据区域由ROOK Ceph进行分配。

前往包含样例清单的目录。

$ cd ../../..

部署数据库。

kubectl apply -f mysql.yaml 

部署应用程序服务器。

kubectl apply -f wordpress.yaml 

这样一来,将会产生两个PVC。

kubectl get pvc
NAME             STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS      AGE
mysql-pv-claim   Bound    pvc-4af72998-cfcf-46a7-9fe4-624e34db85cd   20Gi       RWO            rook-ceph-block   11s
wp-pv-claim      Bound    pvc-2c7a1991-00dd-4309-9883-c9c69eb0e7db   20Gi       RWO            rook-ceph-block   5s

持久性存储申请中的容量要求

请在这里确认一下清单。在PVC的清单中,由于是块存储,accessModes被设置为不允许共享的ReadWriteOnce。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: wp-pv-claim
  labels:
    app: wordpress
spec:
  storageClassName: rook-ceph-block
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 2Gi

可以将块存储装载到文件系统中,也就是说,可能是由供应商动态地创建文件系统。

        volumeMounts:
        - name: wordpress-persistent-storage
          mountPath: /var/www/html
      volumes:
      - name: wordpress-persistent-storage
        persistentVolumeClaim:
          claimName: wp-pv-claim

故障排除

解释一下在没有执行前述的ceph osd crush tunables hammer命令的情况下可能会遇到的问题。

如果Pod在’ContainerCreating’状态下无法进行下一步,则可能是由于Ceph引起的。

kubectl get po
NAME                              READY   STATUS              RESTARTS   AGE
wordpress-5b886cf59b-6mdnv        0/1     ContainerCreating   0          2m44s
wordpress-mysql-b9ddd6d4c-s7dfc   0/1     ContainerCreating   0          2m50s

在这种情况下,通过显示Pod的详细信息并确认Events,可以判断出停滞的原因。可以看出无法挂载卷和发生超时错误。换句话说,可以推测出Ceph或ROOK存在问题。

kubectl describe po wordpress-mysql-b9ddd6d4c-s7dfc

<中略>

Events:
  Type     Reason                  Age                  From                     Message
  ----     ------                  ----                 ----                     -------
  Warning  FailedScheduling        3m9s (x2 over 3m9s)  default-scheduler        error while running "VolumeBinding" filter plugin for pod "wordpress-mysql-b9ddd6d4c-s7dfc": pod has unbound immediate PersistentVolumeClaims
  Normal   Scheduled               3m8s                 default-scheduler        Successfully assigned default/wordpress-mysql-b9ddd6d4c-s7dfc to node1
  Normal   SuccessfulAttachVolume  3m8s                 attachdetach-controller  AttachVolume.Attach succeeded for volume "pvc-4af72998-cfcf-46a7-9fe4-624e34db85cd"
  Warning  FailedMount             65s                  kubelet, node1           Unable to attach or mount volumes: unmounted volumes=[mysql-persistent-storage], unattached volumes=[mysql-persistent-storage default-token-8qr52]: timed out waiting for the condition
  Warning  FailedMount             58s (x2 over 119s)   kubelet, node1           MountVolume.MountDevice failed for volume "pvc-4af72998-cfcf-46a7-9fe4-624e34db85cd" : rpc error: code = Internal desc = rbd: map failed exit status 110, rbd output: rbd: sysfs write failed
In some cases useful info is found in syslog - try "dmesg | tail".
rbd: map failed: (110) Connection timed out

根据https://github.com/ceph/ceph-helm/issues/60,这种情况的原因如下。

重要的Kubernetes使用RBD内核模块将RBD映射到主机。Luminous要求CRUSH_TUNABLES 5(Jewel)。这些可调参数的最低内核版本是4.5。如果您的内核不支持这些可调参数,请运行ceph osd crush tunables hammer。

当通过检查使用Ubuntu 16.04的工作节点的内核版本时,我们发现它是4.4。因此,由于它与上述有关,因此需要进行更改。

vagrant@node1:~$ uname -a
Linux node1 4.4.0-171-generic #200-Ubuntu SMP Tue Dec 3 11:04:55 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

由于使用了Ubuntu 18.04内核,因此不需要进行适配,具体内核如下所示。

vagrant ssh node3
Welcome to Ubuntu 18.04.4 LTS (GNU/Linux 4.15.0-76-generic x86_64)

ROOK Ceph 仪表板

修改设置以从浏览器中访问Ceph仪表盘。

在初始设置中,服务类型被设定为ClusterIP,这将导致无法从集群外部进行访问。

kubectl -n rook-ceph get service rook-ceph-mgr-dashboard 
NAME                       TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)             AGE
rook-ceph-mgr-dashboard    ClusterIP   10.32.0.200   <none>        8443:31930/TCP      5h49m

使用 edit 子命令,在运行中的清单上进行更改,使其可以从 Kubernetes 集群外部进行访问。

kubectl -n rook-ceph edit service rook-ceph-mgr-dashboard

下面是上述命令的执行结果。将第35行的type: ClusterIP更改为type: NodePort。

     23 spec:
     24   clusterIP: 10.32.0.252
     25   ports:
     26   - name: https-dashboard
     27     port: 8443
     28     protocol: TCP
     29     targetPort: 8443
     30     nodePort: 30443
     31   selector:
     32     app: rook-ceph-mgr
     33     rook_cluster: rook-ceph
     34   sessionAffinity: None
     35   type: ClusterIP

通过上述更改,节点端口将被打开,可以访问Ceph的仪表板。通过在清单文件的”ports:”处加入”nodePort: 30443″的配置,如果端口开放,可以保持仪表板地址的稳定。

kubectl get svc -n rook-ceph rook-ceph-mgr-dashboard
NAME                      TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)          AGE
rook-ceph-mgr-dashboard   NodePort   10.32.0.252   <none>        8443:30443/TCP   17h

要访问Ceph仪表板,需要提供密码。可以通过执行以下命令获得该密码。

kubectl -n rook-ceph get secret rook-ceph-dashboard-password -o jsonpath="{['data']['password']}" | base64 --decode && echo
xZVbe1aVOL

将此端口号添加到添加到主节点虚拟机主机的IP地址上,通过 https://192.168.1.91:30443 并使用用户ID admin 可以访问。

Ceph-Dashbd.png

总结

ROOK可以使用Kubernetes集群中的工作节点内置磁盘构建SDS。通过将持久化数据存储在工作节点上,通过集群化实现分布和冗余来确保数据的可靠性,尽管如此,人们仍然有一些抵触情绪。越简单的东西越不容易损坏,因此保存重要数据的设备最好是满足需求的简单设备。通过这种方式,可以保护重要数据免受软件的复杂协作、脆弱性和版本升级等带来的挑战。

然而,如果要构建SDS集群,除了Kubernetes集群之外,就需要相应的成本。但是,如果能够使用ROOK在同一个Kubernetes集群中持久保存数据,就可以减少工作和成本。而且,还想验证一下是否可以获取快照并将其保存到远程对象存储中。

这次我们发现,ROOK Ceph的设置非常简单且可以快速进行。然而,这并不意味着不需要了解Ceph知识。可以说在使用ROOK之前,应该了解Ceph。而且,要使用最新版本的Ceph,工作节点的Linux内核版本必须为4.5以上。如果无法满足该条件,则需要降低配置级别。

Rook在OpenShift中被作为OpenShift容器存储(OCS)提供,从OpenShift 4.3版本开始可使用。若在本地环境使用OpenShift,Rook应被视为一个不可或缺的组件。

广告
将在 10 秒后关闭
bannerAds