Rook-Cephfs + Nvidia Driver vs てんぜん

はじめに

RookだらけのAdvent Calenderに一通り目を通して面白そうだと思い やってみました.

qiita.com

Advent Calernderで寄稿されている記事の数々は全て非常に有益であり,大変わかりやすかったのですが私自身完全に沼にハマってしまい(特にLinux Kernelの部分やNvidia Driver関連の部分)動かすまでにだいぶ苦労しましたので,他の方が同じ道をたどらないように備忘録を残しておきます.

また,以前ブログで書いたこの環境にRook環境を準備していくので,kubernetes環境構築がまだの方は先に構築してきてください.

tenzen.hatenablog.com

Rookとは

RookについてはRedHatの方が非常にわかりやすく解説してされているので詳細はそちらの方もしくは公式ページを読んでいただけば良いのですが,ここでも軽くまとめておきます.

rheb.hatenablog.com

rook.io

RookとはCNCFのincubatingなプロジェクトのうちの一つです. kubernetesでは外部ストレージをPersistent Volumeとしてコンテナにマウントすることができますが,Rookはストレージもクラウドネイティブな運用をしようというものです.RookはCephやEdgefsなどの分散ストレージのシステムをkubernetes上で管理してくれます.もちろんクラウドネイティブを唱っているのでオートヒーリングなども行ってくれます. 今回は分散ストレージにCephfsを選びました.Cephfsについては気が向いたら別記事にまとめます.

準備

実装と言いましてもRookはOperatorでインストール可能なので公式リポトジから取ってきてkubectl applyしていくだけです.

公式リポジトリから取ってきてkubectl applyしていくだけなのですが,一つ最重要事項があります.今回MasterもWorkerもOSにはUbuntu 16.04LTSを使用していくのですが,kernel image 4.4.0では動きませんでした.正確に述べると,Rookは起動し,Cephも起動し,PoolもPVもPVCもエラーなく正常に起動できるのですが,Podにマウントすることができません.そのためubuntu16.04LTSのKernel Imageの変更から行っていきます.

Kernel Imageの変更

まず現在のKernel Imageを調べておきます.

$ sudo uname -a
Linux tenzen 4.4.0-170-generic #199-Ubuntu SMP Thu Nov 14 01:45:04 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

このようにKernelバージョンが4.4.0だとRook-Cephfsを正常に使用することができないので新しいKernel Imageをインストールしていきます.まず,現在使用できるKernel Imageを探してきます.

$ sudo apt-cache search linux-image | grep image-4 | grep generic
(省略)
linux-image-4.15.0-55-generic - Signed kernel image generic
linux-image-4.15.0-58-generic - Signed kernel image generic
linux-image-4.15.0-60-generic - Signed kernel image generic
linux-image-4.15.0-62-generic - Signed kernel image generic
linux-image-4.15.0-64-generic - Signed kernel image generic
linux-image-4.15.0-65-generic - Signed kernel image generic
linux-image-4.15.0-66-generic - Signed kernel image generic
linux-image-4.15.0-69-generic - Signed kernel image generic
linux-image-4.15.0-70-generic - Signed kernel image generic
linux-image-4.15.0-72-generic - Signed kernel image generic
linux-image-4.15.0-74-generic - Signed kernel image generic
linux-image-4.4.0-101-generic - Linux kernel image for version 4.4.0 on 64 bit x86 SMP
linux-image-4.4.0-103-generic - Linux kernel image for version 4.4.0 on 64 bit x86 SMP
...(省略)

今回は最新の一つ前のlinux-image-4.15.0-72-genericを使用していきます.

$ sudo apt-get install -y linux-image-4.15.0-72-generic
$ reboot

再起動すると一番新しいKernel Imageを選択するようになっているので切り替わっていると思います.

$ sudo uname -a
Linux k8s-m 4.15.0-72-generic #81~16.04.1-Ubuntu SMP Tue Nov 26 16:34:21 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

Nvidia Driverの更新

Nvidia DriverはLinux Kernel 依存なのでKernel Imageを変更すると壊れるので直していきます.また,私が試した限りlinux-image-4.15.0-72-genericにおいて記事執筆時点で以前私が以下の記事

tenzen.hatenablog.com

でも行った,apt-get経由によるNvidia Driverの正常なインストールができなくなっています.そのため別の方法でインストールしていきます.

まず,nvidia関連の残骸を消去します.

$ sudo apt-get remove --purge nvidia*
$ sudo apt-get remove --purge cuda*
$ sudo apt-get autoremove

次に,Nvidia DriverのインストーラLinux Headerを見てインストールするものを判断しているため,使用中のLinux Imageに該当するLinux Headerをインストールします.

$ sudo apt-get install -y linux-headers-4.15.0-72-generic
$ reboot

再起動後「/usr/src/」にlinux-headers-4.15.0-72-genericがあることを確認します.これがないとNvidia Driverを正常にインストールすることができませんのでよく確認しておいてください.

$ ls /usr/src
linux-headers-4.15.0-72-generic
...(省略)

Nvidia公式サイトから自分が使用中のGPUなどを選択してインストーラをダウンロードてきます.今回はLinux版で一番新しい440番を使用しました.

