■ はじめに
こんにちは、SREの平です。前回の 『Raspberry PiでOpenStackクラスターを作ってみよう』 ( https://developer.so-tech.co.jp/entry/2022/08/23/113000 ) の続編となります。
32GBのSDカードを使っておうちクラウドを作成しているので、インスタンス(以下VM)のストレージボリュームもこのSDから切り出して使いました。 しかしこの方法の問題として、容量が小さく速度も遅いのと、VMと物理サーバーが紐づいているので、VMを他の物理サーバーにマイグレーションするにはスナップショットを取ったりと面倒です。
対策は簡単で、ボリュームを仮想化すればいいだけなのですが、ちょうど私の自宅にはSynologyのNASがありましたので、これをNFS共有サーバーとして使い、VMのボリュームをSDカードからNFSに変更するというのを、1つ目にやってみたいと思います。
2つ目に、このNFS共有のボリュームをbootableで作成してVMにアタッチするのをterraformで作成し、このVMでS3互換のMinIOをdockerで立ち上げて AWS CLI でバケットの作成や操作をしてみます。
最後に、terraformのバックエンドをさきほど作成したVMに向けて、構成管理ファイルを永続化するサンプルを実行して、今回は終わりにします。
■ この資料におけるIPアドレス
最初にこの資料で使うIPをまとめておきます。
項目 | 内容 |
---|---|
10.234.15.11 | Openstack の Controller |
10.234.15.12~1x | Openstack の Compute |
10.234.15.250 | Synology NAS |
192.168.4.33 | MinIOをインストールするVM |
■ Synologyでボリュームを仮想化する
SynologyのNASで、openstack用のvolume2を作成します。
自宅の共有ディレクトリ用に元々Volumeを1つ切っていました。 今回実験用に別のVolume(Volume2)を切ります。 また今後別の目的でVolume3も使う予定ですので、切り直しされる方は小さくてもいいのでVolumeを3つ用意しておくと便利かもしれません。なおQNAPやフリーのNASソフトでもやることはほとんど一緒なのでその場合は適宜読み替えていただけますでしょうか。
メインメニュー > ストレージマネージャ > ストレージ > ボリュームの作成
項目 内容 ストレージプール 空きがあるプールをプルダウンで選択する 割り当てられたサイズを修正 1000GB など適宜 ボリュームの説明 for_openstack など適宜 これで『ボリューム2』が作成されました。
共有フォルダを作成します。
コンパネ > 共有フォルダ > 『作成』を押す
項目 内容 名前 c-volumes 説明 for_cinder-volume 場所 ボリューム2 など上記で作成したボリュームを選択する マイネットワークでこの共有フォルダを非表示にする ■(チェックする) 無許可のユーザーにサブフォルダとファイルを見せない □(チェックしない) ごみ箱を有効にする □(チェックしない) この共有フォルダを暗号化する □(チェックしない) ローカルユーザー(プルダウンで選択する) guest ■(読み取り/書き込みにチェックする) ローカルグループ(プルダウンで選択する) administrators ■(読み取り/書き込みにチェックする) users ■(読み取り/書き込みにチェックする) 作成した共有フォルダにNFSの権限を付与します。
作成したフォルダ > 『編集』を押す 『NFS権限』タブを押し、『作成』ボタンを押す。
項目 内容 ホスト名またはIP * 特権 読み取り/書き込み squash 全ユーザーをguestにマップ セキュリティ sys 非同期を有効にする ■(チェックする) 非優先ポートからの接続を許可する(1024以上のポート) □(チェックしない) マウントしたサブフォルダへのアクセスを許可する □(チェックしない) これでマウントパス『synas01:/volume2/c-volumes』のNFS共有が作成されました。
■ Openstackでcinderの導入
Openstackにcinderをインストールします。不明な点は公式マニュアルも参照しながら進めるといいと思います。
cf. cinder-volume https://docs.openstack.org/cinder/zed/install/index-ubuntu.html
cf. NFSドライバー https://docs.openstack.org/cinder/zed/configuration/block-storage/drivers/nfs-volume-driver.html
================ ここからコントローラー ================
まずControllerにSSHし、cinderユーザー等を作成します。
※ここでのパスワードは cinder123 にしました。
sudo -i mysql -u root -p CREATE DATABASE cinder; GRANT ALL PRIVILEGES ON cinder.* TO 'cinder'@'localhost' IDENTIFIED BY 'cinder123'; GRANT ALL PRIVILEGES ON cinder.* TO 'cinder'@'%' IDENTIFIED BY 'cinder123'; exit exit
admin環境変数を読み込みます。
. admin-openrc
cinderユーザーの作成等をします。
※ここでのパスワードは cinder123 にしました。
openstack user create --domain default --password-prompt cinder openstack role add --project service --user cinder admin openstack service create --name cinderv3 --description "OpenStack Block Storage" volumev3
APIエンドポイントを作成します。
openstack endpoint create --region RegionOne volumev3 public http://pios01:8776/v3/%\(project_id\)s openstack endpoint create --region RegionOne volumev3 internal http://pios01:8776/v3/%\(project_id\)s openstack endpoint create --region RegionOne volumev3 admin http://pios01:8776/v3/%\(project_id\)s
コンポーネントの導入と起動に必要な設定を行います。
sudo -i apt install cinder-api cinder-scheduler cinder-volume nfs-common sed -i -e 's*# Domain = localdomain*Domain = local*' /etc/idmapd.conf
/etc/nova/nova.conf に以下を追加します。
[cinder] os_region_name = RegionOne
nfsサーバーの設定ファイルを記述します /etc/cinder/nfs_shares
10.234.15.250:/volume2/c-volumes
設定ファイルを記述します /etc/cinder/cinder.conf
[DEFAULT] rootwrap_config = /etc/cinder/rootwrap.conf api_paste_confg = /etc/cinder/api-paste.ini iscsi_helper = lioadm volume_name_template = volume-%s volume_group = cinder-volumes verbose = True state_path = /var/lib/cinder lock_path = /var/lock/cinder volumes_dir = /var/lib/cinder/volumes enabled_backends = nfs # for glance glance_api_servers = http://pios01:9292 # for cinder-scheduler transport_url = rabbit://openstack:rabbitmq123@pios01 auth_strategy = keystone my_ip = 10.234.15.11 # for cinder-volume enabled_backends = nfs #default_volume_type = nfs [database] connection = mysql+pymysql://cinder:cinder123@pios01/cinder [keystone_authtoken] www_authenticate_uri = http://pios01:5000 auth_url = http://pios01:5000 memcached_servers = pios01:11211 auth_type = password project_domain_name = default user_domain_name = default project_name = service username = cinder password = cinder123 [oslo_concurrency] lock_path = /var/lib/cinder/tmp [nfs] volume_driver = cinder.volume.drivers.nfs.NfsDriver nfs_shares_config = /etc/cinder/nfs_shares nfs_mount_point_base = $state_path/mnt
データ入力を行います。
su -s /bin/sh -c "cinder-manage db sync" cinder
再起動し、永続化します。
systemctl restart nova-api.service systemctl restart cinder-scheduler.service systemctl restart cinder-volume.service systemctl restart apache2.service systemctl enable cinder-scheduler.service systemctl enable cinder-volume.service
ボリュームタイプを作成します。
exit . admin-openrc openstack volume type create nfs openstack volume type list
================ ここからコンピュート ================
コンピュートで作業します。コンピュートが複数台の場合、それら全部で行います。
※ "nvme-cli" はログにwarningが出てしまうとき追加します。
sudo -i apt install nfs-common sed -i -e 's*# Domain = localdomain*Domain = local*' /etc/idmapd.conf
/etc/nova/nova.conf に以下を追加します。
[cinder] os_region_name = RegionOne
novaを再起動します。
systemctl restart nova-compute.service
正常性確認:Openstackのコンソールでbootableなボリュームを作成してみる
VMのローカルディスクをNFS経由のボリュームにしてみます。
プロジェクト>ボリューム>ボリューム>ボリュームの作成 を押す
項目 | 内容 |
---|---|
ボリューム名 | vol-test 等 |
ボリュームソース | イメージ |
イメージをソースとして使用する | ubuntu-22.04 等 |
種別 | nfs |
サイズ(GiB) | 10 (GiB) 等(必要に応じて) |
アベイラビリティーゾーン | nova |
グループ | グループなし |
正常性確認:VMにアタッチして起動してみる
プロジェクト>コンピュート>インスタンス インスタンスの起動 を押す
項目 | 内容 |
---|---|
インスタンス名 | test2 等 |
アベイラビリティゾーン | nova |
インスタンス数 | 1 |
ブートソース | ボリューム |
インスタンス時にボリュームを削除 | はい(必要に応じてだがDB等はいいえを選択するのが望ましい) |
ボリューム | vol-test 等 |
フレーバー | micro 等 |
ネットワーク | taira-network |
セキュリティグループ | default |
キーペア | 適当なものを選択 |
カスタマイズスクリプト | 適当なものを入力 |
無事に起動できて、SSHでログインし、ボリュームからbootしているのが確認できたらここまでの設定は大丈夫です。 確認のために作ったVMは削除してください。
■ terraformをインストールし、VMを作成する
普段使っているPCや作業用VMなどにterraformをインストールします。 今回はtfenvを使って(たまたま手元のバージョンがこれだったという理由だけですが)0.12.31をインストールします。
git clone https://github.com/tfutils/tfenv.git ~/.tfenv echo 'export PATH="$HOME/.tfenv/bin:$PATH"' >> ~/.bashrc source ~/.bashrc tfenv install 0.12.31 tfenv use 0.12.31
MinIOを作成するmain.tfを用意します。
なお、ユーザー名やキーペア名は適宜。ネットワークID、ubuntuのイメージIDなどのIDは環境ごとによって異なりますので、これも適宜書き換えてください。main.tfの下に各ID確認コマンドを記述しておきます。
cloud-configの中でssh_authorized_keysも貼っていますが、そちらも適宜書き換えてください。
# 認証情報を記述します。 provider "openstack" { user_name = "taira" tenant_name = "taira-project" password = "taira123" auth_url = "http://10.234.15.11:5000/v3/" } # 固定IP用のポートを作成します。 resource "openstack_networking_port_v2" "port_minio" { name = "port_minio" network_id = "c4bffb81-530e-438a-9f6b-c9b783b2394e" # ネットワークIDを指定します admin_state_up = "true" fixed_ip { subnet_id = "f53aaea3-1a79-481a-a163-6e83a4b29b42" # サブネットIDを指定します ip_address = "192.168.4.33" # インスタンスに割り当てるIPv4アドレスを指定します } } # ボリュームの作成をします。ポート作成後にボリュームを作成するのはVMがポートを認識できるようにするための時間稼ぎです。 resource "openstack_blockstorage_volume_v3" "vol-minio" { name = "vol-minio" size = 100 # ボリュームのサイズをGB単位で指定します volume_type = "nfs" # ボリュームのタイプを指定します image_id = "ca70fb5c-79ec-4ff5-b7b7-7f5e864fa3e2" # ここではubuntuのイメージIDを指定しています depends_on = [openstack_networking_port_v2.port_minio] } # インスタンスの作成をします。 resource "openstack_compute_instance_v2" "vm-minio" { name = "vm-minio" image_name = "ubuntu-22.04" # インスタンスに使用するイメージ名を指定します flavor_name = "micro" # インスタンスに使用するフレーバー名を指定します key_pair = "キーペア名を書いてください" # インスタンスに使用するキーペアの名前を指定します block_device { uuid = openstack_blockstorage_volume_v3.vol-minio.id # ボリュームIDを指定します source_type = "volume" # ボリュームをインスタンスにアタッチするための設定です destination_type = "volume" # ボリュームをインスタンスにアタッチするための設定です boot_index = 0 # ボリュームをブートデバイス(dev/vda)に指定します delete_on_termination = true # インスタンス削除時にボリュームを削除するかどうかを指定します } user_data = <<EOL #cloud-config timezone: Asia/Tokyo package_upgrade: true packages: - zip - avahi-daemon - avahi-utils - ca-certificates - curl - gnupg keyboard: layout: jp write_files: - path: /etc/systemd/timesyncd.conf content: | [Time] NTP=ntp.nict.jp FallbackNTP=ntp.ubuntu.com users: - name: taira shell: /bin/bash groups: adm,admin sudo: ["ALL=(ALL) NOPASSWD:ALL"] ssh_authorized_keys: - ssh-rsa AAAほげほげ証明書省略xxxxxxxx= hoge runcmd: - [ systemctl, restart, systemd-timesyncd.service ] - [ systemctl, restart, avahi-daemon.service ] EOL network { name = "taira-network" # インスタンスに接続するネットワークの名前を指定します port = openstack_networking_port_v2.port_minio.id # インスタンスに接続するポートのIDを指定します } depends_on = [openstack_blockstorage_volume_v3.vol-minio] }
参考:各ID確認コマンド
※admin-openrcなどを読み込んでから行うこと。
項目 | 内容 |
---|---|
ネットワーク/サブネットID | openstack network list |
イメージID | openstack image list |
初期化(プロバイダーなどをダウンロード)して確認(plan)、実行(apply)します。
terraform init terraform plan terraform apply
■ MinIOをdockerで立ち上げる
cf. Install Docker Engine on Ubuntu https://docs.docker.com/engine/install/ubuntu/
作成したインスタンスにsshします ※ユーザー名のtairaは、適宜変更してください。
ssh taira@192.168.4.33
dockerをインストールします。
sudo apt update sudo apt -y install ca-certificates curl gnupg curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg echo "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt update && sudo apt -y install docker-ce docker-ce-cli containerd.io sudo usermod -aG docker $USER
ログインし直すと使えるようになっていますので確認します。
docker run hello-world
MinIOを作成するdocker-compose.ymlを用意します
docker-compose.yml
version: '3' volumes: minio_data: {} # 永続化のため名前付きボリュームを作成します # "/var/lib/docker/volumes/${USER}_minio_data/_data/"になると思います # ディレクトリーは初回起動時に自動で作成されます services: minio: image: minio/minio:latest container_name: standalone-minio ports: - "9000:9000" # サービス用 HOST_PORT:CONTAINER_PORT - "80:80" # コンソール用 environment: MINIO_ROOT_USER: minio MINIO_ROOT_PASSWORD: minio123 MINIO_REGION_NAME: ap-northeast-1 command: server /data --console-address :80 # 自宅用なのでconsoleを80にします volumes: - minio_data:/data # "minio_data"ボリュームを/dataとしてマウントし、 # minioが/dataをバケットの/として扱います
Detachedモードで起動します
docker compose up -d
MinIOの管理画面にアクセスしてみましょう。 UsernameにはMINIO_ROOT_USER、PasswordにはMINIO_ROOT_PASSWORDを入力します。画面が開けば大丈夫でしょう。
http://192.168.4.33/
■ MinIOでBucketsを作成する
MinIOのコンソールで作成しても問題ありませんが、S3互換ということで、AWS CLIにMinIOの認証情報を追記し作業してみます。
cf. AWS CLI with MinIO Server https://min.io/docs/minio/linux/integrations/aws-cli-with-minio.html
現在使っているPCのAWS CLIの設定に以下のように追加します。
~/.aws/config などに以下追記
[profile vm-minio] region = ap-northeast-1 aws_access_key_id = minio aws_secret_access_key = minio123
以下コマンドにて初期状態を確認してみると、Bucketsはないのでそのまま返ってくるはずです。
aws --profile vm-minio --endpoint-url http://192.168.4.33:9000 s3 ls
terraform用のバケット(tf-backend)を以下のように作成します。
aws --profile vm-minio --endpoint-url http://192.168.4.33:9000 s3 mb s3://tf-backend
再び確認してみると以下のように作成されたバケット名が返ってくるはずです。
2023-04-xx hh:mm:nn tf-backend
■ terraformのバックエンドをMinIOにし、構成管理ファイルを永続化する
今回はボリュームを3個、作成してみます。前回のmain.tfファイルとは別の場所で作成しますが、変更点はbackendをs3で指定しているところです。
terraform { backend "s3" { bucket = "tf-backend" region = "ap-northeast-1" key = "rpi-openstack/os-minio/terraform.tfstate" endpoint = "http://192.168.4.33:9000" access_key = "minio" secret_key = "minio123" skip_region_validation = true skip_credentials_validation = true skip_requesting_account_id = true skip_get_ec2_platforms = true skip_metadata_api_check = true force_path_style = true } } provider "openstack" { user_name = "taira" tenant_name = "taira-project" password = "taira123" auth_url = "http://10.234.15.11:5000/v3/" } # 繰り返しはvariableで定義しておきます variable "volumes" { default = { "volume1" = { name = "volume1" size = 1 } "volume2" = { name = "volume2" size = 2 } "volume3" = { name = "volume3" size = 3 } } } resource "openstack_blockstorage_volume_v3" "volume" { for_each = var.volumes name = each.value.name size = each.value.size }
初期化して確認、実行します。
terraform init terraform plan terraform apply
無事にボリュームは3個できましたでしょうか? 確認目的なのでできたら破棄します。
terraform destroy
■ 最後に
今回はボリュームの仮想化や、(なんちゃってではありますが)S3互換のブロックデバイスなど、ストレージにフォーカスしておうちクラウドを拡張させてみました。 ストレージを仮想化すると自由度が向上し、IaCで構成管理の永続化などが出来はじめるので、クラウド感(笑)がマシマシになるのがお分かりいただけたかもしれません。 また、ストレージを物理サーバーから切り離した結果、SDカードはVMの運用とは切り離されて、NFSの許す限り巨大なディスクをVMにアタッチでき、SDは物理サーバーがbootするときに使ったり、ローカルで動くプロセスのログを保存する程度しか使わなくなって、本体の長寿命化にも貢献できたと思います。
今後もこのクラウド環境を拡張していく予定ですので、引き続きお付き合いいただければ幸いです。よろしくお願いいたします。