====== 16 Kubernetes + DRBD Linstor ====== Kubernetes用の冗長化ストレージとして、Linstorを用意してみる。 LinstorはLINBITが開発した、DRBDを管理する管理DBを持つlinstor-controllerとlinstor-satelliteというデータディスクを扱うプログラムで構成されてます。 [[https://github.com/LINBIT/linstor-server]] {{:06_virtualization:05_container:linstor.png|}} ====== 1.環境 ====== 今回はKubernetesのworkerノード3台で、Linstor ^ name ^ IP ^ Disk ^ DRBD用 ^ |node1|172.16.0.65|/dev/sda|/dev/sdb| |node2|172.16.0.252|/dev/sda|/dev/sdb| |node3|172.16.0.234|/dev/sda|/dev/sdb| ※sdaは/用、sdbはlinstor用 ====== 2. DRBDインストール ====== add-apt-repository ppa:linbit/linbit-drbd9-stack apt-get update && apt install drbd-utils drbd-dkms lvm2 modprobe drbd ===== DRBD確認 ===== # cat /proc/drbd version: 9.1.6 (api:2/proto:110-121) GIT-hash: f85adeb71f16a0aead1e875665e2fb68852d94eb build by root@worker01, 2022-04-15 21:43:08 Transports (api:17): tcp (9.1.6) ====== 3. LINSTORインストール ====== 今回は3台でlinstor-controllerを冗長化するので、3台とも全部インストール apt install linstor-controller linstor-satellite linstor-client ===== linstor-controllerはDisable ===== systemctl disable linstor-controller ===== 自動補完 ===== # source /etc/bash_completion.d/linstor # または # source /usr/share/bash_completion/completions/linstor ====== 4. Linstor初期化 ====== 1度node1で、linstor-controllerを上げて初期設定を行います。 node1# systemctl start linstor-controller linstor node create node1 172.16.0.65 linstor node create node2 172.16.0.252 linstor node create node3 172.16.0.234 ===== 確認 ===== node1# linstor node list ╭────────────────────────────────────────────────────────╮ ┊ Node ┊ NodeType ┊ Addresses ┊ State ┊ ╞════════════════════════════════════════════════════════╡ ┊ node1 ┊ SATELLITE ┊ 172.16.0.65:3366 (PLAIN) ┊ Online ┊ ┊ node2 ┊ SATELLITE ┊ 172.16.0.252:3366 (PLAIN) ┊ Online ┊ ┊ node3 ┊ SATELLITE ┊ 172.16.0.234:3366 (PLAIN) ┊ Online ┊ ╰────────────────────────────────────────────────────────╯ ====== 5.Storage pool 設定 ====== こちらも、linstor-controllerを起動しているnode1で実行する。 sdbでLVMを用意してlinstorのストレージプールに利用する。 pvcreate /dev/sdb vgcreate vg /dev/sdb lvcreate -l 100%FREE --thinpool vg/lvmthinpool linstor storage-pool create lvmthin node1 linstor-pool vg/lvmthinpool linstor storage-pool create lvmthin node2 linstor-pool vg/lvmthinpool linstor storage-pool create lvmthin node3 linstor-pool vg/lvmthinpool ===== storage-pool確認 ===== node1# linstor storage-pool list -p +-----------------------------------------------------------------------------------------------------------------------------+ | StoragePool | Node | Driver | PoolName | FreeCapacity | TotalCapacity | CanSnapshots | State | SharedName | |=============================================================================================================================| | DfltDisklessStorPool | node1 | DISKLESS | | | | False | Ok | | | DfltDisklessStorPool | node2 | DISKLESS | | | | False | Ok | | | DfltDisklessStorPool | node3 | DISKLESS | | | | False | Ok | | | linstor-pool | node1 | LVM_THIN | vg/lvmthinpool | 19.90 GiB | 19.96 GiB | True | Ok | | | linstor-pool | node2 | LVM_THIN | vg/lvmthinpool | 19.90 GiB | 19.96 GiB | True | Ok | | | linstor-pool | node3 | LVM_THIN | vg/lvmthinpool | 19.90 GiB | 19.96 GiB | True | Ok | | +-----------------------------------------------------------------------------------------------------------------------------+ ===== 1つVolumeを作ってみる ===== === TestVol01を作成 === 流れは - リソース定義を作成 - ボリューム定義を作成 - リソースを作成 linstor resource-definition create TestVol01 linstor volume-definition create TestVol01 1G linstor resource create TestVol01 -s linstor-pool --auto-place 3 たとえば、node2,node3にリソースを作成して、node1はディスクレスにする場合 linstor resource create node2 node3 TestVol01 -s linstor-pool linstor resource create node1 TestVol01 --diskless === 確認 === # linstor volume list -r TestVol01 +----------------------------------------------------------------------------------------------------+ | Node | Resource | StoragePool | VolNr | MinorNr | DeviceName | Allocated | InUse | State | |====================================================================================================| | node1 | TestVol01 | linstor-pool | 0 | 1002 | /dev/drbd1002 | 315 KiB | Unused | UpToDate | | node2 | TestVol01 | linstor-pool | 0 | 1002 | /dev/drbd1002 | 315 KiB | Unused | UpToDate | | node3 | TestVol01 | linstor-pool | 0 | 1002 | /dev/drbd1002 | 315 KiB | Unused | UpToDate | +----------------------------------------------------------------------------------------------------+ === ディスクを使ってみる === mkfs.xfs /dev/drbd1002 mount /dev/drbd1002 /mnt/ # df /mnt Filesystem 1K-blocks Used Available Use% Mounted on /dev/drbd1002 1042168 40604 1001564 4% /mnt === マウントしているnode1のInUseがInUseに変更して、ディスクを利用している事が分かる === # linstor volume list -r TestVol01 | sed 's/^/ /g' +----------------------------------------------------------------------------------------------------+ | Node | Resource | StoragePool | VolNr | MinorNr | DeviceName | Allocated | InUse | State | |====================================================================================================| | node1 | TestVol01 | linstor-pool | 0 | 1002 | /dev/drbd1002 | 11.00 MiB | InUse | UpToDate | | node2 | TestVol01 | linstor-pool | 0 | 1002 | /dev/drbd1002 | 11.00 MiB | Unused | UpToDate | | node3 | TestVol01 | linstor-pool | 0 | 1002 | /dev/drbd1002 | 11.00 MiB | Unused | UpToDate | +----------------------------------------------------------------------------------------------------+ === 削除 === umount /mnt linstor volume-definition delete TestVol01 0 linstor resource-definition delete TestVol01 ====== 6.冗長化構成 ====== linstorの情報は、/var/lib/linstorに入っているので、これをどのノードでも使えるように冗長化する。 drbd-reactor で/var/lib/linstorをマウントしてないと、linstor-controllerが起動しないようにする仕組みです。 これで、3つのノードどれかで、linstore-controllerが起動して、その他のlinstore-controllerは起動しないという設定が可能となります。 ===== linstor_dbボリュームの用意 ===== linstor resource-definition create linstor_db linstor resource-definition drbd-options --on-no-quorum=io-error linstor_db linstor resource-definition drbd-options --auto-promote=no linstor_db linstor volume-definition create linstor_db 200M linstor resource create linstor_db -s linstor-pool --auto-place 3 ==== もしlinstor-controllerが動いている場合は、disableにして停止 ==== systemctl disable --now linstor-controller ==== linstore_dbマウントするsystemd用意 ==== cat << EOF > /etc/systemd/system/var-lib-linstor.mount [Unit] Description=Filesystem for the LINSTOR controller [Mount] # you can use the minor like /dev/drbdX or the udev symlink What=/dev/drbd/by-res/linstor_db/0 Where=/var/lib/linstor EOF ==== linstor_dbをマウントしてlinstor-controller起動 ==== mv /var/lib/linstor{,.orig} mkdir /var/lib/linstor chattr +i /var/lib/linstor # only if on LINSTOR >= 1.14.0 drbdadm primary linstor_db mkfs.ext4 /dev/drbd/by-res/linstor_db/0 systemctl start var-lib-linstor.mount cp -r /var/lib/linstor.orig/* /var/lib/linstor systemctl start linstor-controller ===== drbd-reactor用意 ===== ※下記の手順は全てのノードで実行する。 ==== install ==== apt install drbd-reactor ==== 起動順のファイル作成 ==== cat << EOF > /etc/drbd-reactor.d/linstor_db.toml [[promoter]] id = "linstor_db" [promoter.resources.linstor_db] start = ["var-lib-linstor.mount", "linstor-controller.service"] EOF ==== 一度drbd-reactor再起動 ==== systemctl restart drbd-reactor systemctl enable drbd-reactor ===== linstor-satellite修正 ===== linstor_dbボリュームに変更を加えないように設定変更 # systemctl edit linstor-satellite [Service] Environment=LS_KEEP_RES=linstor_db ===== linstor-client.conf修正 ===== どのノードでlinstor-controllerが動いていても良いように、linstor-client.confを修正しておく。 # cat /etc/linstor/linstor-client.conf [global] controllers=node1,node2,node3 ===== 確認 ===== linstor_dbがPrimaryのノードでしか、linstor-controllerが起動しない事を確認 # linstor controller which linstor://node2 # drbdadm status linstor_db role:Secondary disk:UpToDate worker02 role:Primary peer-disk:UpToDate worker03 role:Secondary peer-disk:UpToDate node1# systemctl start linstor-controller.service A dependency job for linstor-controller.service failed. See 'journalctl -xe' for details. node2# systemctl stop linstor-controller.service node2# umount /var/lib/linstor node2# # drbdadm secondary linstor_db node1# drbdadm primary linstor_db node1# # systemctl start linstor-controller.service # linstor controller which linstor://node1 ===== 確認(正常な動作) ===== # cat /proc/drbd version: 9.0.32-1 (api:2/proto:86-121) # linstor --version linstor 1.13.0 # drbd-reactor --version drbd-reactor 0.6.0 # linstor controller which linstor://node02 ## ノード再起動や、drbd-reactorを停止した状態で、linstor-controllerが停止 node02:~# systemctl stop drbd-reactor.service node02:~# systemctl stop linstor-controller.service ## 即時に別のノードで、linstor-controllerが起動 node01:~# linstor controller which linstor://linstor-node01 ====== 7.Kubernetsから接続 ====== ==== 大前提条件 ==== Kubernetes helm インストール時下記の3つがlinstorインストールの前提の条件です。 - kubernetes controller からPodのIPに通信できる事 - Pod内から外部へ通信可能 - Pod内で名前解決可能 root@linstor-master:~# kubectl get pod alpine-test -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES alpine-test 1/1 Running 0 73s 10.224.1.2 linstor-node04 root@linstor-master:~# ping 10.224.1.2 -c 3 PING 10.224.1.2 (10.224.1.2) 56(84) bytes of data. 64 bytes from 10.224.1.2: icmp_seq=1 ttl=63 time=0.959 ms 64 bytes from 10.224.1.2: icmp_seq=2 ttl=63 time=0.679 ms 64 bytes from 10.224.1.2: icmp_seq=3 ttl=63 time=0.506 ms --- 10.224.1.2 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2019ms rtt min/avg/max/mdev = 0.506/0.714/0.959/0.186 ms root@linstor-master:~# kubectl exec -it alpine-test -- ping fl8.jp -c 3 PING fl8.jp (182.48.51.190): 56 data bytes 64 bytes from 182.48.51.190: seq=0 ttl=53 time=8.568 ms 64 bytes from 182.48.51.190: seq=1 ttl=53 time=8.715 ms 64 bytes from 182.48.51.190: seq=2 ttl=53 time=8.532 ms --- fl8.jp ping statistics --- 3 packets transmitted, 3 packets received, 0% packet loss round-trip min/avg/max = 8.532/8.605/8.715 ms ==== secret登録 ==== kubectl create secret docker-registry drbdiocred --docker-server=drbd.io \ --docker-username=[User] --docker-password=[Pass] ==== helm repository登録 ==== helm repo add linstor https://charts.linstor.io # helm repo list NAME URL linstor https://charts.linstor.io ==== linstor-opインストール ==== helm install linstor-op linstor/linstor \ --set operator.controller.enabled=false \ --set etcd.persistentVolume.enabled=false \ --set operator.etcd.enabled=false \ --set controllerEndpoint=http://172.16.0.65:3370 ==== 確認 ==== ちゃんとpodが起動してればOK # kubectl get pod NAME READY STATUS RESTARTS AGE alpine-test 1/1 Running 0 9h linstor-op-csi-controller-76d5bcfcb9-z2mrw 6/6 Running 0 9h linstor-op-csi-node-54wf6 3/3 Running 0 9h linstor-op-csi-node-9fcn9 3/3 Running 0 9h linstor-op-csi-node-rw4h5 3/3 Running 0 9h linstor-op-etcd-0 1/1 Running 0 9h linstor-op-ha-controller-6f9784f965-bqqcp 1/1 Running 0 9h linstor-op-ns-node-74zjb 0/2 Init:CrashLoopBackOff 111 (3m4s ago) 9h linstor-op-ns-node-ldc5q 0/2 Init:CrashLoopBackOff 111 (3m51s ago) 9h linstor-op-ns-node-m7hcm 0/2 Init:CrashLoopBackOff 111 (3m28s ago) 9h linstor-op-operator-7b9b9b685d-mnc8z 1/1 Running 0 9h ubuntu 1/1 Running 0 8h ubuntu-7c969d5f7d-lq96g 1/1 Running 0 8h ==== StorageClass作成 ==== Kubernetes から利用する為に、StorageClass作成 apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: # The name used to identify this StorageClass. name: linstor-basic-storage-class # The name used to match this StorageClass with a provisioner. # linstor.csi.linbit.com is the name that the LINSTOR CSI plug-in uses to identify itself provisioner: linstor.csi.linbit.com volumeBindingMode: WaitForFirstConsumer parameters: # LINSTOR will provision volumes from the drbdpool storage pool configured # On the satellite nodes in the LINSTOR cluster specified in the plug-in's deployment storagePool: "linstor-pool" resourceGroup: "linstor-basic-storage-class" # Setting a fstype is required for "fsGroup" permissions to work correctly. # Currently supported: xfs/ext4 csi.storage.k8s.io/fstype: xfs linstor.csi.linbit.com/autoPlace: "3" ==== PVC作成 ==== kind: PersistentVolumeClaim apiVersion: v1 metadata: name: linstor-volume-01 spec: storageClassName: linstor-basic-storage-class accessModes: - ReadWriteOnce resources: requests: storage: 3Gi === PVC作成した時点 === PVC作成した時点ではまだPVは作成してない。 # kubectl apply -f pvc.yaml persistentvolumeclaim/linstor-volume-01 created # kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE linstor-volume-01 Pending linstor-basic-storage-class 4s # kubectl get pv No resources found # linstor volume list -p +------------------------------------------------------------------------------------------+ | Node | Resource | StoragePool | VolNr | MinorNr | DeviceName | Allocated | InUse | State | |==========================================================================================| +------------------------------------------------------------------------------------------+ ==== PodからPV利用 ==== apiVersion: v1 kind: Pod metadata: name: ubuntu spec: containers: - image: ubuntu name: ubuntu command: [ "/bin/bash", "-c", "--" ] args: [ "while true; do sleep 30; done;" ] volumeMounts: - name: linstor-volume mountPath: /data ports: - containerPort: 80 volumes: - name: linstor-volume persistentVolumeClaim: claimName: "linstor-volume-01" === Pod作成すると、PVも作成される === kubectl apply -f ubutnu.yaml # kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pvc-c83e52e0-f8c7-447c-a3f2-8f01daaeb4c2 3Gi RWO Delete Bound default/linstor-volume-01 linstor-basic-storage-class 82s # kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE linstor-volume-01 Bound pvc-c83e52e0-f8c7-447c-a3f2-8f01daaeb4c2 3Gi RWO linstor-basic-storage-class 4m54s # linstor volume list -p +--------------------------------------------------------------------------------------------------------------------------------------------+ | Node | Resource | StoragePool | VolNr | MinorNr | DeviceName | Allocated | InUse | State | |============================================================================================================================================| | linstor-node04 | pvc-c83e52e0-f8c7-447c-a3f2-8f01daaeb4c2 | linstor-pool | 0 | 1000 | /dev/drbd1000 | 5.23 MiB | Unused | UpToDate | | linstor-node05 | pvc-c83e52e0-f8c7-447c-a3f2-8f01daaeb4c2 | linstor-pool | 0 | 1000 | /dev/drbd1000 | 4.61 MiB | Unused | UpToDate | | linstor-node06 | pvc-c83e52e0-f8c7-447c-a3f2-8f01daaeb4c2 | linstor-pool | 0 | 1000 | /dev/drbd1000 | 11.38 MiB | Unused | UpToDate | +--------------------------------------------------------------------------------------------------------------------------------------------+ === PVC削除 === PVCを削除すると、ちゃんとlinstorで削除されている。 # kubectl delete pod ubuntu pod "ubuntu" deleted # kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE linstor-volume-01 Bound pvc-06ac4732-f3f4-46fe-a0b6-6f58a9895cb2 3Gi RWO linstor-basic-storage-class 29m # kubectl delete pvc linstor-volume-01 persistentvolumeclaim "linstor-volume-01" deleted # linstor volume list -p +------------------------------------------------------------------------------------------+ | Node | Resource | StoragePool | VolNr | MinorNr | DeviceName | Allocated | InUse | State | |==========================================================================================| +------------------------------------------------------------------------------------------+ {{tag>Kuberneted DRBD}}