www.nvidia.co.jp

ダウンロードできたらダウンロードしてきたファイルの権限を変更後ディスプレイマネージャを切ってCUIモードでログインし直してください.(UbuntuならCtr+Alt+F1)

$ mv /home/tenzen/Downloads/NVIDIA-Linux-x86_64-440.44.run /home/tenzen
$ chmod 777 NVIDIA-Linux-x86_64-440.44.run
$ sudo service lightdm stop

CUIモードでログインできたらドライバをインストールしていきます.インストーラを起動すると青い画面になって色々聞かれるので使用しているホストに合わせて答えていってください.

$ sudo NVIDIA-Linux-x86_64-440.44.run

以上でNvidia Driverの更新が終了しました.

時間調整

サーバ間の時間がズレているとcephに怒られるので時間を合わせます. 今回は外側123/udpを使用できない環境なので,以下の記事を参考にMasterサーバにNTPサーバを建てて,Masterサーバの時間に全てのサーバの時間を合わせます.

qiita.com

まず,必要なパッケージ類をインストールしていきます.

$ sudo apt-get install ntp ntpdate

次にMasterでLocal時間をデフォルトにNTP Serverを建てるために「/etc/ntp.conf」に以下を追記します. xxx.xxx.xxx.xxxはMasterのプライベートIPアドレスを記述してください.

restrict xxx.xxx.xxx.xxx mask 255.255.255.0 nomodify notrap

# 自分のローカルタイムを参照
server  127.127.1.0 prefer
fudge   127.127.1.0 stratum 10

サーバ側の必要なポートを開放します.

$ sudo ufw allow 123/udp
$
$ sudo ufw reload
$
$ sudo systemctl restart ntp

NTPサーバ側の設定が終わったのでクライアントであるWorkerの「/etc/ntp.conf」に以下を記述します. 先ほどと同じくxxx.xxx.xxx.xxxにはサーバ側のプライベートIPアドレスを記述します.

server xxx.xxx.xxx.xxx prefer

ntpの設定を再読込します.

$ sudo systemctl restart ntp

Rook・Cephの設定

今回v1.2を使用するのでGit Cloneしてきます.

$ git clone -b release-1.2 https://github.com/rook/rook.git

ダウンロードしてきたらまず,「/rook/cluster/examples/kubernetes/ceph/operator.yaml」の以下の項目のNodeAffinityを編集してディスク監視Podの配置ノードを絞ります.水色の部分がコメントされていると思うので,コメントアウトします.今回はストレージ専用ホストを準備できなかったのでGPUの刺さっているホストにディスクを刺し,Rookでしようします.そのため前回の記事 Kubernetes(k8s) v1.16とNvidia-Docker2を用いたマルチノードDeepLearning環境の構築 Part2 - てんぜんの生存日誌GPUの刺さっているホストに付けた「hardware-type=NVIDIAGPU」のラベルをを用います.

...(省略)
        # (Optional) Rook Discover priority class name to set on the pod(s)
        # - name: DISCOVER_PRIORITY_CLASS_NAME
        #   value: "<PriorityClassName>"
        # (Optional) Discover Agent NodeAffinity.
+       - name: DISCOVER_AGENT_NODE_AFFINITY
+         value: "hardware-type=NVIDIAGPU"
        # Allow rook to create multiple file systems. Note: This is considered
        # an experimental feature in Ceph as described at
...(省略)

次に,「/rook/cluster/examples/kubernetes/ceph/cluster.yaml」 の以下の青色のコメントされている項目をコメントアウトします.編集しなくても起動しますが,筆者の環境ではディスクの数に対してOSDが十分な数起動してくれず,Cephのステータスが 「HEALTH_WARN」「 too few PGs per OSD」の状態となったため行いました.

github.com

...(省略)
# mgr:
#   modules:
    # Several modules should not need to be included in this list. The "dashboard" and "monitoring" modules
    # are already enabled by other settings in the cluster CR and the "rook" module is always enabled.
#   - name: pg_autoscaler
#     enabled: true
...(省略)

さらに,使用するディスクを指定します.「useAllNodes」・「useAllDevices」はデフォルトでオンになっていると思いますが,今回はディスクを選択して使用するためfalseに以下の水色の部分のように「/rook/cluster/examples/kubernetes/ceph/cluster.yaml」を編集します.

...(省略)
  storage: # cluster level storage configuration and selection
+   useAllNodes: false
+   useAllDevices: false
...(省略)

使用するディスクの名前は事前に調べておき,下記の水色の部分のように「/rook/cluster/examples/kubernetes/ceph/cluster.yaml」を編集します.

...(省略)
      # journalSizeMB: "1024"  # uncomment if the disks are 20 GB or smaller
      # osdsPerDevice: "1" # this value can be overridden at the node or device level
      # encryptedDevice: "true" # the default value for this option is "false"
# Cluster level list of directories to use for filestore-based OSD storage. If uncomment, this example would create an OSD under the dataDirHostPath.
    #directories:
    #- path: /var/lib/rook
