DockerのvolumuをQNAP上のISCSIへお引越しする話

## はじめに
いきなりタイトル詐欺のお知らせですが、DockerのvolumuをQNAPのISCSIへお引越しと記載している物の、正確にはサーバ上に新たにローカルディスクをくっつけて、そことQNAPのISCSIをRAID1させて、DockerのVolumeデータはそちらにお引越しとなります。
ちなみになんでこんな回りくどい構成にしているかというと、ただの<b>浪漫</b>です。

## 環境
環境はESXi上に構築しているUbuntuの最新版24.04のLTSを使用しています。
### バージョン情報
```shell:コマンド
root@vm-omsrv01:~# cat /etc/os-release
PRETTY_NAME="Ubuntu 24.04 LTS"
NAME="Ubuntu"
VERSION_ID="24.04"
VERSION="24.04 LTS (Noble Numbat)"
VERSION_CODENAME=noble
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=noble
LOGO=ubuntu-logo
```
<br>

肝心のディスクは枯渇の前兆が見え始めたので、早速対応していきます。
```shell:コマンド
root@vm-omsrv01:~# df -h /
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda2        49G   34G   13G  74% /
```
予め必要なパッケージのインストールをしておいてください。
```shell:コマンド
apt -y install parted mdadm
```


## 1.QNAP上でISCSIの作成

まずはQNAPの管理コンソールに管理者権限でログインし、「iSCSI & ファイバーチャネル」というアプリを立ち上げます。
![WS000002.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566232/3c3d1ca1-07b1-c1e3-7cb3-802efad26ea5.jpeg)
<br>

セットアップウィザードが立ち上がるので、次へをクリックします。
![WS000003.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566232/62070dae-05fe-71fc-2247-485773bdcc2b.jpeg)
<br>

続いてISCSIの名前を付ける項目です。後々の作業でサーバから確認するのでわかりやすい名前に変えておいた方がよいでしょう。
![WS000005.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566232/da19f454-3743-618b-8c67-0dc1fca7b537.jpeg)
<br>
パスワード設定はここでは無しとしています。
必要な方は設定してください。

![WS000006.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566232/bfee4b53-3cd3-85de-683a-4c59681c2235.jpeg)
<br>
インターフェースについては、任意のものを使用してください。

![WS000008.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566232/770298ef-5bab-bb7d-5d42-f8c82043af55.jpeg)
<br>
内容に問題なければ適用をクリックしてください。

![WS000009.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566232/fbc454e5-bd0e-7972-2f67-fdaef6a7f673.jpeg)
<br>
続いてストレージサイズの割り当てになります。

![WS000012.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566232/d111a214-f578-d23e-15ba-17151dea2619.jpeg)
<br>
必要なサイズを割り当ててください。ここでは100GBとしています。

![WS000013.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566232/b129b4eb-5628-ec00-0d10-497a0f65bba6.jpeg)
<br>
内容に問題なければ完了をクリックします。

![WS000014.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566232/d8be588d-b4a0-797e-68f8-18fde18baa92.jpeg)
<br>
5分ほど経つと作成が完了します。
以上がQNAPのNAS上からISCSIを作成する方法でした。

![WS000016.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566232/aae75514-d6f6-be4a-037e-9a04d8c9accc.jpeg)

## 2.サーバに新しいディスクの追加作業
続いて、サーバにISCSIと同様に新しいディスクを100GB追加しました。
```shell:コマンド
root@vm-omsrv01:~# fdisk -l /dev/sdb
ディスク /dev/sdb: 100 GiB, 107374182400 バイト, 209715200 セクタ
Disk model: Virtual disk
単位: セクタ (1 * 512 = 512 バイト)
セクタサイズ (論理 / 物理): 512 バイト / 512 バイト
I/O サイズ (最小 / 推奨): 512 バイト / 512 バイト
```
<br>

早速ディスクのフォーマット作業を行っていきます。
まずはローカルに追加したディスクのフォーマットを行ってきます。
今回100GB追加しましたが、興味本位で半分の50GBのみ割り当てを行っていきます。

