Rook-Cephfs + Nvidia Driver vs てんぜん
はじめに
RookだらけのAdvent Calenderに一通り目を通して面白そうだと思い やってみました.
Advent Calernderで寄稿されている記事の数々は全て非常に有益であり,大変わかりやすかったのですが私自身完全に沼にハマってしまい(特にLinux Kernelの部分やNvidia Driver関連の部分)動かすまでにだいぶ苦労しましたので,他の方が同じ道をたどらないように備忘録を残しておきます.
また,以前ブログで書いたこの環境にRook環境を準備していくので,kubernetes環境構築がまだの方は先に構築してきてください.
Rookとは
RookについてはRedHatの方が非常にわかりやすく解説してされているので詳細はそちらの方もしくは公式ページを読んでいただけば良いのですが,ここでも軽くまとめておきます.
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において記事執筆時点で以前私が以下の記事
でも行った,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番を使用しました.
ダウンロードできたらダウンロードしてきたファイルの権限を変更後ディスプレイマネージャを切って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サーバの時間に全てのサーバの時間を合わせます.
まず,必要なパッケージ類をインストールしていきます.
$ 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」の状態となったため行いました.
...(省略) # 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に仮想ログインしてください.
$ 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ドライバの使用でも大丈夫だそうです.
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にアクセスすると以下のように表示されるはずです.
初期ユーザ名はadminでパスワードは以下のコマンドを実行すると取得できます.
$ kubectl -n rook-ceph get secret rook-ceph-dashboard-password -o jsonpath="{['data']['password']}" | base64 --decode && echo hogehoge
トラブルシューティング
構築に失敗して再構築する際は使用したデバイスを初期化しましょう.以下のコマンドで初期化できます. デバイス名は任意に設定してください.
$ sudo dmsetup remove_all && sudo sgdisk -Z /dev/sda && sudo rm -vR /var/lib/rook*
おわりに
今回はRookによってストレージオーケストレーションを実装してみました. Linux Kernelの部分で躓くなど結構大変でしたがやってよかったと思います.