# Individual nodes and their config can be specified as well, but 'useAllNodes' above must be set to false. Then, only the named
# nodes below will be used as storage resources.  Each node's 'name' field should match their 'kubernetes.io/hostname' label.
+   nodes:
+   - name: "michiru"
+     devices:
+     - name: "sda"
+     - name: "sdb"
+     - name: "sdc"
+     - name: "sdd"
+     - name: "sde"
+   - name: "eriri"
+     devices:
+     - name: "sda"
+     - name: "sdb"
+     - name: "sdc"
+     - name: "sdd"
+     - name: "sde"
+   - name: "utaha"
+     devices:
+     - name: "sda"
+     - name: "sdb"
+     - name: "sdc"
+      - name: "sdd" 
...(省略)

最後にCeph DashboardのServiceを編集します. サンプルとしてNodePort・Ingress・LoadBalancerが用意されていますが,今回はNodePortを使用しました. 実運用では何回も再起動することは稀ですが,サンプルのままではkubernetes側で開いているポートが自動的に割り当てられて起動するたびにポートが変わってしまうので「dashboard-external-https.yaml」を以下のように青色の部分を追加してポートを固定にします.

apiVersion: v1
kind: Service
metadata:
  name: rook-ceph-mgr-dashboard-external-https
  namespace: rook-ceph
  labels:
    app: rook-ceph-mgr
    rook_cluster: rook-ceph
spec:
  ports:
  - name: dashboard
+   nodePort: 30123
    port: 8443
    protocol: TCP
    targetPort: 8443
  selector:
    app: rook-ceph-mgr
    rook_cluster: rook-ceph
  sessionAffinity: None
  type: NodePort

以上で準備完了です.

デプロイ

順番にkubectl applyしていくだけです.

$ cd rook/cluster/examples/kubernetes/ceph
$ kubectl apply -f common.yaml
namespace/rook-ceph created
customresourcedefinition.apiextensions.k8s.io/cephclusters.ceph.rook.io created
customresourcedefinition.apiextensions.k8s.io/cephclients.ceph.rook.io created
customresourcedefinition.apiextensions.k8s.io/cephfilesystems.ceph.rook.io created
customresourcedefinition.apiextensions.k8s.io/cephnfses.ceph.rook.io created
customresourcedefinition.apiextensions.k8s.io/cephobjectstores.ceph.rook.io created
customresourcedefinition.apiextensions.k8s.io/cephobjectstoreusers.ceph.rook.io created
customresourcedefinition.apiextensions.k8s.io/cephblockpools.ceph.rook.io created
customresourcedefinition.apiextensions.k8s.io/volumes.rook.io created
customresourcedefinition.apiextensions.k8s.io/objectbuckets.objectbucket.io created
customresourcedefinition.apiextensions.k8s.io/objectbucketclaims.objectbucket.io created
clusterrolebinding.rbac.authorization.k8s.io/rook-ceph-object-bucket created
clusterrole.rbac.authorization.k8s.io/rook-ceph-cluster-mgmt created
clusterrole.rbac.authorization.k8s.io/rook-ceph-cluster-mgmt-rules created
role.rbac.authorization.k8s.io/rook-ceph-system created
clusterrole.rbac.authorization.k8s.io/rook-ceph-global created
clusterrole.rbac.authorization.k8s.io/rook-ceph-global-rules created
clusterrole.rbac.authorization.k8s.io/rook-ceph-mgr-cluster created
clusterrole.rbac.authorization.k8s.io/rook-ceph-mgr-cluster-rules created
clusterrole.rbac.authorization.k8s.io/rook-ceph-object-bucket created
serviceaccount/rook-ceph-system created
rolebinding.rbac.authorization.k8s.io/rook-ceph-system created
clusterrolebinding.rbac.authorization.k8s.io/rook-ceph-global created
serviceaccount/rook-ceph-osd created
serviceaccount/rook-ceph-mgr created
serviceaccount/rook-ceph-cmd-reporter created
role.rbac.authorization.k8s.io/rook-ceph-osd created
clusterrole.rbac.authorization.k8s.io/rook-ceph-osd created
clusterrole.rbac.authorization.k8s.io/rook-ceph-mgr-system created
clusterrole.rbac.authorization.k8s.io/rook-ceph-mgr-system-rules created
role.rbac.authorization.k8s.io/rook-ceph-mgr created
role.rbac.authorization.k8s.io/rook-ceph-cmd-reporter created
rolebinding.rbac.authorization.k8s.io/rook-ceph-cluster-mgmt created
rolebinding.rbac.authorization.k8s.io/rook-ceph-osd created
rolebinding.rbac.authorization.k8s.io/rook-ceph-mgr created
rolebinding.rbac.authorization.k8s.io/rook-ceph-mgr-system created
clusterrolebinding.rbac.authorization.k8s.io/rook-ceph-mgr-cluster created
clusterrolebinding.rbac.authorization.k8s.io/rook-ceph-osd created
rolebinding.rbac.authorization.k8s.io/rook-ceph-cmd-reporter created
podsecuritypolicy.policy/rook-privileged created
clusterrole.rbac.authorization.k8s.io/psp:rook created
clusterrolebinding.rbac.authorization.k8s.io/rook-ceph-system-psp created
rolebinding.rbac.authorization.k8s.io/rook-ceph-default-psp created
rolebinding.rbac.authorization.k8s.io/rook-ceph-osd-psp created
rolebinding.rbac.authorization.k8s.io/rook-ceph-mgr-psp created
rolebinding.rbac.authorization.k8s.io/rook-ceph-cmd-reporter-psp created
serviceaccount/rook-csi-cephfs-plugin-sa created
serviceaccount/rook-csi-cephfs-provisioner-sa created
role.rbac.authorization.k8s.io/cephfs-external-provisioner-cfg created
rolebinding.rbac.authorization.k8s.io/cephfs-csi-provisioner-role-cfg created
clusterrole.rbac.authorization.k8s.io/cephfs-csi-nodeplugin created
clusterrole.rbac.authorization.k8s.io/cephfs-csi-nodeplugin-rules created
clusterrole.rbac.authorization.k8s.io/cephfs-external-provisioner-runner created
clusterrole.rbac.authorization.k8s.io/cephfs-external-provisioner-runner-rules created
clusterrolebinding.rbac.authorization.k8s.io/rook-csi-cephfs-plugin-sa-psp created
clusterrolebinding.rbac.authorization.k8s.io/rook-csi-cephfs-provisioner-sa-psp created
clusterrolebinding.rbac.authorization.k8s.io/cephfs-csi-nodeplugin created
clusterrolebinding.rbac.authorization.k8s.io/cephfs-csi-provisioner-role created
serviceaccount/rook-csi-rbd-plugin-sa created
serviceaccount/rook-csi-rbd-provisioner-sa created
role.rbac.authorization.k8s.io/rbd-external-provisioner-cfg created
rolebinding.rbac.authorization.k8s.io/rbd-csi-provisioner-role-cfg created
clusterrole.rbac.authorization.k8s.io/rbd-csi-nodeplugin created
clusterrole.rbac.authorization.k8s.io/rbd-csi-nodeplugin-rules created
clusterrole.rbac.authorization.k8s.io/rbd-external-provisioner-runner created
clusterrole.rbac.authorization.k8s.io/rbd-external-provisioner-runner-rules created
clusterrolebinding.rbac.authorization.k8s.io/rook-csi-rbd-plugin-sa-psp created
clusterrolebinding.rbac.authorization.k8s.io/rook-csi-rbd-provisioner-sa-psp created
clusterrolebinding.rbac.authorization.k8s.io/rbd-csi-nodeplugin created
clusterrolebinding.rbac.authorization.k8s.io/rbd-csi-provisioner-role created
$
$ kubectl apply -f operator.yaml
deployment.apps/rook-ceph-operator created
$
$ kubectl apply -f cluster.yaml
cephcluster.ceph.rook.io/rook-ceph created
$ 
$ kubectl apply -f toolbox.yaml
deployment.apps/rook-ceph-tools created
$
$ kubectl apply -f dashboard-external-https.yaml
service/rook-ceph-mgr-dashboard-external-https created