```shell:コマンド
root@vm-omsrv01:~# parted --script /dev/sdb "mklabel gpt"
root@vm-omsrv01:~# parted --script /dev/sdb "mkpart primary 0GB 50GB"
root@vm-omsrv01:~# parted --script /dev/sdb "set 1 raid on"
root@vm-omsrv01:~# fdisk -l /dev/sdb*
ディスク /dev/sdb: 100 GiB, 107374182400 バイト, 209715200 セクタ
Disk model: Virtual disk
単位: セクタ (1 * 512 = 512 バイト)
セクタサイズ (論理 / 物理): 512 バイト / 512 バイト
I/O サイズ (最小 / 推奨): 512 バイト / 512 バイト
ディスクラベルのタイプ: gpt
ディスク識別子: 849D01CD-8E18-4CFA-8709-0C6F9FB2B72C

デバイス   開始位置 最後から   セクタ サイズ タイプ
/dev/sdb1      2048 97656831 97654784  46.6G Linux RAID


ディスク /dev/sdb1: 46.57 GiB, 49999249408 バイト, 97654784 セクタ
単位: セクタ (1 * 512 = 512 バイト)
セクタサイズ (論理 / 物理): 512 バイト / 512 バイト
I/O サイズ (最小 / 推奨): 512 バイト / 512 バイト
```
<br>

続いてISCSIのディスクも作業していきます。
フォーマット系のコマンドはローカルディスクの時と同じですが、ISCSIの認識作業もあるのでまずはそちらから実施していきます。

```shell:コマンド
root@vm-omsrv01:~# # ターゲットを検出
root@vm-omsrv01:~# iscsiadm -m discovery -t sendtargets -p 192.168.179.15 | grep 192.168.179.15
192.168.179.15:3260,1 omsrv-vol
root@vm-omsrv01:~#
root@vm-omsrv01:~# # 対象のISCSIへログイン
root@vm-omsrv01:~# iscsiadm -m node -T omsrv-vol -p 192.168.179.15 --login
Logging in to [iface: default, target: omsrv-vol, portal: 192.168.179.15,3260]
Login to [iface: default, target: omsrv-vol, portal: 192.168.179.15,3260] successful.
root@vm-omsrv01:~#
root@vm-omsrv01:~# # ログイン確認
root@vm-omsrv01:~# iscsiadm -m session -o show
tcp: [1] 192.168.179.15:3260,1 omsrv-vol (non-flash)
root@vm-omsrv01:~#
root@vm-omsrv01:~# # 対象ISCSIへの自動起動設定確認(事前)
root@vm-omsrv01:~# iscsiadm -m node -T omsrv-vol -o show | grep node.startup
node.startup = manual
node.startup = manual
node.startup = manual
root@vm-omsrv01:~#
root@vm-omsrv01:~# # 対象ISCSIへの自動起動設定の反映
root@vm-omsrv01:~# iscsiadm -m node -T omsrv-vol -o update -n node.startup -v automatic
root@vm-omsrv01:~#
root@vm-omsrv01:~# # 対象ISCSIへの自動起動設定確認(事後)
root@vm-omsrv01:~# iscsiadm -m node -T omsrv-vol -o show | grep node.startup
node.startup = automatic
node.startup = automatic
node.startup = automatic
```
<br>
続いてディスクのフォーマットをしていきます。

```shell:コマンド
root@vm-omsrv01:~# parted --script /dev/sdc "mklabel gpt"
root@vm-omsrv01:~# parted --script /dev/sdc "mkpart primary 0GB 50GB"
root@vm-omsrv01:~# parted --script /dev/sdc "set 1 raid on"
root@vm-omsrv01:~# fdisk -l /dev/sdc*
ディスク /dev/sdc: 100 GiB, 107374182400 バイト, 209715200 セクタ
Disk model: iSCSI Storage
単位: セクタ (1 * 512 = 512 バイト)
セクタサイズ (論理 / 物理): 512 バイト / 512 バイト
I/O サイズ (最小 / 推奨): 512 バイト / 8388608 バイト
ディスクラベルのタイプ: gpt
ディスク識別子: E00E3A9A-FFED-483F-B5EE-41806108716D

デバイス   開始位置 最後から   セクタ サイズ タイプ
/dev/sdc1     16384 97648639 97632256  46.6G Linux RAID


ディスク /dev/sdc1: 46.55 GiB, 49987715072 バイト, 97632256 セクタ
単位: セクタ (1 * 512 = 512 バイト)
セクタサイズ (論理 / 物理): 512 バイト / 512 バイト
I/O サイズ (最小 / 推奨): 512 バイト / 8388608 バイト
```

