DRBDの練習 4 〜LVM / DRBD / LVM〜
DRBDの下位デバイスと、DRBDのデバイスにLVMを使ってみる。
DRBDの公式ドキュメントを参考に作業する。
まずはDRBDの下位デバイスとして使う論理ボリューム vg01/r0
を作成する。
drbd1# pvcreate /dev/vdb Physical volume "/dev/vdb" successfully created. drbd1# pvs PV VG Fmt Attr PSize PFree /dev/vda5 drbd1-vg lvm2 a-- <4.52g 0 /dev/vdb vg01 lvm2 a-- <10.00g <9.51g drbd1# vgcreate vg01 /dev/vdb Volume group "vg01" successfully created drbd1# vgs vg01 VG #PV #LV #SN Attr VSize VFree vg01 1 1 0 wz--n- <10.00g <9.51g drbd1# lvcreate -n r0 -L 500M vg01 Logical volume "r0" created. drbd1# lvs vg01 LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert r0 vg01 -wi-ao---- 500.00m
全く同じことをdrbd2
でも行う。
続いて、DRBDの設定ファイルを編集する。
disk
には先ほど作成した論理ボリューム /dev/vg01/r0
を指定する。
resource r0 { on drbd1 { device /dev/drbd1; disk /dev/vg01/r0; address 192.168.122.166:7776; meta-disk internal; } on drbd2 { device /dev/drbd1; disk /dev/vg01/r0; address 192.168.122.45:7776; meta-disk internal; } }
以前の記事と同様に、リソースの初回有効化を行う。
drbd1# drbdadm create-md r0 drbd1# drbdadm up r0
ここまではdrbd2
でも実行する。
ここからはdrbd1
だけで実行。
drbd1# drbdadm new-current-uuid --clear-bitmap r0/0 drbd1# drbdadm primary r0
これで、論理ボリューム vg01/r0
が、DRBDで同期される。
次に、今使えるようになった/dev/drbd1
をLVMのPVとして、その上にVG vg_drbd
, LV lv0
を作る。
drbd1# pvcreate /dev/drbd1 Physical volume "/dev/drbd1" successfully created. drbd1# pvs PV VG Fmt Attr PSize PFree /dev/drbd1 vg_drbd lvm2 a-- 496.00m 496.00m /dev/vda5 drbd1-vg lvm2 a-- <4.52g 0 /dev/vdb vg01 lvm2 a-- <10.00g <9.51g drbd1# vgcreate vg_drbd /dev/drbd1 Volume group "vg_drbd" successfully created drbd1# vgs vg_drbd VG #PV #LV #SN Attr VSize VFree vg_drbd 1 0 0 wz--n- 496.00m 496.00m drbd1# lvcreate -n lv0 -L 200M vg_drbd Logical volume "lv0" created. drbd1# lvs vg_drbd LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert lv0 vg_drbd -wi-a----- 200.00m
今作った`lv0'にファイルシステムを作り、マウントして、ファイルを作成してみる。
drbd1# mkfs.ext4 /dev/vg_drbd/lv0 mke2fs 1.46.2 (28-Feb-2021) Discarding device blocks: done Creating filesystem with 204800 1k blocks and 51200 inodes Filesystem UUID: 2d5a478b-f48d-475d-9f3a-3feff10c6fb8 Superblock backups stored on blocks: 8193, 24577, 40961, 57345, 73729 Allocating group tables: done Writing inode tables: done Creating journal (4096 blocks): done Writing superblocks and filesystem accounting information: done drbd1# mount /dev/vg_drbd/lv0 /mnt drbd1# echo 'Test File' > /mnt/test drbd1# ls /mnt lost+found test drbd1# cat /mnt/test Test File
アクティブ系をdrbd1
からdrbd2
に切り換えてみる。
まずdrbd1
で、lv0
をアンマウントし、vg_drbd
を非アクティブ化して、セカンダリに降格する。
drbd1# umount /mnt drbd1# vgchange -a n vg_drbd 0 logical volume(s) in volume group "vg_drbd" now active drbd1# drbdadm secondary r0 drbd1# drbdadm status r0 r0 role:Secondary disk:UpToDate peer role:Secondary replication:Established peer-disk:UpToDate
続いてdrbd2
をプライマリに昇格する。
drbd2# drbdadm primary r0 drbd2# drbdadm status r0 r0 role:Primary disk:UpToDate peer role:Secondary replication:Established peer-disk:UpToDate drbd2# pvs PV VG Fmt Attr PSize PFree /dev/drbd1 vg_drbd lvm2 a-- 496.00m 296.00m /dev/vda5 drbd2-vg lvm2 a-- <4.52g 0 /dev/vdb vg01 lvm2 a-- <10.00g <9.51g drbd2# vgs vg_drbd VG #PV #LV #SN Attr VSize VFree vg_drbd 1 1 0 wz--n- 496.00m 296.00m drbd2# lvs vg_drbd LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert lv0 vg_drbd -wi------- 200.00m
ちゃんとdrbd1
で作ったPV, VG, LVが見えている。
drbd2
で、vg_drbd
をアクティブ化し、マウントしてファイルを確認。
drbd2# vgchange -a y vg_drbd 1 logical volume(s) in volume group "vg_drbd" now active drbd2# mount /dev/vg_drbd/lv0 /mnt drbd2# ls /mnt lost+found test drbd2# cat /mnt/test Test File
DRBDで入れ子LVが同期できた!
DRBDの練習 3 〜障害対応での切換〜
前回に続いてDRBDの練習。
障害が発生したときの切換をシミュレーションしてみる。
現時点での状態を確認。
drbd1# drbdadm status r0 r0 role:Primary disk:UpToDate peer role:Secondary replication:Established peer-disk:UpToDate drbd2# drbdadm status r0 r0 role:Secondary disk:UpToDate peer role:Secondary replication:Established peer-disk:UpToDate
プライマリがdrbd1
で、セカンダリがdrbd2
。
drbd1
で、テスト用にdd
を使ってファイルに書き込みつづける。
drbd1# dd if=/dev/zero of=/mnt/test bs=1 oflag=sync status=progress 507 bytes copied, 3 s, 0.2 kB/s
この状態で、KVMのホスト環境から強制的にdrbd1を停止してみる。
host$ virsh destroy drbd1 Domain drbd1 destroyed
drbd2
で、状態を確認。
drbd2# drbdadm status r0 r0 role:Secondary disk:UpToDate peer connection:Connecting
接続が切れている。
そこで、drbd2
をプライマリに昇格してみる。
drbd2# drbdadm primary r0 drbd2# drbdadm status r0 r0 role:Primary disk:UpToDate peer connection:Connecting
プライマリに昇格できたので、マウントして中身を確認。
drbd2# mount /dev/drbd1 /mnt drbd2# ls /mnt lost+found test drbd2# ls -l /mnt/test -rw-r--r-- 1 root root 656 Jun 27 23:25 /mnt/test
一旦アンマウントしてセカンダリに降格。
drbd2# umount /mnt drbd2# drbdadm secondary r0 drbd2# drbdadm status r0 r0 role:Secondary disk:UpToDate peer connection:Connecting
そして、drbd1
を起動してみる。
host$ virsh start --console drbd1 drbd1# drbdadm status r0 r0 role:Secondary disk:UpToDate peer role:Secondary replication:Established peer-disk:UpToDate
drbd1
をプライマリに昇格して、マウントする。
drbd1# drbdadm primary r0 drbd1# mount /dev/drbd1 /mnt drbd1# drbdadm status r0 r0 role:Primary disk:UpToDate peer role:Secondary replication:Established peer-disk:UpToDate drbd1# ls /mnt lost+found test drbd1# ls -l /mnt/test -rw-r--r-- 1 root root 656 Jun 27 23:25 /mnt/test
今回のテスト条件では、問題なく同期が取れていたことが確認できた!
DRBDの練習 2 〜アクティブ系の切換〜
前回に続いてDRBDの練習。
計画的にアクティブ系を切り替える状況をシミュレーションしてみる。ただし、ここではサービス無停止までは考慮しない。
現時点での状態を確認。
drbd1# drbdadm status r0 r0 role:Primary disk:UpToDate peer role:Secondary replication:Established peer-disk:UpToDate drbd2# drbdadm status r0 r0 role:Secondary disk:UpToDate peer role:Secondary replication:Established peer-disk:UpToDate
プライマリがdrbd1
で、セカンダリがdrbd2
。
テスト用にファイルを作る。
/dev/drbd1
がdrbd1
で/mnt
にmount
されている。
drbd1# echo 'Test File 1' > /mnt/test1 drbd1# ls /mnt lost+found test1 drbd1# cat /mnt/test1 Test File 1
まずは、現在プライマリのdrbd1
をシャットダウンしてみる。
drbd1# shutdown -P now
この状態でdrbd2
でステータスを確認。
drbd2# drbdadm status r0 r0 role:Secondary disk:UpToDate peer connection:Connecting
peer connection
がConnecting
となっていて接続が切れていることがわかる。
この状態でdrbd2
をプライマリに昇格してみる。
drbd2# drbdadm primary r0 drbd2# drbdadm status r0 r0 role:Primary disk:UpToDate peer connection:Connecting
プライマリに昇格できたので、マウントして中身を確認。
drbd2# mount /dev/drbd1 /mnt drbd2# ls /mnt lost+found test1 drbd2# cat /mnt/test1 Test File 1
先ほど作ったファイルが存在している。
さらにファイルを作成してみる。
drbd2# echo 'Test File 2' > /mnt/test2 drbd2# ls /mnt lost+found test1 test2 drbd2# cat /mnt/test2 Test File 2
この状態でdrbd1
を起動してみる。
host$ virsh start --console drbd1 drbd1# drbdadm status r0 r0 role:Secondary disk:UpToDate peer role:Primary replication:Established peer-disk:UpToDate
drbd1
がセカンダリになっている。
drbd2
でアンマウントして、セカンダリに戻す。
drbd2# umount /mnt drbd2# drbdadm secondary r0 drbd2# drbdadm status r0 r0 role:Secondary disk:UpToDate peer role:Secondary replication:Established peer-disk:UpToDate
そして、drbd1
をプライマリに昇格する。
drbd1# drbdadm primary r0 drbd1# drbdadm status r0 r0 role:Primary disk:UpToDate peer role:Secondary replication:Established peer-disk:UpToDate
マウントして中身を確認。
drbd1# mount /dev/drbd1 /mnt drbd1# ls /mnt lost+found test1 test2 drbd1# cat /mnt/test2 Test File 2
drbd2
で作成したファイルも確認できた!
DRBDの練習 1 〜DRBDのシステム構築〜
DRBD (Distributed Replicated Block Device) を使ってディスクをミラーリングしたシステムを作ってみる。
The DRBD User’s Guideを参考に作業する。
日本語版もあるが、訳が少し怪しいところがあるので、なるべく英語版を参照することにする。
テスト環境としてKVM上にDebian bullseyeのVMを2台作る。 以前の自動インストールの記事を参照。
host$ virt-install --name drbd1 --memory 4096 --vcpus 1 --location $PWD/debian-bullseye-DI-rc1-amd64-netinst.iso --os-variant debiantesting --disk path=drbd1-vda.img,size=5,format=qcow2 --disk path=drbd1-vdb.img,size=10,format=qcow2 --network network=default --graphics none --serial pty --console pty --initrd-inject preseed.cfg --extra-args 'console=ttyS0,115200n8 serial hostname=drbd1 netcfg/get_ipaddress=192.168.122.129 netcfg/get_nameservers=192.168.122.1' host$ virt-install --name drbd2 --memory 4096 --vcpus 1 --location $PWD/debian-bullseye-DI-rc1-amd64-netinst.iso --os-variant debiantesting --disk path=drbd2-vda.img,size=5,format=qcow2 --disk path=drbd2-vdb.img,size=10,format=qcow2 --network network=default --graphics none --serial pty --console pty --initrd-inject preseed.cfg --extra-args 'console=ttyS0,115200n8 serial hostname=drbd2 netcfg/get_ipaddress=192.168.122.130 netcfg/get_nameservers=192.168.122.1'
OSはvda
にインストールして、10 GiBのvdb
は手つかずのまま置いておく。
ホスト名とIPアドレスはマニュアル設定する。
ここからはVM上での作業。
一番最初に、DRBDパッケージをインストールして、有効化する。
Debianの場合
# apt install drbd-utils # systemctl enable drbd
DRBDの設定ファイルを編集する。 両方のホストで全く同じ内容にする必要がある。
/etc/drbd.d/global_common.conf
は書き換えなくても使えるが、今回は次のように、レプリケーションのモードに「プロトコルB」を指定した。
common { net { protocol B; } }
プロトコルBとは、プライマリノードでの書き込みについて、レプリケーションパケットが対向ノードに届いた時点で書き込み完了とするというもので、
両方のノードに同時に電源障害が起き、かつ、プライマリノードのデータストアに回復不能な破壊があった場合には、最後の書き込みが失われるかもしれない
とのこと (参考)。
続いて、リソース設定ファイル /etc/drbd.d/r0.res
を作成する。
resource r0 { device /dev/drbd1; disk /dev/vdb; meta-disk internal; on drbd1 { address 192.168.122.129:7789; } on drbd2 { address 192.168.122.130:7789; } }
今回はdisk
に、2番目の仮想ディスクvdb
全体を使う。
IPアドレスは事前に確認しておく。ポート番号は、使われていなければ何でも構わない。
設定ファイルの詳細はマニュアルを参照のこと。
定義したリソース r0
について、はじめて有効化する場合は、最初にデバイスのメタデータを作成する。
drbd1# drbdadm create-md r0
次に、リソース r0
を有効化する。
drbd1# drbdadm up r0
リソース r0
のステータスを確認してみる。
drbd1# drbdadm status r0 r0 role:Secondary disk:Inconsistent peer connection:Connecting
この段階ではInconsistent
となるが問題ない。
drbd2
でも全く同じことを行い、
再びステータスを確認してみる。
drbd1# drbdadm status r0 r0 role:Secondary disk:Inconsistent peer role:Secondary replication:Established peer-disk:Inconsistent
依然としてInconsistent
だが、replication
はEstablished
になっている。
ここまでで、ひとまずリソースr0
が準備できたので、サービスを起動する。
drbd1# systemctl start drbd
既に下位デバイスに同期したい内容が書かれている場合には初回のフル同期が必要だが、今回は新しい(仮想)ディスクを使っていて、初回にフル同期する必要はないので、強制的に同期状態に変える。
drbd1# drbdadm new-current-uuid --clear-bitmap r0
この処理は片方のホストだけでやればよい。
再度ステータスを確認してみる。
drbd1# drbdadm status r0 r0 role:Secondary disk:UpToDate peer role:Secondary replication:Established peer-disk:UpToDate
drbd2
で確認しても、UpToDate
になっている。
しかし、どちらのホストもSecondary
になっている。
そこで、書き込みを行いたい側のホストで、プライマリに昇格する。
drbd1# drbdadm primary r0 drbd1# drbdadm status r0 r0 role:Primary disk:UpToDate peer role:Secondary replication:Established peer-disk:UpToDate
drbd2
でもステータスを確認してみる。
drbd2# drbdadm status r0 r0 role:Secondary disk:UpToDate peer role:Primary replication:Established peer-disk:UpToDate
drbd1
がプライマリ、drbd2
がセカンダリとして同期されている。
DRBDで作られたデバイスの状態を確認してみる。
drbd1# fdisk -l /dev/drbd1 Disk /dev/drbd1: 10 GiB, 10737053696 bytes, 20970808 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes
プライマリのdrbd1
では、ちゃんとディスクデバイスとして見えている。
drbd2# fdisk -l /dev/drbd1 fdisk: cannot open /dev/drbd1: Wrong medium type
セカンダリのdrbd2
だと怒られた。
プライマリのdrbd1
で /dev/drbd1
にファイルシステムを作って、マウントする。
drbd1# mkfs.ext4 /dev/drbd1 mke2fs 1.46.2 (28-Feb-2021) Discarding device blocks: done Creating filesystem with 2621351 4k blocks and 655360 inodes Filesystem UUID: bd340ca5-5981-4ba6-8bf3-94c61c16b7b4 Superblock backups stored on blocks: 32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632 Allocating group tables: done Writing inode tables: done Creating journal (16384 blocks): done Writing superblocks and filesystem accounting information: done drbd1# mount /dev/drbd1 /mnt
書き込み性能をdd
を使って簡単にテストしてみる。
drbd1# dd if=/dev/zero of=/tmp/test bs=1M count=1024 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB, 1.0 GiB) copied, 0.6066 s, 1.8 GB/s drbd1# dd if=/dev/zero of=/mnt/test bs=1M count=1024 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB, 1.0 GiB) copied, 1.58761 s, 676 MB/s
DRDBを使っていない/tmp
への書き込みに比べて約4割ほどの速度。
同期されていることを確認する。
まずdrbd1
をセカンダリに降格する。
drbd1# umount /mnt drbd1# drbdadm secondary r0 drbd1# drbdadm status r0 r0 role:Secondary disk:UpToDate peer role:Secondary replication:Established peer-disk:UpToDate
次にdrbd2
をプライマリに昇格する。
drbd2# drbdadm primary r0 drbd2# drbdadm status r0 r0 role:Primary disk:UpToDate peer role:Secondary replication:Established peer-disk:UpToDate
マウントしてファイルを確認。
drbd2# mount /dev/drbd1 /mnt drbd2# ls /mnt/ lost+found test
先ほどの性能テストで作られたファイルが存在している。
test
ファイルを削除して、セカンダリに戻す。
drbd2# rm /mnt/test drbd2# umount /mnt drbd2# drbdadm secondary r0 drbd2# drbdadm status r0 r0 role:Secondary disk:UpToDate peer role:Secondary replication:Established peer-disk:UpToDate
そして再びdrbd1
をプライマリに昇格して中身を確認。
drbd1# drbdadm primary r0 drbd1# drbdadm status r0 r0 role:Primary disk:UpToDate peer role:Secondary replication:Established peer-disk:UpToDate drbd1# mount /dev/drbd1 /mnt drbd1# ls /mnt/ lost+found
DRBDで2ホスト間のディスクが同期できた!
Fedora CoreOSのインストール練習 4 〜podの自動起動〜
前回作ったKubernetesマニフェストで作ったpodをIgnitionで自動起動するように、Fedora CoreOSインストールしてみる。
まずは、Butane config wp-pod.bu
を用意する。
variant: fcos version: 1.3.0 passwd: users: - name: core ssh_authorized_keys: - (ssh公開鍵) systemd: units: - name: wp-pod.service enabled: true contents: | [Unit] Description=Play WordPress pod After=network-online.target Wants=network-online.target [Service] Type=oneshot RemainAfterExit=yes ExecStartPre=-/bin/podman pod kill wp-pod ExecStartPre=-/bin/podman pod rm wp-pod ExecStartPre=/bin/podman build -t pod-wordpress:latest /var/home/wp-pod ExecStart=/bin/podman play kube /var/home/wp-pod/wp-pod.yaml ExecStop=/bin/podman pod stop wp-pod [Install] WantedBy=multi-user.target storage: files: - path: /var/home/wp-pod/Dockerfile contents: inline: | FROM docker.io/library/wordpress:latest ENV WORDPRESS_DB_NAME='wp' WORDPRESS_DB_HOST='127.0.0.1' WORDPRESS_DB_USER='wordpress' WORDPRESS_DB_PASSWORD='wordpress-password' - path: /var/home/wp-pod/wp-pod.yaml contents: inline: | apiVersion: v1 kind: Pod metadata: labels: app: wp-pod name: wp-pod spec: containers: - name: web image: localhost/pod-wordpress:latest ports: - containerPort: 80 hostPort: 80 protocol: TCP securityContext: allowPrivilegeEscalation: true capabilities: drop: - CAP_MKNOD - CAP_NET_RAW - CAP_AUDIT_WRITE privileged: false readOnlyRootFilesystem: false seLinuxOptions: {} - name: db image: docker.io/library/mariadb:latest env: - name: MYSQL_ROOT_PASSWORD value: mysql-root-password - name: MYSQL_DATABASE value: wp - name: MYSQL_USER value: wordpress - name: MYSQL_PASSWORD value: wordpress-password securityContext: allowPrivilegeEscalation: true capabilities: drop: - CAP_MKNOD - CAP_NET_RAW - CAP_AUDIT_WRITE privileged: false readOnlyRootFilesystem: false seLinuxOptions: {} volumeMounts: - mountPath: /var/lib/mysql name: wp-mysql-pvc restartPolicy: Always volumes: - name: wp-mysql-pvc persistentVolumeClaim: claimName: wp-mysql
pod
を自動起動させるsystemdサービスwp-pod.service
を定義している。
podman play kube
はpodが起動するとコマンドが終了するので、 Type=oneshot
とRemainAfterExit=yes
を指定する。
ExecStartPre
で独自コンテナイメージをビルドさせている。
Butane config wp-pod.bu
をIgnition config wp-pod.ign
に変換する。
host$ docker run -i --rm quay.io/coreos/butane:release < wp-pod.bu > wp-pod.ign
生成されたwp-pod.ign
を使ってFedora CoreOSをインストールする。
インストールが終了したらログインして、podが起動するまで少し待ってから、podの起動を確認してみる。
$ systemctl status wp-pod.service ● wp-pod.service - Play WordPress pod Loaded: loaded (/etc/systemd/system/wp-pod.service; enabled; vendor preset> Active: active (exited) since Wed 2021-06-16 08:08:23 UTC; 6s ago Process: 1944 ExecStartPre=/bin/podman pod kill wp-pod (code=exited, status> Process: 2000 ExecStartPre=/bin/podman pod rm wp-pod (code=exited, status=1> Process: 2026 ExecStartPre=/bin/podman build -t pod-wordpress:latest /var/h> Process: 2210 ExecStart=/bin/podman play kube /var/home/wp-pod/wp-pod.yaml > Main PID: 2210 (code=exited, status=0/SUCCESS) Tasks: 6 (limit: 2280) Memory: 1.0G CGroup: /system.slice/wp-pod.service ├─2429 /usr/bin/conmon --api-version 1 -c a0017f7e8221da59cd409527> ├─2435 /usr/bin/conmon --api-version 1 -c 4d71c1b65740a07e2b8fca3f> └─2463 /usr/bin/conmon --api-version 1 -c 7b4edae69fe2dbbace2b2ab2> Jun 16 08:08:23 localhost podman[2210]: 2021-06-16 08:08:23.270676058 +0000 UTC> Jun 16 08:08:23 localhost podman[2210]: 2021-06-16 08:08:23.460813506 +0000 UTC> Jun 16 08:08:23 localhost podman[2210]: 2021-06-16 08:08:23.466814111 +0000 UTC> Jun 16 08:08:23 localhost podman[2210]: 2021-06-16 08:08:23.466855117 +0000 UTC> Jun 16 08:08:23 localhost podman[2210]: Pod: Jun 16 08:08:23 localhost podman[2210]: 2b836abed04bc8069f5186b64b01b19d3cc2bee> Jun 16 08:08:23 localhost podman[2210]: Containers: Jun 16 08:08:23 localhost podman[2210]: 7b4edae69fe2dbbace2b2ab2c44dd01b3d50ab9> $ sudo podman pod ps POD ID NAME STATUS CREATED INFRA ID # OF CONTAINERS 2b836abed04b wp-pod Running 36 seconds ago a0017f7e8221 3 $ sudo podman ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a0017f7e8221 k8s.gcr.io/pause:3.5 39 seconds ago Up 23 seconds ago 0.0.0.0:80->80/tcp 2b836abed04b-infra 7b4edae69fe2 localhost/pod-wordpress:latest apache2-foregroun... 39 seconds ago Up 23 seconds ago 0.0.0.0:80->80/tcp wp-pod-web 4d71c1b65740 docker.io/library/mariadb:latest mysqld 23 seconds ago Up 23 seconds ago 0.0.0.0:80->80/tcp wp-pod-db
無事wp-pod
が起動している。
ブラウザでもWordPressが起動していることを確認。
いちおうサービス停止も確認しておく。
$ sudo systemctl stop wp-pod.service $ sudo podman pod ps POD ID NAME STATUS CREATED INFRA ID # OF CONTAINERS 2b836abed04b wp-pod Exited 3 minutes ago a0017f7e8221 3 $ sudo podman ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Kubernetesマニフェストを使ってPodmanでpodを自動起動するようにFedora CoreOSを構成できた!
Podmanで独自コンテナイメージとボリュームを使うpodの作成
Fedora CoreOS上でpodを動かすのが目標だけど、その前にまず手動でpodを作って動かしてみる。
Podmanのコマンドリファレンスを参照しながら作業を進める。
まずは独自コンテナイメージを作成する。
今回はサンプルとしてWordPressに環境変数を設定しただけのコンテナにする。
最初にDockerfileを作成。
$ cat <<EOF > Dockerfile FROM docker.io/library/wordpress:latest ENV WORDPRESS_DB_NAME='wp' WORDPRESS_DB_HOST='127.0.0.1' \ WORDPRESS_DB_USER='wordpress' WORDPRESS_DB_PASSWORD='wordpress-password' EOF
続いてpodmanでpod-wordpress:latest
というタグを付けてビルド。
$ sudo podman build -t pod-wordpress:latest . STEP 1: FROM docker.io/library/wordpress:latest Getting image source signatures Copying blob 69692152171a done Copying blob ac1fe7c6d966 done Copying blob 9b4ca5ae9dfa done Copying blob 5b26fc9ce030 done Copying blob 2040822db325 done Copying blob 3492f4769444 done Copying blob 1dec05775a74 done Copying blob 77107a42338e done Copying blob f58e4093c52a done Copying blob d32715f578d3 done Copying blob 7a73fb2558ce done Copying blob 75e2da936ffe done Copying blob 759622df3a7b done Copying blob 667b573fcff7 done Copying blob c2f98ef02756 done Copying blob 50e11300b0a6 done Copying blob de37513870b9 done Copying blob f25501789abc done Copying blob 0cf8e3442952 done Copying blob d45ce270a7e6 done Copying blob 534cdc5a6ea6 done Copying config c2dd1984ad done Writing manifest to image destination Storing signatures STEP 2: ENV WORDPRESS_DB_NAME='wp' WORDPRESS_DB_HOST='127.0.0.1' WORDPRESS_DB_USER='wordpress' WORDPRESS_DB_PASSWORD='wordpress-password' STEP 3: COMMIT pod-wordpress:latest --> ed133c15e36 ed133c15e364cb72b5a93626a43e38316237eb291c5f9f18bec647db111ad58e
次に、wp-pod
という名前のpodを手動で作成する。
$ sudo podman pod create -n wp-pod -p 80:80 29004378ddfbf605c11e8a916066336627d14e8d9fd82d2ac7c6d898d3790503 $ sudo podman pod ps POD ID NAME STATUS CREATED INFRA ID # OF CONTAINERS 29004378ddfb wp-pod Created 16 seconds ago 8bc8772c5324 1
MariaDBの/var/lib/mysql
を永続化するためのボリュームを作成。
$ sudo podman volume create wp-mysql wp-mysql
MariaDBコンテナwp-pod-db
をwp-pod
内で実行。
$ sudo podman run -d --restart=always --pod=wp-pod -e MYSQL_ROOT_PASSWORD='mysql-root-password' -e MYSQL_DATABASE='wp' -e MYSQL_USER='wordpress' -e MYSQL_PASSWORD='wordpress-password' -v wp-mysql:/var/lib/mysql --name wp-pod-db docker.io/library/mariadb Trying to pull docker.io/library/mariadb:latest... Getting image source signatures Copying blob 345e3491a907 done Copying blob 5e9250ddb7d0 done Copying blob 57671312ef6f done Copying blob 2d512e2ff778 done Copying blob b846f4f4774a done Copying blob 57c1a7dc2af9 done Copying blob 55edbf0f673e done Copying blob 82d8723e99d8 done Copying blob 66409f940bd2 done Copying blob c34793730ad6 done Copying blob 8f1925a0d734 done Copying blob 72904fb5fd0b done Copying config eff6290896 done Writing manifest to image destination Storing signatures 824fdae25e81491d0b04f0d30cde7131cd986d47e522e6078f0c84c65ac505ac
続いて、先ほどビルドしたコンテナイメージpod-wordpress:latest
をwp-pod-web
コンテナとしてwp-pod
内で実行。
$ sudo podman run -d --restart=always --pod=wp-pod --name wp-pod-web localhost/pod-wordpress:latest 31f5d2b2a9c16d6a945242c363c5209ddea7c8563c2f720265f0a7bc4c95c6a2
wp-pod
でWordPressが稼働したはず。
podとコンテナの状態を確認。
$ sudo podman pod ps POD ID NAME STATUS CREATED INFRA ID # OF CONTAINERS 29004378ddfb wp-pod Running 4 minutes ago 8bc8772c5324 3 $ sudo podman ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8bc8772c5324 k8s.gcr.io/pause:3.5 4 minutes ago Up 50 seconds ago 0.0.0.0:80->80/tcp 29004378ddfb-infra 824fdae25e81 docker.io/library/mariadb:latest mysqld 50 seconds ago Up 50 seconds ago 0.0.0.0:80->80/tcp wp-pod-db 31f5d2b2a9c1 localhost/pod-wordpress:latest apache2-foregroun... 32 seconds ago Up 33 seconds ago 0.0.0.0:80->80/tcp wp-pod-web
期待通りに動いている。
実際に別ホストから接続してみる。
remote$ curl -v http://192.168.152.2:80/ * Trying 192.168.152.2:80... * TCP_NODELAY set * Connected to 192.168.152.2 (192.168.152.2) port 80 (#0) > GET / HTTP/1.1 > Host: 192.168.152.2 > User-Agent: curl/7.68.0 > Accept: */* > * Mark bundle as not supporting multiuse < HTTP/1.1 302 Found < Date: Tue, 15 Jun 2021 08:23:13 GMT < Server: Apache/2.4.38 (Debian) < X-Powered-By: PHP/7.4.20 < Expires: Wed, 11 Jan 1984 05:00:00 GMT < Cache-Control: no-cache, must-revalidate, max-age=0 < X-Redirect-By: WordPress < Location: http://192.168.152.2/wp-admin/install.php < Content-Length: 0 < Content-Type: text/html; charset=UTF-8 < * Connection #0 to host 192.168.152.2 left intact
問題なく動いているみたい。 実際にブラウザでアクセスするとちゃんとWordPressの初期設定画面が表示された!
ここまででpodを手動で動かすことはできたけど、Ignitionでインストールすることを考えると、明示的に実行するコマンドはなるべく減らしてシンプルにしたい。
そこで、Kubernetesのマニフェストファイルを作ってpodを自動構成するようにしてみる。
マニフェストファイルはゼロから自力で作るのは手間なので、先ほど作ったpodの構成をpodmanで出力させる。
$ sudo podman generate kube wp-pod > wp-pod.yaml
こうやって出力されたファイルには、コンテナのデフォルト設定なども含まれているので、編集して不要な設定を削ってやる。
整理した後のマニフェストファイルwp-pod.yaml
がこれ。
apiVersion: v1 kind: Pod metadata: labels: app: wp-pod name: wp-pod spec: containers: - name: web image: localhost/pod-wordpress:latest ports: - containerPort: 80 hostPort: 80 protocol: TCP securityContext: allowPrivilegeEscalation: true capabilities: drop: - CAP_MKNOD - CAP_NET_RAW - CAP_AUDIT_WRITE privileged: false readOnlyRootFilesystem: false seLinuxOptions: {} - name: db image: docker.io/library/mariadb:latest env: - name: MYSQL_ROOT_PASSWORD value: mysql-root-password - name: MYSQL_DATABASE value: wp - name: MYSQL_USER value: wordpress - name: MYSQL_PASSWORD value: wordpress-password securityContext: allowPrivilegeEscalation: true capabilities: drop: - CAP_MKNOD - CAP_NET_RAW - CAP_AUDIT_WRITE privileged: false readOnlyRootFilesystem: false seLinuxOptions: {} volumeMounts: - mountPath: /var/lib/mysql name: wp-mysql-pvc restartPolicy: Always volumes: - name: wp-mysql-pvc persistentVolumeClaim: claimName: wp-mysql
マニフェストファイルでのpod作成を試すために、さっき作ったwp-pod
を一旦消す。
$ sudo podman pod stop wp-pod 29004378ddfbf605c11e8a916066336627d14e8d9fd82d2ac7c6d898d3790503 $ sudo podman pod rm wp-pod 29004378ddfbf605c11e8a916066336627d14e8d9fd82d2ac7c6d898d3790503 $ sudo podman pod ps POD ID NAME STATUS CREATED INFRA ID # OF CONTAINERS $ sudo podman ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES $ sudo podman volume rm wp-mysql wp-mysql $ sudo podman volume ls
そして、マニフェストファイルwp-pod.yaml
を使ってpodを再生。
$ sudo podman play kube ./wp-pod.yaml Trying to pull docker.io/library/mariadb:latest... Getting image source signatures Copying blob b846f4f4774a skipped: already exists Copying blob 345e3491a907 skipped: already exists Copying blob 57671312ef6f skipped: already exists Copying blob 5e9250ddb7d0 skipped: already exists Copying blob 2d512e2ff778 skipped: already exists Copying blob 57c1a7dc2af9 skipped: already exists Copying blob 66409f940bd2 skipped: already exists Copying blob 82d8723e99d8 skipped: already exists Copying blob 55edbf0f673e skipped: already exists Copying blob c34793730ad6 skipped: already exists Copying blob 8f1925a0d734 [--------------------------------------] 0.0b / 0.0b Copying blob 72904fb5fd0b [--------------------------------------] 0.0b / 0.0b Copying config eff6290896 done Writing manifest to image destination Storing signatures Pod: 5c7741db9e2e4c8ae2a253f6568aa61b018de93d032be7c4377ce91f2dca30f4 Containers: f83e8b9be5fec747f59a86e5a9d1fae0ac4b6fc3e44f18e1c79d35f9dc8dae55 44914870bab7da18a1cbd87e7adcc2169a88ea2d1b83f580d41440b30d92976e
きちんと実行されているか確認。
$ sudo podman pod ps POD ID NAME STATUS CREATED INFRA ID # OF CONTAINERS 5c7741db9e2e wp-pod Running 20 seconds ago c0b859f1cf3e 3 $ sudo podman ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c0b859f1cf3e k8s.gcr.io/pause:3.5 27 seconds ago Up 23 seconds ago 0.0.0.0:80->80/tcp 5c7741db9e2e-infra f83e8b9be5fe localhost/pod-wordpress:latest apache2-foregroun... 27 seconds ago Up 22 seconds ago 0.0.0.0:80->80/tcp wp-pod-web 44914870bab7 docker.io/library/mariadb:latest mysqld 23 seconds ago Up 23 seconds ago 0.0.0.0:80->80/tcp wp-pod-db $ sudo podman volume ls DRIVER VOLUME NAME local 59378a373f5dcd7e01a03425bfeec23c6632c203918ead50a4d81eb1b49054bc local wp-mysql
ブラウザでもWordPressが動いていることを確認した。
Podmanで独自コンテナとボリュームを使うpodを構成できた!
Fedora CoreOSのインストール練習 4 〜ディレクトリ配置〜
今回はFedora CoreOSというよりはIgnitionとButaneの話。
Ignitionで手元のディレクトリに下を丸ごとFedora CoreOS上に配置してみる。
まずは配置するディレクトリ構造を作る。
$ mkdir test $ mkdir test/dir1 $ mkdir test/dir2 $ echo 'Test file 1' > test/dir1/file1 $ dd if=/dev/urandom of=test/dir1/file2 bs=512 count=1 $ chmod +x test/dir1/file2 $ echo 'Test file 3' > test/dir2/file3 $ chmod 600 test/dir2/file3
test1
は普通のテキストファイル、test2
は実行権限を付けたバイナリファイル、test3
はパーミッションを600
に設定したテキストファイルを作成している。
作ったディレクトリ構造を確認。
$ ls -lR test/ test/: total 8 drwxr-xr-x 2 user group 4096 Jun 12 17:08 dir1 drwxr-xr-x 2 user group 4096 Jun 12 17:08 dir2 test/dir1: total 8 -rw-r--r-- 1 user group 12 Jun 12 17:07 file1 -rwxr-xr-x 1 user group 512 Jun 12 17:17 file2 test/dir2: total 4 -rw------- 1 user group 12 Jun 12 17:08 file3
次に、作ったtest
ディレクトリの下を配置するためのButan configファイルtree-embed.bu
を、
Butan configの仕様を参考に作成する。
ここでは、手元のtest配下を/var/home/core/target
に配置するように指定している。
variant: fcos version: 1.3.0 passwd: users: - name: core password_hash: (ハッシュ) storage: trees: - path: /var/home/core/target local: test
そして、作ったButan configをIgnition configファイルに変換する。
$ docker run -i --rm -v $PWD:/data quay.io/coreos/butane:release --files-dir /data < tree-embed.bu > tree-embed.ign
生成されたtree-embed.ign
の中身を整形したものがこちら。
{ "ignition": { "version": "3.2.0" }, "passwd": { "users": [ { "name": "core", "passwordHash": "(ハッシュ)" } ] }, "storage": { "files": [ { "path": "/var/home/core/target/dir1/file1", "contents": { "source": "data:,Test%20file%201%0A" }, "mode": 420 }, { "path": "/var/home/core/target/dir1/file2", "contents": { "source": "data:;base64,wTMSSxSVQHkEHeJdfqBKd8e9E0TyQReFqkTeXPydW7oCy83Em8GAOUGDDYeuTpZBZVOIcVkuFowrKeWpmnXIsGOt5g1CmWEDSw9dKbziFs7ASonrNaoVTmcl3k18Y45/oaIOmQx+i9/YZ9rAofZbaeIuqiCTputWB8COCoFZEEP1iRLOgw5AIM5Z2XcZD6b8fp5++jwu0h3VWdKW+xN9NHxQIPzz4J4fIK8Jpw5Lcrkzl0Yu0SAqV0xLgeQWtwNrmvihzxFqjhpqCE1QOb4zPsavfvTOUdbGzd7bW595n0MIBvvqcV0PqgX4OkjihqBwYhWECaakNVy3BVFtTgif4IPpgc2Qm8JMy7rpJwNFCPBleTf8Sys+LsXoXvyimDe2vRo0whKjSkWGO+TfoYl618g5p4gmWERVzC/oq35E2egcbN9Fy8gqssheJQwfVNQQ7viDLRdc7fY/i8zDBm+GGgsgrCMsuqUKerechAnw6UqNKtX10mu5KuQIWfZSGZKzb1bzAHCX4wl/DdWs4LIXnZfPe5F1gnWkC52eSNBFfNvzZqIaLIuZWHpAR4VnVfUNW0BRbgNgSWMkTt+7b0VWHpeMSADdDvEGCiUg9V4E6B60qLxTwFMj2oRdLzdErf5/OkXzzWXI7GafCBOmiWJvz1Lpbne74gJlrHKDd705iYQ=" }, "mode": 493 }, { "path": "/var/home/core/target/dir2/file3", "contents": { "source": "data:,Test%20file%203%0A" }, "mode": 420 } ] } }
テキストファイルはそのまま、バイナリファイルはbase64エンコードされて埋め込まれている。ファイルの中身がIgnition configに埋め込まれるので、当然ながら配置元ファイルの内容を変更したら、(Butane configを変更していなくても)Ignition configを変換し直す必要がある。
modeの420
は0644
を、493
は0755
を整数値にしたもの。
Butane configの仕様に書かれている通り、実行可能ファイルは0755
、それ以外は0644
に設定されている。
tree-embed.ign
を使ってFedora CoreOSをインストールして確認してみる。
$ ls -lR /var/home/core/target target/: total 0 drwxr-xr-x. 2 root root 32 Jun 12 08:33 dir1 drwxr-xr-x. 2 root root 19 Jun 12 08:33 dir2 target/dir1: total 8 -rw-r--r--. 1 root root 12 Jun 12 08:33 file1 -rwxr-xr-x. 1 root root 512 Jun 12 08:33 file2 target/dir2: total 4 -rw-r--r--. 1 root root 12 Jun 12 08:33 file3
手元のディレクトリ構造がFedora CoreOSに配置できた!