デプロイには5~10分前後かかります.(ネットワーク速度による) ここまでできたら以下のコマンドを実行してPodの起動具合を確認してください.

$ watch -n1 "kubectl get pods -n rook-ceph -owide"
csi-cephfsplugin-jjgmh                              3/3     Running     0          21h   xxx.xxx.xxx.xxx   michiru   <none>           <none>
csi-cephfsplugin-lvmcc                              3/3     Running     0          21h   xxx.xxx.xxx.xxx   utaha     <none>           <none>
csi-cephfsplugin-provisioner-565ffd64f5-9dpsp       4/4     Running     0          21h   10.244.2.36      eriri     <none>           <none>
csi-cephfsplugin-provisioner-565ffd64f5-fqmgn       4/4     Running     0          21h   10.244.1.49      michiru   <none>           <none>
csi-cephfsplugin-qqj42                              3/3     Running     0          21h   xxx.xxx.xxx.xxx   eriri     <none>           <none>
csi-cephfsplugin-x677t                              3/3     Running     0          21h   xxx.xxx.xxx.xxx   k8s-m     <none>           <none>
csi-rbdplugin-5xvsz                                 3/3     Running     0          21h   xxx.xxx.xxx.xxx   eriri     <none>           <none>
csi-rbdplugin-gvrxd                                 3/3     Running     0          21h   xxx.xxx.xxx.xxx   utaha     <none>           <none>
csi-rbdplugin-provisioner-7bb78d6c66-6ljfh          5/5     Running     0          21h   10.244.3.32      utaha     <none>           <none>
csi-rbdplugin-provisioner-7bb78d6c66-dkt5w          5/5     Running     0          21h   xxx.xxx.xxx.xxx      michiru   <none>           <none>
csi-rbdplugin-vlxr6                                 3/3     Running     0          21h   xxx.xxx.xxx.xxx   k8s-m     <none>           <none>
csi-rbdplugin-wgv46                                 3/3     Running     0          21h   xxx.xxx.xxx.xxx   michiru   <none>           <none>
rook-ceph-crashcollector-eriri-6df7ff6fff-kmdcp     1/1     Running     0          21h   10.244.2.47      eriri     <none>           <none>
rook-ceph-crashcollector-michiru-77f65f8877-gf6sz   1/1     Running     0          21h   10.244.1.65      michiru   <none>           <none>
rook-ceph-crashcollector-utaha-7458f68769-n5nhn     1/1     Running     0          21h   10.244.3.35      utaha     <none>           <none>
rook-ceph-mgr-a-7c4d46c8c6-jm4d4                    1/1     Running     0          21h   10.244.1.55      michiru   <none>           <none>
rook-ceph-mon-a-5f47c4f56-5wcs4                     1/1     Running     0          21h   10.244.1.54      michiru   <none>           <none>
rook-ceph-mon-b-d6cc4655f-p6x48                     1/1     Running     0          21h   10.244.3.34      utaha     <none>           <none>
rook-ceph-mon-c-597df57bf8-chtwv                    1/1     Running     0          21h   10.244.2.38      eriri     <none>           <none>
rook-ceph-operator-888d59546-k968r                  1/1     Running     0          21h   10.244.2.34      eriri     <none>           <none>
rook-ceph-osd-0-56bd746868-ptdhj                    1/1     Running     0          21h   10.244.3.37      utaha     <none>           <none>
rook-ceph-osd-1-88fcf7bc5-5fvdf                     1/1     Running     0          21h   10.244.2.41      eriri     <none>           <none>
rook-ceph-osd-10-966cd7f69-6ffhn                    1/1     Running     0          21h   10.244.2.42      eriri     <none>           <none>
rook-ceph-osd-11-5c98547c68-p7db2                   1/1     Running     0          21h   10.244.1.58      michiru   <none>           <none>
rook-ceph-osd-12-57c9f8f9c5-j85jc                   1/1     Running     0          21h   10.244.2.43      eriri     <none>           <none>
rook-ceph-osd-13-c4bc674db-mv9s5                    1/1     Running     0          21h   10.244.1.60      michiru   <none>           <none>
rook-ceph-osd-2-78bf5cf9cb-xwnrv                    1/1     Running     0          21h   10.244.1.61      michiru   <none>           <none>
rook-ceph-osd-3-58bfd87b4f-vsrqp                    1/1     Running     0          21h   10.244.3.38      utaha     <none>           <none>
rook-ceph-osd-4-798f58bc4b-ks2bv                    1/1     Running     0          21h   10.244.2.44      eriri     <none>           <none>
rook-ceph-osd-5-d5649865f-fvbrz                     1/1     Running     0          21h   10.244.1.62      michiru   <none>           <none>
rook-ceph-osd-6-886566b68-zh287                     1/1     Running     0          21h   10.244.3.39      utaha     <none>           <none>
rook-ceph-osd-7-856b9f6599-blk29                    1/1     Running     0          21h   10.244.2.45      eriri     <none>           <none>
rook-ceph-osd-8-5fcb74bf9b-hz2cf                    1/1     Running     0          21h   10.244.1.63      michiru   <none>           <none>
rook-ceph-osd-9-85d5654f89-khffz                    1/1     Running     0          21h   10.244.3.40      utaha     <none>           <none>
rook-ceph-osd-prepare-eriri-lkqhx                   0/1     Completed   0          20h   10.244.2.50      eriri     <none>           <none>
rook-ceph-osd-prepare-michiru-245vt                 0/1     Completed   0          20h   10.244.1.71      michiru   <none>           <none>
rook-ceph-osd-prepare-utaha-9xxkg                   0/1     Completed   0          20h   10.244.3.43      utaha     <none>           <none>
rook-ceph-tools-78b599b6dd-zwg46                    1/1     Running     0          21h   10.244.1.53      michiru   <none>           <none>
rook-discover-bcbbq                                 1/1     Running     0          21h   10.244.2.35      eriri     <none>           <none>
rook-discover-knx5t                                 1/1     Running     0          21h   10.244.3.31      utaha     <none>           <none>
rook-discover-wgbbm                                 1/1     Running     0          21h   10.244.1.47      michiru   <none>           <none>