<br>
「/proc/partitions」を確認して、デバイスが認識されているか見てみます。

```shell:コマンド
# Linuxシステムで現在認識されているすべてのディスクデバイスとそのパーティションを表示
root@vm-omsrv01:~# cat /proc/partitions | egrep "major|sd[bc]"
major minor  #blocks  name
   8       16  104857600 sdb
   8       17   48827392 sdb1
   8       32  104857600 sdc
   8       33   48816128 sdc1
```

## 3.RAID1の構築
2本のディスクが出来ましたので、早速RAID1の構築をしていきます。
「sdb1」と「sdc1」のデバイスを使用して「md0」というraid1を作っていきます。
「cat /proc/mdstat」を実行した際に、syncが完了していれば構築完了のようです。

```shell:コマンド
root@vm-omsrv01:~# mdadm --create /dev/md0 --level=raid1 --raid-devices=2 /dev/sdb1 /dev/sdc1
mdadm: Note: this array has metadata at the start and
    may not be suitable as a boot device.  If you plan to
    store '/boot' on this device please ensure that
    your boot-loader understands md/v1.x metadata, or use
    --metadata=0.90
Continue creating array? y
mdadm: Defaulting to version 1.2 metadata
mdadm: array /dev/md0 started.
root@vm-omsrv01:~#
root@vm-omsrv01:~# cat /proc/mdstat
Personalities : [raid1]
md0 : active raid1 sdc1[1] sdb1[0]
      48782336 blocks super 1.2 [2/2] [UU]
      [>....................]  resync =  2.0% (985472/48782336) finish=11.3min speed=70390K/sec

unused devices: <none>
root@vm-omsrv01:~#
root@vm-omsrv01:~# cat /proc/mdstat
Personalities : [raid1]
md0 : active raid1 sdc1[1] sdb1[0]
      48782336 blocks super 1.2 [2/2] [UU]

unused devices: <none>
```
<br>
ディスクの同期が完了したら、早速フォーマットしてOSにマウントしましょう。
今回はext4でフォーマットしていきます。

```shell:コマンド
root@vm-omsrv01:~# mkfs.ext4 /dev/md0
mke2fs 1.47.0 (5-Feb-2023)
Creating filesystem with 12195584 4k blocks and 3049648 inodes
Filesystem UUID: ea2b8a20-c34e-41b8-8263-cb819b601dd8
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
        4096000, 7962624, 11239424

Allocating group tables: done
Writing inode tables: done
Creating journal (65536 blocks): done
Writing superblocks and filesystem accounting information: done
root@vm-omsrv01:~#
root@vm-omsrv01:~# mount /dev/md0 /mnt/docker_volume
root@vm-omsrv01:~#
root@vm-omsrv01:~# df -h /mnt/docker_volume
Filesystem      Size  Used Avail Use% Mounted on
/dev/md0         46G   24K   44G   1% /mnt/docker_volume
```
<br>
手動でマウントできることを確認したら、fstabに記載し自動マウントさせるようにしましょう。

```shell:コマンド
root@vm-omsrv01:~# umount /mnt/docker_volume
root@vm-omsrv01:~# df -h /mnt/docker_volume
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda2        49G   34G   13G  74% /
root@vm-omsrv01:~#
root@vm-omsrv01:~# blkid | grep md
/dev/md0: UUID="ea2b8a20-c34e-41b8-8263-cb819b601dd8" BLOCK_SIZE="4096" TYPE="ext4"
root@vm-omsrv01:~#
root@vm-omsrv01:~# echo "/dev/disk/by-uuid/ea2b8a20-c34e-41b8-8263-cb819b601dd8 /mnt/docker_volume  ext4 defaults 0 0" >> /etc/fstab
root@vm-omsrv01:~# systemctl daemon-reload
root@vm-omsrv01:~# mount -a
root@vm-omsrv01:~# df -h /mnt/docker_volume
Filesystem      Size  Used Avail Use% Mounted on
/dev/md0         46G   24K   44G   1% /mnt/docker_volume
```

## 4.DockerのVolume領域の引っ越し
新しいraidの領域もできたので、早速DockerのVolume領域のデータを移行しましょう。
まずはDocker関連のサービスを停止します。

```shell:コマンド
root@vm-omsrv01:~# systemctl stop docker
root@vm-omsrv01:~# systemctl stop docker.socket
```

