kubesprayで構築したk8s環境にTopoLVMを使用してRook Cephのブロックストレージを構築する

# はじめに
おうちのk8s環境でクラウド環境と同様なストレージサービスを利用したい（まだまだこれから勉強なのですが、とりあえず永続ボリュームがサクッとつくれないと不便だと思っている）ので、Rook Cephの環境を構築しました。
以下の記事には大変お世話になりました。わかってしまえば簡単なことも、自分は結構時間をとってしまったので、誰かのお役に立てればと思い、記事として残します。

[TopoLVMによるPVC-basedなRook/Ceph with Pod Topology Spread Constraints](https://tenzen.hatenablog.com/entry/2020/07/12/231235)
[RancherでTopoLVMの動作環境を構築する方法](https://github.com/masa213f/example-topolvm)

---

#環境
ESXi6.7

- vm
  - k8s-master (cpu x2, mem 4GB,HDD System:30GB) x 1台
  - k8s-node1~3(cpu x2, mem 4GB,HDD System:30GB Storage用:50GB) x 3台
  - jumpserver     x 1台 (Vagrant, kubespray作業用VM)

- os
  - k8s-master, k8s-node1~3 Ubuntu20.04LTS
  - jumpserver:CentOS8.2.2004

##k8s環境
![k8s-storage (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91405/c4cd6059-b8f6-3273-3099-eb5e1a83b611.png)

##TopoLVMを使用したRook Ceph
![k8s-storage-rook (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91405/1ce7fe14-bf29-19de-731a-0b4aee5a6134.png)

---

# 手順

## VMの構築

### ベースOSの選定
Ubuntuを使っている記事が多いので、無難にUbuntuにしました。
（VMのディスクサイズをカスタマイズしたかったので自前のboxを作りました）
一応、コマンドを記載しておきます。

#### OSの更新
```bash
apt-get update
apt-get upgrade -y
apt-get dist-upgrade -y
```

#### 再起動
```bash
shutdown -r now
```

#### sshの設定
```bash
mkdir /home/vagrant/.ssh
chmod 700 /home/vagrant/.ssh
cd /home/vagrant/.ssh 
curl -k -L -o authorized_keys 'https://github.com/hashicorp/vagrant/blob/master/keys/vagrant.pub'
chmod 600 /home/vagrant/.ssh/authorized_keys
chown -R vagrant:vagrant /home/vagrant/.ssh
```

#### パスワードなしでsudo可の設定
```bash
visodo
```

以下の行を最終行に追加する
vagrant ALL=(ALL) NOPASSWD: ALL

#### sshdのUseDNSをnoにしてssh接続を高速化する
```bash
vi /etc/ssh/sshd_config
```

UseDNS no がコメント化されている行があるので先頭の#を外す


#### 軽量化
```bash
apt-get clean
apt-get autoremove

export HISTSIZE=0
rm -f /home/vagrant/.bash_history
rm -f /root/.bash_history
rm -rf /var/log/*
rm -rf /tmp/*

dd if=/dev/zero of=/tmp/ZERO bs=1M
rm /tmp/ZERO
```
#### 仮想マシンを停止
```bash
shutdown -h now
```

---

### boxイメージの作成
以下の記事を参照して作成します。
→[Vagrant box用イメージの作成](https://qiita.com/yasubehe/items/4cbb03451d2dec58b669#vagrant-box%E7%94%A8%E3%82%A4%E3%83%A1%E3%83%BC%E3%82%B8%E3%81%AE%E4%BD%9C%E6%88%90)

---

### VangantでVM構築
VagrantでESXi上に新規にk8s構築用のVMを4台作成します（作業用のVMは別に用意してあります）。

#### Vagrant実行環境の準備
作業用のVMはCentOS8.2です（もともとあるものを流用）。
以下の手順でVagrant実行環境を準備します。
[CentOS8.2にVagrantをインストール](https://qiita.com/yasubehe/items/4cbb03451d2dec58b669#centos82%E3%81%ABvagrant%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)


#### VM構築
各Workerノードにシステムディスクとは別のディスク（50GB）を追加して構築します。
構築後、50GBのディスクが/dev/sdbとして見えることを前提としています。

以下のVagrantファイルを使用して構築しています。
[Vagrantfile](https://raw.githubusercontent.com/yasubehe/k8s-vagrant/master/k8s-ubuntu/vagrant/Vagrantfile)
[config.yaml](https://github.com/yasubehe/k8s-vagrant/blob/master/k8s-ubuntu/vagrant/config.yaml)

vagrant multi sequenceで作成していて一気に構築できるはずなのですが、エラーになるので一個ずつ作成しています。
vagrantはあまり触ったことがないのでここは気にしないでおきます。。。

```bash
#/bin/bash
vagrant up k8s-master
vagrant up k8s-node1
vagrant up k8s-node2
vagrant up k8s-node3
```

---

## kubesprayによるk8sの構築

### kubespray実行環境のセットアップ
ここでは、jumpserverにkubesprayの実行環境を構築します。

#### 事前設定
jumpserverのssh公開鍵を各workerノードのauthorized_keysにコピーします。
各workerノードにsshpassをインストールします。

これは、前述の「VM構築」で構築時に設定しました(Vagrantfile参照)。

#### jumpserverの設定
```bash
git clone https://github.com/kubernetes-sigs/kubespray.git

dnf install python38 -y
pip3 install --upgrade pip
cd kubespray
pip3 install -r requirements.txt
```

---

### k8sの構築

#### 設定
Inventory/Playbookの内容確認を確認し、書き換えます。

IPSの部分は作成するノードすべてのIPアドレスを記載します。

```bash
cp -rfp inventory/sample inventory/mycluster
declare -a IPS=(192.168.123.180 192.168.123.181 192.168.123.182 192.168.123.183)
CONFIG_FILE=inventory/mycluster/hosts.yml python3 contrib/inventory_builder/inventory.py ${IPS[@]}
```

自動生成されたhosts.ymlファイルを以下のように編集します。
デフォルトでは、node1、node2、node3、node4のような名前がホスト名になってしまうため、わかりやすくするためです。
また、Control Plane 1台、Workerノード 3台になるように、設定を見直します。
etcdはControl Planeでのみ起動するようにします。

hosts.yml

```yaml
all:
  hosts:
    k8s-master:
      ansible_host: 192.168.123.180
      ip: 192.168.123.180
      access_ip: 192.168.123.180
    k8s-node1:
      ansible_host: 192.168.123.181
      ip: 192.168.123.181
      access_ip: 192.168.123.181
    k8s-node2:
      ansible_host: 192.168.123.182
      ip: 192.168.123.182
      access_ip: 192.168.123.182
    k8s-node3:
      ansible_host: 192.168.123.183
      ip: 192.168.123.183
      access_ip: 192.168.123.183
  children:
    kube-master:
      hosts:
        k8s-master:
    kube-node:
      hosts:
        k8s-node1:
        k8s-node2:
        k8s-node3:
    etcd:
      hosts:
        k8s-master:
    k8s-cluster:
      children:
        kube-master:
        kube-node:
    calico-rr:
      hosts: {}
```

---

#### 構築
以下のコマンドを実行してk8s環境を構築します。


```bash
ansible-playbook -i inventory/mycluster/hosts.yml cluster.yml -b -v --private-key=~/.ssh/id_rsa
```

---

## TopoLVMの設定
ここからは、kubectlが実行できる環境で実施します（k8s-masterで実施しました）。

[TopoLVMのデプロイ](https://github.com/topolvm/topolvm/tree/master/deploy)の手順と比較しながら見てもらえるとわかりやすいと思います。

---

### TopoLVMのインストール
すべてのWorkerノードで以下のシェルを実行し、TopoLVMをインストールします。
（Vagrantファイル内からシェルを実行して一気に構築してしまってもよいかもしれません）

[install.sh](https://raw.githubusercontent.com/yasubehe/k8s-vagrant/master/k8s-ubuntu/vagrant/topoLVM/install.sh)

```bash
#!/bin/bash

# install TopoLVM ★2020/8/12時点でバージョンは0.5.3が最新

echo "TopoLVM install"
pvcreate /dev/sdb
vgcreate datagroup /dev/sdb

mkdir -p /root/lvmd
cd /root/lvmd
wget https://github.com/topolvm/topolvm/releases/download/v0.5.3/lvmd-0.5.3.tar.gz
tar zxvf lvmd-0.5.3.tar.gz
mkdir /opt/sbin
chown root:root lvmd
mv lvmd /opt/sbin/lvmd

git clone --single-branch --branch v0.5.3 https://github.com/topolvm/topolvm.git
sed -i -e 's/^\(\s*volume-group: \).*$/\1datagroup/g' ./topolvm/deploy/lvmd-config/lvmd.yaml
mkdir /etc/topolvm
cp -p ./topolvm/deploy/lvmd-config/lvmd.yaml /etc/topolvm/lvmd.yaml
cp -p ./topolvm/deploy/systemd/lvmd.service /etc/systemd/system/lvmd.service
systemctl enable --now lvmd

echo "TopoLVM installed"
```

---

## TopoLVMのためのk8sの設定

### k8sの設定

#### cert-managerのデプロイ

```bash
kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v0.16.1/cert-manager.yaml
```

#### topolvm-system名前空間の作成

```bash
git clone --single-branch --branch v0.5.3 https://github.com/topolvm/topolvm.git
kubectl apply -f ./topolvm/deploy/manifests/base/namespace.yaml
```

#### topolvm-schedulerの設定ファイルの配備
```bash
mkdir -p /etc/kubernetes/topolvm/
cp -p ./topolvm/deploy/scheduler-config/* /etc/kubernetes/topolvm/
```

#### topolvm-schedulerの設定

今回は、DaemonSetとしてtopolvm-schedulerを動作させます。
（Deployment and Serviceを使用して動作させることも可能なようです。）

kubectlを実行するサーバ（例:Control plane）でソースをDLします。

```
dnf install git -y
git clone --single-branch --branch v0.5.3 https://github.com/topolvm/topolvm.git
```

使用するマニフェストは以下のファイルす。
topolvm/deploy/manifests/overlays/daemonset-scheduler/scheduler.yaml

変更するポイント
・hostNetwork: true
  kube-scheduler がhostNetworkを使用していない場合は、hostNetworkの値を変更する必要があります。
  
  わからなかったら以下のコマンドで確認します。

```
kubectl get pods -n kube-system
kubectl get pod kube-scheduler-xxxxxxx -n kube-system -o yaml
```

  自分の環境では変更しません。

・key: node-role.kubernetes.io/master
  control plane ノードに一致するラベルを指定する必要があります。

  以下のコマンドを実行して上記ラベルが control planeノードに存在するか確認します。
  存在しなければ値を変更する必要があります。

```
kubectl get node --show-labels
```

  自分の環境では変更しません。

#### TopoLVM Webhookからシステム名前空間を保護
```bash
kubectl label ns kube-system topolvm.cybozu.com/webhook=ignore
```

---

## TopoLVMのデプロイ

#### Kustomizeのインストール
公式ではKustomizeを使用してデプロイしているのでそれに従います。
→Kustomizeとは、kubernetesのYAML設定ファイルをパッケージングするツールです。

```bash
wget https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh
bash ./install_kustomize.sh
mv kustomize /usr/local/bin/kustomize
```

#### kustomizeを使用してTopoLVMをデプロイ
```bash
/usr/local/bin/kustomize build ./topolvm/deploy/manifests/overlays/daemonset-scheduler | kubectl apply -f -
```

node Podの起動を待つ

```bash
kubectl get pods -n topolvm-system -l app.kubernetes.io/name=node
```

#### cert-managerマニフェストを生成する
```bash
kubectl apply -f ./topolvm/deploy/manifests/base/certificates.yaml
```

#### TopoLVMのpodが起動していることを確認する
```bash
kubectl get pods -n topolvm-system --watch
```

#### kube-schedulerの設定

```
vi /etc/kubernetes/manifests/kube-scheduler.yaml
```

以下のように編集します。

```yaml

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    component: kube-scheduler
    tier: control-plane
  name: kube-scheduler
  namespace: kube-system
spec:
  containers:
  - command:
    - kube-scheduler
    - --authentication-kubeconfig=/etc/kubernetes/scheduler.conf
    - --authorization-kubeconfig=/etc/kubernetes/scheduler.conf
    - --bind-address=0.0.0.0
    - --kubeconfig=/etc/kubernetes/scheduler.conf
    - --leader-elect=true
    - --port=0
    - --config=/var/lib/scheduler/scheduler-config.yaml    #★追加
    image: k8s.gcr.io/kube-scheduler:v1.18.6
    imagePullPolicy: IfNotPresent
    livenessProbe:
      failureThreshold: 8
      httpGet:
        path: /healthz
        port: 10259
        scheme: HTTPS
      initialDelaySeconds: 15
      timeoutSeconds: 15
    name: kube-scheduler
    resources:
      requests:
        cpu: 100m
    volumeMounts:
    - mountPath: /etc/kubernetes/scheduler.conf
      name: kubeconfig
      readOnly: true
    - mountPath: /var/lib/scheduler    #★追加
      name: topolvm-config             #★追加
      readOnly: true                   #★追加
  hostNetwork: true
  priorityClassName: system-cluster-critical
  volumes:
  - hostPath:
      path: /etc/kubernetes/scheduler.conf
      type: FileOrCreate
    name: kubeconfig
  - hostPath:                          #★追加
      path: /etc/kubernetes/topolvm    #★追加
      type: Directory                  #★追加
    name: topolvm-config               #★追加
status: {}
```


---

## Rook/Cephのデプロイ

参考：https://tenzen.hatenablog.com/entry/2020/07/12/231235
      https://qiita.com/MahoTakara/items/a1ed9811c790cd2a0d5f

### 事前準備

3つのworker nodeがそれぞれ別rackにあることを想定して、各ノードにrackをラベルとして与えます。
それぞれのノードにosd podが分散するように構築してきます。

```bash
kubectl label node k8s-node1 topology.rook.io/rack=rackA
kubectl label node k8s-node2 topology.rook.io/rack=rackB
kubectl label node k8s-node3 topology.rook.io/rack=rackC
```

### common operator のデプロイ
「common.yaml」「operator.yaml」をデプロイします。

```bash
git clone --single-branch --branch release-1.4 https://github.com/rook/rook.git
```

#### Common Resources
```bash
kubectl create -f rook/cluster/examples/kubernetes/ceph/common.yaml
```

#### Operator
```bash
kubectl create -f rook/cluster/examples/kubernetes/ceph/operator.yaml
```

### 「cluster-on-pvc.yaml」の編集
OSDの数は6、rackおよびrack内のノードで分散配置するように設定しています。
（[TopoLVMによるPVC-basedなRook/Ceph with Pod Topology Spread Constraints](https://tenzen.hatenablog.com/entry/2020/07/12/231235)）の設定ほぼそのままです。
今回は、3rackかつ1ノード/rackで分散されるので各workerノードに2OSD podが起動することになります。

[cluster-on-pvc.yaml](https://raw.githubusercontent.com/yasubehe/k8s-vagrant/master/k8s-ubuntu/rook/cluster-on-pvc.yaml)

```yaml
apiVersion: ceph.rook.io/v1
kind: CephCluster
metadata:
  name: rook-ceph
  namespace: rook-ceph
spec:
  dataDirHostPath: /var/lib/rook
  mon:
    count: 3
    allowMultiplePerNode: false
    volumeClaimTemplate:
      spec:
        storageClassName: topolvm-provisioner
        resources:
          requests:
            storage: 3Gi
  cephVersion:
    image: ceph/ceph:v15.2.4
    allowUnsupported: false
  skipUpgradeChecks: false
  continueUpgradeAfterChecksEvenIfNotHealthy: false
  mgr:
    modules:
    - name: pg_autoscaler
      enabled: true
  dashboard:
    enabled: true
    ssl: true
  crashCollector:
    disable: false
  storage:
    storageClassDeviceSets:
    - name: topolvm-ssd-cluster
      count: 6
      portable: false
      tuneSlowDeviceClass: true
      encrypted: false
      placement:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - rook-ceph-osd
                - key: app
                  operator: In
                  values:
                  - rook-ceph-osd-prepare
              topologyKey: kubernetes.io/hostname
        topologySpreadConstraints:
        # rackで分散配置
        - maxSkew: 1
          topologyKey: topology.rook.io/rack
          whenUnsatisfiable: DoNotSchedule
          labelSelector:
            matchExpressions:
            - key: app
              operator: In
              values:
              - rook-ceph-osd
              - rook-ceph-osd-prepare
        # rack内のnodeで分散配置（今回はrack内にnode1台なので意味はない）
        - maxSkew: 1
          topologyKey: kubernetes.io/hostname
          whenUnsatisfiable: DoNotSchedule
          labelSelector:
            matchExpressions:
            - key: app
              operator: In
              values:
              - rook-ceph-osd
              - rook-ceph-osd-prepare
      resources:
      volumeClaimTemplates:
      - metadata:
          name: data
        spec:
          resources:
            requests:
              storage: 10Gi
          storageClassName: topolvm-provisioner
          volumeMode: Block
          accessModes:
            - ReadWriteOnce
  disruptionManagement:
    managePodBudgets: false
    osdMaintenanceTimeout: 30
    manageMachineDisruptionBudgets: false
    machineDisruptionBudgetNamespace: openshift-machine-api
```

### cluster-on-pvc のデプロイ

```bash
kubectl apply -f https://raw.githubusercontent.com/yasubehe/k8s-vagrant/master/k8s-storage/cluster-on-pvc.yaml
```

### CephFSのデプロイ
```bash
kubectl apply -f https://raw.githubusercontent.com/yasubehe/k8s-vagrant/master/k8s-ubuntu/rook/filesystem.yaml
```

---

## Rook toolboxのセットアップ
cephの状態を確認します。

```bash
kubectl apply -f ./rook/cluster/examples/kubernetes/ceph/toolbox.yaml
```

podの起動を確認する（STATUSがRunningになるのを待つ）

```bash
root@k8s-master:~# kubectl -n rook-ceph get pod -l "app=rook-ceph-tools"
NAME                              READY   STATUS    RESTARTS   AGE
rook-ceph-tools-7d9467775-xm984   1/1     Running   0          63s
root@k8s-master:~#
```

ポッドに接続

```
root@k8s-master:~# kubectl -n rook-ceph exec -it $(kubectl -n rook-ceph get pod -l "app=rook-ceph-tools" -o jsonpath='{.items[0].metadata.name}') bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl kubectl exec [POD] -- [COMMAND] instead.
[root@rook-ceph-tools-7d9467775-xm984 /]#
```

ceph statusを実行します。
healthがHEALTH_OKになっていることが確認できます。

```
[root@rook-ceph-tools-7d9467775-xm984 /]# ceph status
  cluster:
    id:     ed6cbc67-9813-439c-9111-d7d3ee19d1ca
    health: HEALTH_OK

  services:
    mon: 3 daemons, quorum a,b,c (age 10m)
    mgr: a(active, since 9m)
    mds: yasubehefs:1 {0=yasubehefs-a=up:active} 1 up:standby-replay
    osd: 6 osds: 6 up (since 9m), 6 in (since 9m)

  task status:
    scrub status:
        mds.yasubehefs-a: idle
        mds.yasubehefs-b: idle

  data:
    pools:   2 pools, 64 pgs
    objects: 22 objects, 2.2 KiB
    usage:   6.0 GiB used, 54 GiB / 60 GiB avail
    pgs:     64 active+clean

  io:
    client:   1.2 KiB/s rd, 2 op/s rd, 0 op/s wr

[root@rook-ceph-tools-7d9467775-xm984 /]#
```

## cephのダッシュボードにアクセスする

参考：[ROOK Ceph のブロックストレージを検証したメモ](https://qiita.com/MahoTakara/items/a1ed9811c790cd2a0d5f#%E3%82%B9%E3%83%88%E3%83%AC%E3%83%BC%E3%82%B8%E3%82%AF%E3%83%A9%E3%82%B9%E3%81%AE%E8%A8%AD%E5%AE%9A)

サービスがClusterIPになっているのでNodePortに変更してアクセスする。

```bash
kubectl patch service rook-ceph-mgr-dashboard -n rook-ceph -p '{"spec":{"type":"NodePort"}}'
```

ポート番号を確認します。

```bash
root@k8s-master:~# kubectl -n rook-ceph get service rook-ceph-mgr-dashboard
NAME                      TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
rook-ceph-mgr-dashboard   NodePort   10.233.15.104   <none>        8443:32702/TCP   9h
root@k8s-master:~#
```

以下のURLでアクセスします。

```
https://192.168.123.181:32702/
```

ユーザ：admin 
パスワードは以下で取得します。

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

---

## 動作確認

ブロックストレージが使えるのか動作を確認してみます。
「[RancherでTopoLVMの動作環境を構築する方法](https://github.com/masa213f/example-topolvm)」ここのサンプルを借用させていただきました。

testpod.yaml

```yaml
kind: PersistentVolumeClaim         # PersistentVolumeClaimの作成
apiVersion: v1
metadata:
  name: topolvm-pvc
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi                  # 1GiBのボリュームを作る
  storageClassName: topolvm-provisioner  # topoLVMから
---
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
  labels:
    app.kubernetes.io/name: my-pod
spec:
  containers:
  - name: ubuntu
    image: quay.io/cybozu/ubuntu:18.04
    command: ["/usr/local/bin/pause"]
    volumeMounts:
    - mountPath: /test1           # /test1にマウントする
      name: my-volume
  volumes:                        # このボリュームを作って
    - name: my-volume
      persistentVolumeClaim:
        claimName: topolvm-pvc
```

デプロイします。

```bash
root@k8s-master:~# kubectl apply -f testpod.yaml
persistentvolumeclaim/topolvm-pvc created
pod/my-pod created
root@k8s-master:~#
```

起動を確認します。

```bash

root@k8s-master:~# kubectl get pods
NAME     READY   STATUS    RESTARTS   AGE
my-pod   1/1     Running   0          35m
root@k8s-master:~#
```

1Giのpvcが作られています。

```bash
root@k8s-master:~# kubectl get pvc
NAME          STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS          AGE
topolvm-pvc   Bound    pvc-a16fa45e-2ae5-4d99-844c-5207767fe4e8   1Gi        RWO            topolvm-provisioner   43m
root@k8s-master:~#
```

cephのボリュームがPVで割り当たっています。
ceph自身もPVで作られています。

```bash
root@k8s-master:~# kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                                        STORAGECLASS          REASON   AGE
pvc-1a3d8280-a60a-4c48-9abc-d14b1b1d6600   3Gi        RWO            Delete           Bound    rook-ceph/rook-ceph-mon-b                    topolvm-provisioner            10h
pvc-2bdaa2ea-c38d-42cf-904f-ded8a482f975   10Gi       RWO            Delete           Bound    rook-ceph/topolvm-ssd-cluster-data-4-5mvmj   topolvm-provisioner            10h
pvc-313c2cee-86cc-415c-b707-e97e9c1f18c0   10Gi       RWO            Delete           Bound    rook-ceph/topolvm-ssd-cluster-data-0-lfgqp   topolvm-provisioner            10h
pvc-56510718-faef-4950-8c5e-2c3b5754b0fc   3Gi        RWO            Delete           Bound    rook-ceph/rook-ceph-mon-c                    topolvm-provisioner            10h
pvc-67cfbfd3-439d-4ab3-bcb2-e3a060d63038   10Gi       RWO            Delete           Bound    rook-ceph/topolvm-ssd-cluster-data-2-xxdl5   topolvm-provisioner            10h
pvc-7feee616-eee7-497a-a8f7-85907cc40c80   3Gi        RWO            Delete           Bound    rook-ceph/rook-ceph-mon-a                    topolvm-provisioner            10h
pvc-866dc1a3-de63-4046-a120-a13bf1d73e6e   10Gi       RWO            Delete           Bound    rook-ceph/topolvm-ssd-cluster-data-1-9v2bd   topolvm-provisioner            10h
pvc-a16fa45e-2ae5-4d99-844c-5207767fe4e8   1Gi        RWO            Delete           Bound    default/topolvm-pvc                          topolvm-provisioner            44m
pvc-b89bef94-22f4-4a26-ace4-fbad54f2dccd   10Gi       RWO            Delete           Bound    rook-ceph/topolvm-ssd-cluster-data-3-cchh6   topolvm-provisioner            10h
pvc-c1ac3bd5-90d9-4f1b-ad15-f0dc2a551a55   10Gi       RWO            Delete           Bound    rook-ceph/topolvm-ssd-cluster-data-5-qmzxk   topolvm-provisioner            10h
root@k8s-master:~#
```

乗り込んで、期待通りか確認します。
/test1にマウントされてました。

```bash
kubectl exec -it my-pod bash
root@my-pod:/# mount | grep test1
/dev/topolvm/453c2052-eacc-4da1-b9b6-845ba1acd615 on /test1 type xfs (rw,relatime,lazytime,wsync,attr2,inode64,logbufs=8,logbsize=32k,noquota)
root@my-pod:/#
```

---

#まとめ
おうち環境でも永続ボリュームが作れるようになりました。
kubesprayやKustomizeもただ使っているだけなので徐々に慣れていきたいです。

---

#参考URL
[TopoLVMによるPVC-basedなRook/Ceph with Pod Topology Spread Constraints](https://tenzen.hatenablog.com/entry/2020/07/12/231235)
[RancherでTopoLVMの動作環境を構築する方法](https://github.com/masa213f/example-topolvm)
[kubespray](https://github.com/kubernetes-sigs/kubespray)
[Deploying TopoLVM](https://github.com/topolvm/topolvm/tree/master/deploy)