全て立ち上がり終わったら上記のようなPodが立ち上がっているはずです.また,rook-ceph-osdは1デバイスに1つたちあがるようになっているのでデバイスの数rook-ceph-osdが立ち上がっている確認してください. また,rook-discoverがnodeAffinityで設定したNodeのみで立ち上がっていることを確認してください.上記ではeriri・utaha・michiruになっています.

Cephの状態をtool-boxで確認します.以下のコマンドでtoolboxに仮想ログインしてください.

github.com

$ 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-zwg46 /]# ceph status
  cluster:
    id:     c2058098-1c39-48fe-974e-675e7270f8d2
    health: HEALTH_OK
 
  services:
    mon: 3 daemons, quorum a,b,c (age 22h)
    mgr: a(active, since 21h)
    osd: 14 osds: 14 up (since 22h), 14 in (since 22h)
 
  data:
    pools:   0 pools, 0 pgs
    objects: 0 objects, 0 KiB
    usage:   14 GiB used, 6.8 TiB / 6.8 TiB avail
    pgs:     
[root@rook-ceph-tools-78b599b6dd-zwg46 /]# 
[root@rook-ceph-tools-78b599b6dd-zwg46 /]# ceph osd status
+----+---------+-------+-------+--------+---------+--------+---------+-----------+
| id |   host  |  used | avail | wr ops | wr data | rd ops | rd data |   state   |
+----+---------+-------+-------+--------+---------+--------+---------+-----------+
| 0  |  utaha  | 1025M |  463G |    0   |     0   |    0   |     0   | exists,up |
| 1  |  eriri  | 1025M |  463G |    0   |     0   |    0   |     0   | exists,up |
| 2  | michiru | 1025M |  463G |    0   |     0   |    0   |     0   | exists,up |
| 3  |  utaha  | 1025M |  463G |    0   |     0   |    0   |     0   | exists,up |
| 4  |  eriri  | 1025M |  463G |    0   |     0   |    0   |     0   | exists,up |
| 5  | michiru | 1025M |  463G |    0   |     0   |    0   |     0   | exists,up |
| 6  |  utaha  | 1025M |  463G |    0   |     0   |    0   |     0   | exists,up |
| 7  |  eriri  | 1025M |  463G |    0   |     0   |    0   |     0   | exists,up |
| 8  | michiru | 1025M |  445G |    0   |     0   |    0   |     0   | exists,up |
| 9  |  utaha  | 1025M |  929G |    0   |     0   |    0   |     0   | exists,up |
| 10 |  eriri  | 1025M |  463G |    0   |     0   |    0   |     0   | exists,up |
| 11 | michiru | 1025M |  463G |    0   |     0   |    2   |   106   | exists,up |
| 12 |  eriri  | 1025M |  463G |    0   |     0   |    0   |     0   | exists,up |
| 13 | michiru | 1025M |  463G |    0   |     0   |    0   |     0   | exists,up |
+----+---------+-------+-------+--------+---------+--------+---------+-----------+
[root@rook-ceph-tools-78b599b6dd-zwg46 /]# 
[root@rook-ceph-tools-78b599b6dd-zwg46 /]# exit
$

