Raspberry PiでOpenStackクラスター GitHub Actionsでデプロイ編

こんにちは、SREの平です。前回の 『Raspberry PiでOpenStackクラスター ストレージ拡張編』 ( https://developer.so-tech.co.jp/entry/2023/04/19/110000 ) の続編となります。

私の趣味であるOpenStackクラスターの作成方法を、初めての方向けにご説明させてもらってきましたが、今回は仕上げです。GitHub Actionsを使って、私の自宅のOpenStack環境を、自動構築していきます。

まずは前回までの差分で主なものはこちらです。

  • 2023.2 Bobcat対応(2023/10/4リリースに対応しています)。
  • マルチアーキテクチャ対応(arm64とamd64に対応しました。Raspberry PI(以下RPi)を使わずintel等のNUCだけのクラスターや、RPi/NUC混在環境にもご利用いただけます)。
  • amazon linux 2のVMイメージを追加済み(ワーカーノードがamd64である必要があります。なのでRPiだけのクラスターでは動きません)。

あと自動化と今後の拡張のために以下の構築や変更も必要です。

  • パブリックDNSで引けるドメインの契約と、各サーバーがドメインに1台ずつ登録されていること。
  • "/etc/hosts"は編集しないこと。
  • LAN内にself-hosted runnersを構築すること(構築に必要)。
  • LAN内にNFSが動いていること(cinderボリュームのバックエンドに使用)。
  • LAN内にMinIO等のS3互換が動いていること(terraformのバックエンドに使用)。
  • 公開鍵をgithubに登録していること。
  • クラスターがdev/prd用に2つ必要(もちろん1クラスターでも可)。
  • Openstackクラスターの全サーバーにNICが2つあり、ネットワークはvlanであること。
  • 全物理サーバーでSWAPを有効化した。

もちろん不足も多々あると思いますがそういったものは随時追加をしてください。また、不要な物については削除等のカスタマイズをお願いします。ご自身の環境に合わせて自由に使いやすく作り替えてみてください。

■ 構成図

Physical Network Diagram

Logical Network Diagram

■ 作成手順概要

以下のように進めていきます。詳しくはまたそれぞれでご説明します。

  • LAN内のMinIO/NFSサーバー等の構築
  • clone
  • ansible/terraformの変数を、各環境に合うように設定変更する。
  • netplan/config.yamlの変更用playbookだけ先に手動でansibleを回して反映させておく。
  • ローカル用で使うパスワードファイルを準備する。
  • (初回や不具合を出し切るために)ローカルでDru runしてみる。
  • 自分用のrepositoryを作成しpushする。
  • GitHub Actionsのセルフホステッドランナーを準備する。
  • GitHub ActionsのSecretsを準備する。
  • GitHub Actionsで実行してみる。
  • terraformでインスタンスを作成する

■ LAN内のMinIO/NFSサーバー等の構築

「Raspberry PiでOpenStackクラスター ストレージ拡張編」などを参考に、MinIOと、NFSサーバーの用意をお願いいたします。 上記構成図では以下が該当のサーバーです。

目的 ホスト名
MinIO/ほか色々 pipi01.example.com
NFS synas01.example.com

■ clone

リポジトリをクローンしてください。 https://github.com/triplekube/myhome-openstack

以下のような構成になっています。

ansible
├── play-netplan.yml          # netplanの設定を行います。
├── site.yml                  # openstackのインストールを行います。
├── inventories/              # 接続先のホストを記述します。
│   ├── dev/                  # DEVはRPiのOpenStackだけで構成されたDEV環境です。
│   │   ├── hosts.yml
│   │   └── group_vars/
│   │       └── all.yml
│   └── prd/                  # PRDはRPi(ARM)/NUC(Intel)混成で構成され、本番として利用しています。
│       ├── hosts.yml
│       └── group_vars/
│           └── all.yml
├── roles/
│   ├── openstack/
│   │   ├── tasks/            # 具体的な実行タスクが記述されます。
│   │   │   ├── main.yml      # このファイルで各タスクをincludeしています。不要なタスクは削除してください。
│   │   │   ├── hoge1.yaml
│   │   │   └── hoge2.yaml
│   │   ├── handlers/         # アプリを再起動するeventやstateに応答するために使用されます。
│   │   │   └── main.yml
│   │   ├── files/            # 編集されずにそのままコピーされる静的ファイルはこちらに格納します。
│   │   ├── templates/        # jinjaテンプレートで書き換えが必要な動的ファイルはこちらに格納します。
│   ├── common/
│   └── netplan/
└── ansible.cfg               # sshの設定などを記述します。

■ ansible/terraformの変数を、各環境に合うように設定変更する。

私の設定と異なる部分(ユーザー名やIPアドレス)を変えてください。 環境によりtasks/main.yamlで不要なタスクをコメントアウト等する必要があります。

※なお私はDEVとPRDの2クラスターを作っていますが、1つの場合はどちらかを削除するなどの対応でいいと思います。

  • ansible
ファイル 内容
ansible/inventories/dev/group_vars/all.yml 開発用クラスタの色々な変数。prdも同じように変えてください。
ansible/inventories/dev/hosts.yml 開発用クラスタのサーバー名やIPアドレスの登録
ansible/roles/netplan/tasks/main.yaml netplan用のデフォゲとDNSのIPアドレスの登録
ansible/roles/openstack/tasks/main.yaml cinderやpromtail/grafana等がローカルになければ該当タスクをはずしてください。
ansible/roles/openstack/tasks/both.yaml 追加するパッケージなど追加・削除があれば変更してください。
ansible/roles/openstack/tasks/os-basic-setup.yaml フレーバーの設定を直接書いています。

terraformも私の設定と異なる部分(ユーザー名やIPアドレス)を変えてください。ただこちらは手抜きでopenstackのログイン情報や公開鍵などを記述しているのでSecrets Managerなどの利用も検討してみてください。

  • terraform
ファイル 内容
terraform/environments/dev/instance/main.tf 開発用クラスタのtf stateやログイン情報。prdも同じように変えてください。
terraform/environments/dev/instance/variable.tf NW名や作成したいVMの情報など。運用開始後はほぼこのファイルのみ使います。
terraform/environments/prd/instance/assets/default.tpl 作成するubuntu VMの初期設定です。公開鍵など記述してください。
terraform/environments/prd/instance/assets/default-amzn2.tpl 作成するamazon linuxの初期設定です。

■ netplan/config.yamlの変更用playbookだけ先に手動でansibleを回して反映させておく。

「Raspberry PiでOpenStackクラスターを作ってみよう」で用意する物理サーバーの初回起動時はDHCPでIPアドレスが不明ですが、運用中はIPとMACアドレスを固定し、インターフェイス名も1つ目をeth0、2つ目をeth1に固定させます。その変更をansibleにさせますが、actionsに含めたくないので別のplaybookを用意しました。 なおこのansibleでsudoを使っています。RPiなら不要ですが、NUC等USBイメージからインストールしたような場合sudoをノンパスで使えるように設定してから実行します。

例 RPiでなくDHCP(10.234.12.188)で起動したNUCで、sudoを有効にしてからplay-netplan.ymlを実行した例。ユーザー名は taira 。そしてこの設定後、このNUCのIPアドレスは10.234.14.11に変更される。

ssh 10.234.12.188
echo "taira ALL=(ALL) NOPASSWD:ALL" |sudo tee -a /etc/sudoers.d/taira_sudoers
exit
ansible-playbook ansible/play-netplan.yml -i 10.234.12.188, -e "ip0=10.234.14.11/22 nic0=enp1s0 nic1=enx207bd27657eb"

作業用PCから、play-netplan.ymlで変更後のIPアドレスに対して、ssh接続できることを確認してから実行してみます。

ssh 10.234.14.11

詳しくは以下に記述しましたのでご覧ください。 /ansible/roles/netplan/readme.md

■ ローカル用で使うパスワードファイルを準備する。

次にローカル用で使うパスワードファイルを準備します(github actionsでしか実行しない場合は不要ですが、まずローカルで動くかテストしますよね?)。 リポジトリに含めないように注意し、home直下などに以下のようなファイルを用意します。 もちろん各種パスワードは各自で適宜変更してください。

  • secrets.test.env
# DEV
export DEV_PW_OS_ADMIN=admin123
export DEV_PW_MARIADB=pass123
export DEV_PW_RABBITMQ=rabbitmq123
export DEV_PW_OS_KEYSTONE=keystone123
export DEV_PW_OS_GLANCE=glance123
export DEV_PW_OS_PLACEMENT=placement123
export DEV_PW_OS_CINDER=cinder123
export DEV_PW_OS_NOVA=nova123
export DEV_PW_OS_NEUTRON=neutron123
export DEV_PW_OS_METADATA=hoge
export DEV_PW_OS_ADD_NAME=taira123

# PRD
export PRD_PW_OS_ADMIN=admin1234
export PRD_PW_MARIADB=pass1234
export PRD_PW_RABBITMQ=rabbitmq1234
export PRD_PW_OS_KEYSTONE=keystone1234
export PRD_PW_OS_GLANCE=glance1234
export PRD_PW_OS_PLACEMENT=placement1234
export PRD_PW_OS_CINDER=cinder1234
export PRD_PW_OS_NOVA=nova1234
export PRD_PW_OS_NEUTRON=neutron1234
export PRD_PW_OS_METADATA=hoge1234
export PRD_PW_OS_ADD_NAME=taira1234

■ (初回や不具合を出し切るために)ローカルでDru runしてみる。

まずローカル用で使うパスワードファイルを、環境変数として読み込んでおきます。 以下のようにして admin123 など設定したパスワードが表示されれば大丈夫です。

. ~/secrets.test.env
echo $DEV_PW_OS_ADMIN

では実行してみます。ここで色々なエラーが出ると思いますので、変数やtaskの無効化など、エラーが出ないよう調整いただければと思います。

※ansible.cfgはリポジトリ直下に置いてあるので、そこで実行してみてください。

#dev
ansible-playbook ansible/site.yml -i ansible/inventories/dev/hosts.yml --check
#prd
ansible-playbook ansible/site.yml -i ansible/inventories/prd/hosts.yml --check

ここでエラーなく回るようであればActionsを使って自動化していきます。

■ 自分用のrepositoryを作成しpushする。

 https://github.com/new から新規でPrivateのrepositoryを作り、cloneし、 編集したファイルをコピーしてpushしておきます。

なおブランチはdevとして使うdevelopブランチをデフォルトとし、prd用のmainブランチも用意します。 devを用意しない場合はmainだけでもかまいません。

■ GitHub Actionsのセルフホステッドランナーを準備する。

公式を参考に、セルフホステッドランナーを構築します。 https://github.com/actions/runner

上記ネットワークトポロジーでは以下が該当のサーバーです。このサーバーから各コントローラーやワーカーにsshできるかを確認しておいてください。

目的 IPまたはホスト名
runner skyeye.example.com

■ GitHub ActionsのSecretsを準備する。

Secrets and variablesのActionsで、パスワードなどを登録してください。 内容は secrets.test.env と同じで export DEV_PW_OS_ADMIN=admin123 なら

Name DEV_PW_OS_ADMIN
Secret  admin123

のように22個登録します(環境により前後します)。

■ GitHub Actionsで実行してみる。

詳しくは .github/workflows/deploy.yml を見てもらえればと思いますが

  • developにPRを出せばdevでansibleのDry Runが回るはずです。
  • developにマージでデプロイします。
  • mainブランチにマージしたらprdでデプロイが動きます。

これで環境の自動構築は完成です。 さて、VMの構成管理はterraformにします。次で作成していきましょう。

■ terraformでインスタンスを作成する

まずtfファイルを補完するバケットをMinIO等に用意してください。

この設定ファイル terraform/environments/dev/instance/main.tf と実際に作成するバケット名、例えば

  • tfstate.pios.example.com
  • tfstate.nucos.example.com

は揃えてください。そして以下のように環境ごとに実行します。

cd terraform/environments/dev/instance/
terraform init
terraform plan

作成するVMのインスタンス名やIPアドレスは以下にまとめています。 terraform/environments/dev/instance/variable.tf

デフォルトですと simple と simple-nfs という2つのVMを作成しようとします。 どちらかだけにしたり、VMの設定をコピーして、10台分用意したりするのも良いでしょう。

なおVMをubuntuでなくamazon linuxにしたいときはその変数の中に image というのがありますがここを

image        = "amzn2-2.0.20231101.0-amd64"

のような形に変えれば使えます。ただamazon linuxは私はarm64ではうまく動かせませんでしたので、amd64のワーカーを1台以上追加してください。ほかのディストリビューションもimportしてあげたあと、イメージ名を指定すれば使えるので、ここも色々試してみてください。

ではplanで問題なければデプロイします。

terraform apply

いかがでしょうか。無事にVMが作成できれば完成です。

■ 最後に

環境をマージだけで用意できるようになるともう手作業はしたくなくなりますね。

なおDNSについて細かく書かなかったのですが、我が家のサーバーはCloud DNSにterraformでホスト名を登録してまして、パブリックDNSで引けるようにしています。もちろんRoute53とかでも大丈夫ですが、DNSを使わず、hostsファイルで運用する場合、今後の拡張が難しくなってきます。その場合はローカルにDNSを立てて、8.8.8.8の部分をローカルDNSに向けるような方法も検討してみてください。

あと今回はamazon linux 2のVMを予め用意するようにしました。ただ他のcloud imageと違ってseed.isoが必要などひと手間必要なんですよね、それがやや面倒だったんですが、これが完成すれば手軽に利用できるので、EC2等の検証も簡単にできるようになりました。ぜひお試しください。

次回はこのクラウド上でコンテナとネットワークの拡張をしてみたいと思います。 よろしくお願いいたします。