rsyncで同期させる前の状態を確認します。
```shell:コマンド
root@vm-omsrv01:/# ls -l /var/lib/docker /mnt/docker_volume
/mnt/docker_volume:
合計 16
drwx------ 2 root root 16384  8月 24 01:24 lost+found

/var/lib/docker:
合計 60
drwx--x--x   5 root root  4096  8月  2 16:11 buildkit
drwx--x---  13 root root  4096  8月 23 23:05 containers
-rw-------   1 root root    36  8月  2 15:46 engine-id
drwx------   3 root root  4096  8月  2 15:46 image
drwxr-x---   3 root root  4096  8月  2 15:46 network
drwx--x--- 171 root root 20480  8月 23 23:05 overlay2
drwx------   4 root root  4096  8月  2 15:46 plugins
drwx------   2 root root  4096  8月 23 13:44 runtimes
drwx------   5 root root  4096  8月 23 13:45 swarm
drwx------   2 root root  4096  8月 23 13:45 tmp
drwx-----x  11 root root  4096  8月 23 13:44 volumes
```
<br>
rsyncで同期させていきます。標準出力で大量にファイル名が出るので注意してください。

```shell:コマンド
root@vm-omsrv01:~# rsync -ahv /var/lib/docker/ /mnt/docker_volume/
xxx/
xxx/_data/
xxx/_data/config

sent 18.80G bytes  received 7.01M bytes  15.26M bytes/sec
total size is 18.77G  speedup is 1.00
```
<br>

事後の状態を見るときちんと同期されていそうです。
```shell:コマンド
root@vm-omsrv01:~# ls -l /var/lib/docker /mnt/docker_volume
/mnt/docker_volume:
合計 76
drwx--x--x   5 root root  4096  8月  2 16:11 buildkit
drwx--x---  13 root root  4096  8月 23 23:05 containers
-rw-------   1 root root    36  8月  2 15:46 engine-id
drwx------   3 root root  4096  8月  2 15:46 image
drwx------   2 root root 16384  8月 24 01:24 lost+found
drwxr-x---   3 root root  4096  8月  2 15:46 network
drwx--x--- 171 root root 20480  8月 23 23:05 overlay2
drwx------   4 root root  4096  8月  2 15:46 plugins
drwx------   2 root root  4096  8月 23 13:44 runtimes
drwx------   5 root root  4096  8月 23 13:45 swarm
drwx------   2 root root  4096  8月 23 13:45 tmp
drwx-----x  11 root root  4096  8月 23 13:44 volumes

/var/lib/docker:
合計 60
drwx--x--x   5 root root  4096  8月  2 16:11 buildkit
drwx--x---  13 root root  4096  8月 23 23:05 containers
-rw-------   1 root root    36  8月  2 15:46 engine-id
drwx------   3 root root  4096  8月  2 15:46 image
drwxr-x---   3 root root  4096  8月  2 15:46 network
drwx--x--- 171 root root 20480  8月 23 23:05 overlay2
drwx------   4 root root  4096  8月  2 15:46 plugins
drwx------   2 root root  4096  8月 23 13:44 runtimes
drwx------   5 root root  4096  8月 23 13:45 swarm
drwx------   2 root root  4096  8月 23 13:45 tmp
drwx-----x  11 root root  4096  8月 23 13:44 volumes
```
<br>

最後にDockerのデータ領域のデフォルトの向き先を変更するため、「/etc/docker/daemon.json」を修正します。

```diff_shell:コマンド
root@vm-omsrv01:~# cat /etc/docker/daemon.json
{
+  "data-root": "/mnt/docker_volume"
}
```


```shell:コマンド
root@vm-omsrv01:~# systemctl start docker.socket
root@vm-omsrv01:~# systemctl start docker.service
root@vm-omsrv01:~# systemctl status docker
● docker.service - Docker Application Container Engine
     Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; preset: enabled)
    Drop-In: /etc/systemd/system/docker.service.d
             mqoverride.conf
     Active: active (running) since Sat 2024-08-24 01:57:55 JST; 23s ago
TriggeredBy: ● docker.socket
       Docs: https://docs.docker.com
   Main PID: 136453 (dockerd)
      Tasks: 9
     Memory: 26.9M (peak: 27.2M)
        CPU: 241ms
     CGroup: /system.slice/docker.service
             mq136453 /usr/bin/dockerd
```
<br>
lsやdocker psで確認してみると、新しい向き先の領域のファイルが更新され、dockerのプロセスも無事以前の状態を引き継いで起動したようです！