上記のように正常に起動できていることがわかりました.次にCephFsのファイルシステムをデプロイします.

$ kubectl apply -f filesystem.yaml
cephfilesystem.ceph.rook.io/myfs created
$
$ watch -n1 "kubectl get pods -n rook-ceph -owide"
csi-cephfsplugin-jjgmh                              3/3     Running     0          22h   xxx.xxx.xxx.xxx   michiru   <none>           <none>
csi-cephfsplugin-lvmcc                              3/3     Running     0          22h   xxx.xxx.xxx.xxx   utaha     <none>           <none>
csi-cephfsplugin-provisioner-565ffd64f5-9dpsp       4/4     Running     0          22h   10.244.2.36      eriri     <none>           <none>
csi-cephfsplugin-provisioner-565ffd64f5-fqmgn       4/4     Running     0          22h   10.244.1.49      michiru   <none>           <none>
csi-cephfsplugin-qqj42                              3/3     Running     0          22h   xxx.xxx.xxx.xxx   eriri     <none>           <none>
csi-cephfsplugin-x677t                              3/3     Running     0          22h   xxx.xxx.xxx.xxx   k8s-m     <none>           <none>
csi-rbdplugin-5xvsz                                 3/3     Running     0          22h   xxx.xxx.xxx.xxx   eriri     <none>           <none>
csi-rbdplugin-gvrxd                                 3/3     Running     0          22h   xxx.xxx.xxx.xxx   utaha     <none>           <none>
csi-rbdplugin-provisioner-7bb78d6c66-6ljfh          5/5     Running     0          22h   10.244.3.32      utaha     <none>           <none>
csi-rbdplugin-provisioner-7bb78d6c66-dkt5w          5/5     Running     0          22h   10.244.1.48      michiru   <none>           <none>
csi-rbdplugin-vlxr6                                 3/3     Running     0          22h   xxx.xxx.xxx.xxx   k8s-m     <none>           <none>
csi-rbdplugin-wgv46                                 3/3     Running     0          22h   xxx.xxx.xxx.xxx   michiru   <none>           <none>
rook-ceph-crashcollector-eriri-6df7ff6fff-kmdcp     1/1     Running     0          22h   10.244.2.47      eriri     <none>           <none>
rook-ceph-crashcollector-michiru-77f65f8877-gf6sz   1/1     Running     0          22h   10.244.1.65      michiru   <none>           <none>
rook-ceph-crashcollector-utaha-7458f68769-n5nhn     1/1     Running     0          22h   10.244.3.35      utaha     <none>           <none>
rook-ceph-mds-myfs-a-5c9cfbdfdb-ds2n6               1/1     Running     0          22h   10.244.1.64      michiru   <none>           <none>
rook-ceph-mds-myfs-b-d994c8557-cndtn                1/1     Running     0          22h   10.244.2.46      eriri     <none>           <none>
rook-ceph-mgr-a-7c4d46c8c6-jm4d4                    1/1     Running     0          22h   10.244.1.55      michiru   <none>           <none>
rook-ceph-mon-a-5f47c4f56-5wcs4                     1/1     Running     0          22h   10.244.1.54      michiru   <none>           <none>
rook-ceph-mon-b-d6cc4655f-p6x48                     1/1     Running     0          22h   10.244.3.34      utaha     <none>           <none>
rook-ceph-mon-c-597df57bf8-chtwv                    1/1     Running     0          22h   10.244.2.38      eriri     <none>           <none>
rook-ceph-operator-888d59546-k968r                  1/1     Running     0          22h   10.244.2.34      eriri     <none>           <none>
rook-ceph-osd-0-56bd746868-ptdhj                    1/1     Running     0          22h   10.244.3.37      utaha     <none>           <none>
rook-ceph-osd-1-88fcf7bc5-5fvdf                     1/1     Running     0          22h   10.244.2.41      eriri     <none>           <none>
rook-ceph-osd-10-966cd7f69-6ffhn                    1/1     Running     0          22h   10.244.2.42      eriri     <none>           <none>
rook-ceph-osd-11-5c98547c68-p7db2                   1/1     Running     0          22h   10.244.1.58      michiru   <none>           <none>
rook-ceph-osd-12-57c9f8f9c5-j85jc                   1/1     Running     0          22h   10.244.2.43      eriri     <none>           <none>
rook-ceph-osd-13-c4bc674db-mv9s5                    1/1     Running     0          22h   10.244.1.60      michiru   <none>           <none>
rook-ceph-osd-2-78bf5cf9cb-xwnrv                    1/1     Running     0          22h   10.244.1.61      michiru   <none>           <none>
rook-ceph-osd-3-58bfd87b4f-vsrqp                    1/1     Running     0          22h   10.244.3.38      utaha     <none>           <none>
rook-ceph-osd-4-798f58bc4b-ks2bv                    1/1     Running     0          22h   10.244.2.44      eriri     <none>           <none>
rook-ceph-osd-5-d5649865f-fvbrz                     1/1     Running     0          22h   10.244.1.62      michiru   <none>           <none>
rook-ceph-osd-6-886566b68-zh287                     1/1     Running     0          22h   10.244.3.39      utaha     <none>           <none>
rook-ceph-osd-7-856b9f6599-blk29                    1/1     Running     0          22h   10.244.2.45      eriri     <none>           <none>
rook-ceph-osd-8-5fcb74bf9b-hz2cf                    1/1     Running     0          22h   10.244.1.63      michiru   <none>           <none>
rook-ceph-osd-9-85d5654f89-khffz                    1/1     Running     0          22h   10.244.3.40      utaha     <none>           <none>
rook-ceph-osd-prepare-eriri-lkqhx                   0/1     Completed   0          21h   10.244.2.50      eriri     <none>           <none>
rook-ceph-osd-prepare-michiru-245vt                 0/1     Completed   0          21h   10.244.1.71      michiru   <none>           <none>
rook-ceph-osd-prepare-utaha-9xxkg                   0/1     Completed   0          21h   10.244.3.43      utaha     <none>           <none>
rook-ceph-tools-78b599b6dd-zwg46                    1/1     Running     0          22h   10.244.1.53      michiru   <none>           <none>
rook-discover-bcbbq                                 1/1     Running     0          22h   10.244.2.35      eriri     <none>           <none>
rook-discover-knx5t                                 1/1     Running     0          22h   10.244.3.31      utaha     <none>           <none>
rook-discover-wgbbm                                 1/1     Running     0          22h   10.244.1.47      michiru   <none>           <none>

rook-ceph-mds-myfsが起動出来ていることを確認してください.起動できていたら先ほど同様にtool-boxで正常にpoolが起動できているか確認します.

$  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-zwg46 /]# ceph status
  cluster:
    id:     c2058098-1c39-48fe-974e-675e7270f8d2
    health: HEALTH_OK
 
  services:
    mon: 3 daemons, quorum a,b,c (age 22h)
    mgr: a(active, since 21h)
    mds: myfs:1 {0=myfs-a=up:active} 1 up:standby-replay
    osd: 14 osds: 14 up (since 22h), 14 in (since 22h)
 
  data:
    pools:   2 pools, 16 pgs
    objects: 31 objects, 3.7 KiB
    usage:   14 GiB used, 6.8 TiB / 6.8 TiB avail
    pgs:     16 active+clean
 
  io:
    client:   1.2 KiB/s rd, 2 op/s rd, 0 op/s wr
[root@rook-ceph-tools-78b599b6dd-zwg46 /]#
[root@rook-ceph-tools-78b599b6dd-zwg46 /]# ceph df
RAW STORAGE:
    CLASS     SIZE        AVAIL       USED       RAW USED     %RAW USED 
    ssd       6.8 TiB     6.8 TiB     20 MiB       14 GiB          0.20 
    TOTAL     6.8 TiB     6.8 TiB     20 MiB       14 GiB          0.20 
 
POOLS:
    POOL              ID     STORED      OBJECTS     USED        %USED     MAX AVAIL 
    myfs-metadata      1     3.7 KiB          22     384 KiB         0       2.1 TiB 
    myfs-data0         2        16 B           9      48 KiB         0       2.1 TiB 