```shell:コマンド
root@vm-omsrv01:~# ls -l /var/lib/docker /mnt/docker_volume
/mnt/docker_volume:
合計 76
drwx--x--x   5 root root  4096  8月  2 16:11 buildkit
drwx--x---  13 root root  4096  8月 23 23:05 containers
-rw-------   1 root root    36  8月  2 15:46 engine-id
drwx------   3 root root  4096  8月  2 15:46 image
drwx------   2 root root 16384  8月 24 01:24 lost+found
drwxr-x---   3 root root  4096  8月  2 15:46 network
drwx--x--- 171 root root 20480  8月 24 10:50 overlay2
drwx------   4 root root  4096  8月  2 15:46 plugins
drwx------   2 root root  4096  8月 24 10:50 runtimes
drwx------   5 root root  4096  8月 24 10:50 swarm
drwx------   2 root root  4096  8月 24 10:50 tmp
drwx-----x  11 root root  4096  8月 24 10:50 volumes

/var/lib/docker:
合計 60
drwx--x--x   5 root root  4096  8月  2 16:11 buildkit
drwx--x---  13 root root  4096  8月 23 23:05 containers
-rw-------   1 root root    36  8月  2 15:46 engine-id
drwx------   3 root root  4096  8月  2 15:46 image
drwxr-x---   3 root root  4096  8月  2 15:46 network
drwx--x--- 171 root root 20480  8月 23 23:05 overlay2
drwx------   4 root root  4096  8月  2 15:46 plugins
drwx------   2 root root  4096  8月 23 13:44 runtimes
drwx------   5 root root  4096  8月 23 13:45 swarm
drwx------   2 root root  4096  8月 23 13:45 tmp
drwx-----x  11 root root  4096  8月 23 13:44 volumes
root@vm-omsrv01:~#
root@vm-omsrv01:~# docker ps
CONTAINER ID   IMAGE                                COMMAND                   CREATED        STATUS                             PORTS                                                                                                                   NAMES
9d5cb5642f7c   openvpn-openvpn-udp                  "/usr/local/bin/set-…"   18 hours ago   Up 10 seconds                      0.0.0.0:1194->1194/udp, :::1194->1194/udp                                                                               openvpn-udp
8eeaf130261b   jc21/nginx-proxy-manager:latest      "/init"                   20 hours ago   Up 13 seconds                      0.0.0.0:80-81->80-81/tcp, :::80-81->80-81/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp                                    nginx-proxy
f3cb3a49c05c   jc21/mariadb-aria:latest             "/scripts/run.sh"         20 hours ago   Up 10 seconds                      3306/tcp                                                                                                                nginx-proxy-database
bc531f0aa2cd   gitlab/gitlab-ce:latest              "/assets/wrapper"         20 hours ago   Up 10 seconds (health: starting)   0.0.0.0:2422->22/tcp, :::2422->22/tcp, 0.0.0.0:9080->80/tcp, :::9080->80/tcp, 0.0.0.0:9443->443/tcp, :::9443->443/tcp   gitlab-web-1
ea222ed93033   4km3/dnsmasq                         "/usr/sbin/dnsmasq -k"    20 hours ago   Up 9 seconds                       0.0.0.0:53->53/tcp, 0.0.0.0:53->53/udp, :::53->53/tcp, :::53->53/udp                                                    dnsmasq-dnsmasq-1
134c3389c1bf   kindest/node:v1.29.0                 "/usr/local/bin/entr…"   2 weeks ago    Up 10 seconds                      127.0.0.1:37429->6443/tcp                                                                                               kind-control-plane
```

## 最後に
今回実施してみたのは結構試験的な所もあり、恐らくNASのHDDや1000ASE-Tが後々ボトルネックになりそうな気もしているので、完全SSD化や2.5GBASE-Tなどのハードウェアの補強も必要だと感じる今日この頃でした。
早く冬のボーナス欲しい…。

## 参考サイト
・RAID 1 を構成する
https://www.server-world.info/query?os=Ubuntu_24.04&p=raid1

・iSCSI イニシエーターの設定
https://www.server-world.info/query?os=Ubuntu_24.04&p=iscsi&f=3