[root@rook-ceph-tools-78b599b6dd-zwg46 /]#
[root@rook-ceph-tools-78b599b6dd-zwg46 /]# exit
$

filesystem.yamlで以下のようにreplicated(回復性)を3,回復基準をホストに設定しているのでpoolの使用可能容量が1/3になっています.

...(省略)
  # The list of data pool specs. Can use replication or erasure coding.
  dataPools:
    - failureDomain: host
      replicated:
        size: 3
...(省略)

PVとしての使用

実際にPersistentVolumeを作成してPodにマウントしてみます. CSIドライバとFlexドライバの二種類が用意されていますが,Kubernetes v1.13以降で推奨されているCSIドライバを使用します.Kubernetes 1.12以前ではFlexドライバの使用でも大丈夫だそうです.

github.com

NOTE: This example uses the CSI driver, which is the preferred driver going forward for K8s 1.13 and newer. Examples are found in the CSI CephFS directory. For an example of a volume using the flex driver (required for K8s 1.12 and earlier), see the Flex Driver section below.

「rook/cluster/examples/kubernetes/ceph/csi/cephfs/strageclass.yaml」の以下の項目でPersistentVolumeのReclaim Policyが設定できます.今回はデフォルトのDeleteのまま使用します.

...(省略)
  # (optional) The driver can use either ceph-fuse (fuse) or ceph kernel client (kernel)
  # If omitted, default volume mounter will be used - this is determined by probing for ceph-fuse
  # or by setting the default mounter explicitly via --volumemounter command-line argument.
  # mounter: kernel
reclaimPolicy: Delete
mountOptions:
  # uncomment the following line for debugging
  #- debug
...(省略)

「rook/cluster/examples/kubernetes/ceph/csi/cephfs/strageclass.yaml」・「rook/cluster/examples/kubernetes/ceph/csi/cephfs/pvc.yaml」・「rook/cluster/examples/kubernetes/ceph/csi/cephfs/pod.yaml」をデプロイしていきます.

$ cd rook/cluster/examples/kubernetes/ceph/csi/cephfs/
$ kubectl apply -f strageclass.yaml
storageclass.storage.k8s.io/csi-cephfs created
$ kubectl apply -f pvc.yaml
persistentvolumeclaim/cephfs-pvc created
$ kubectl apply -f csi/cephfs/pod.yaml
pod/csicephfs-demo-pod created
$
$ kubectl get sc
$ NAME         PROVISIONER                     AGE
csi-cephfs   rook-ceph.cephfs.csi.ceph.com   45m
$
$ kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                STORAGECLASS   REASON   AGE
pvc-6ced0e07-5a3c-4a4c-addf-3ea2c4ea2427   1Gi        RWX            Delete           Bound    default/cephfs-pvc   csi-cephfs              6s
$
$ kubectl get pvc
NAME         STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
cephfs-pvc   Bound    pvc-6ced0e07-5a3c-4a4c-addf-3ea2c4ea2427   1Gi        RWX            csi-cephfs     10s
$
$ kubectl describe pods csicephfs-demo-pod
...(省略)
Conditions:
  Type              Status
  Initialized       True 
  Ready             True 
  ContainersReady   True 
  PodScheduled      True 
Volumes:
  mypvc:
    Type:       PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
    ClaimName:  cephfs-pvc
    ReadOnly:   false
  default-token-zmhnb:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-zmhnb
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  kubernetes.io/hostname=utaha
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason                  Age        From                     Message
  ----    ------                  ----       ----                     -------
  Normal  Scheduled               <unknown>  default-scheduler        Successfully assigned default/csicephfs-demo-pod to utaha
  Normal  SuccessfulAttachVolume  3m40s      attachdetach-controller  AttachVolume.Attach succeeded for volume "pvc-6ced0e07-5a3c-4a4c-addf-3ea2c4ea2427"
  Normal  Pulling                 3m22s      kubelet, utaha           Pulling image "nginx"
  Normal  Pulled                  2m51s      kubelet, utaha           Successfully pulled image "nginx"
  Normal  Created                 2m51s      kubelet, utaha           Created container web-server
  Normal  Started                 2m51s      kubelet, utaha           Started container web-server

PV,PVCともに無事にBOUNDされており,Podにマウントされていることがわかります.

Ceph DashBoard

最後にDashBoardにアクセスしてみます.URLはCluseterのホストプライベートIPアドレスの30123にアクセスすると以下のように表示されるはずです.

ceph_dashboard_login_page
Ceph DashBoardログイン画面

初期ユーザ名はadminでパスワードは以下のコマンドを実行すると取得できます.

github.com

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

ceph_dashboard_top_page
Ceph DashBoardトップ画面

トラブルシューティング

構築に失敗して再構築する際は使用したデバイスを初期化しましょう.以下のコマンドで初期化できます. デバイス名は任意に設定してください.

$ sudo dmsetup remove_all && sudo sgdisk -Z /dev/sda && sudo rm -vR /var/lib/rook*

おわりに

今回はRookによってストレージオーケストレーションを実装してみました. Linux Kernelの部分で躓くなど結構大変でしたがやってよかったと思います.