物理サーバ1台の上に Red Hat OpenStack Platform 17.1 の環境を作ってみよう

Red Hat のテクニカルサポートエンジニアの田中です。

ここしばらくのバージョンの Red Hat OpenStack Platform(以降 RHOSP)では Director を使用して OpenStack クラスタをデプロイします。 Director は Upstream では TripleO(OpenStack-On-OpenStack)と呼ばれており、まずアンダークラウドと呼ばれる1台構成の OpenStack クラスタを作り、アンダークラウドの Heat や Ironic、Neutron といった機能と Ansible/Puppet などの構成管理ツールを活用してオーバークラウドと呼ばれる OpenStack クラスタをデプロイします。 OpenStack で OpenStack を管理することによって一元的かつフレキシブルに OpenStack クラスタのライフサイクルを管理できるのが Director の魅力......なのですが、OpenStack クラスタを 2 つ作る必要があったり、ノードの構成やネットワークの構成、各コンポーネントの設定などカスタマイズの幅が非常に広かったりと、初めて OpenStack を触る人にとっては少し難しい仕組みであるのも事実です。 弊社ではデプロイの手順を説明をした Installing and managing Red Hat OpenStack Platform with director というドキュメントがあるのですが、どのような構成・設計にも対応できるよう汎用的な書かれ方をしており、初めて Director を触る人にとっては少し難しく感じるでしょう。

本記事は、物理サーバマシン1台と RHOSP のサブスクリプションさえあればコピペで RHOSP 17.1 のデプロイができる手順を公開し Director の理解のとっかかりとしていただければ、というのがコンセプトです。 RHOSP 17 以降では RHOSP 16 以前と比較して一部手順に違いあるので、RHOSP 16 以前は触れたことがありこれから RHOSP 17 の導入を検討している人にも有用な内容かと思います。 お手軽な検証環境の構築手順として参考にしていただくのも良いでしょう。

ただし本手順および本手順で構築された環境は Red Hat としてはサポート対象外であることにご留意ください。 本手順で作成される環境の構成は非サポート構成であり、また、弊社がサポートしていないサードパーティのソフトウェアなども手順中で使用しているためです。

Director による RHOSP 17.1 デプロイの流れ

RHOSP 17.1 をデプロイする場合、手順は大きく分けて以下のようになるかと思います。

  1. ノード構成やネットワーク構成の設計
  2. サーバやネットワークの用意
  3. アンダークラウドマシンへの RHEL 9.2 インストール
  4. アンダークラウドのインストール(openstack undercloud install コマンド)
  5. オーバークラウドのデプロイ
    1. ネットワーク情報のプロビジョン(openstack overcloud network provision コマンド)
    2. VIP 情報のプロビジョン(openstack overcloud network vip provision コマンド)
    3. オーバークラウドのノード情報のインポート(openstack overcloud node import コマンド・openstack baremetal introspection コマンド)
    4. オーバークラウドノードのプロビジョン(openstack overcloud node provision コマンド)
    5. オーバークラウドのデプロイ(openstack overcloud deploy コマンド)

本手順の前提条件

本記事の手順の前提条件は以下です。

  • 十分なスペックの物理マシンがあること。私の環境では以下のスペックのマシンを用意しました。
    • CPU : Intel(R) Xeon(R) Gold 6130 CPU × 2 ソケット (合計 64 スレッド)
    • メモリ : 187GB
    • ストレージ : HDD 1.7 TB
  • Red Hat Customer Portal のアカウントがあること
  • 必要なノード数分の有効な RHOSP サブスクリプションがあること(サブスクリプションは別途購入が必要です)
  • インターネットにアクセス可能であること(Proxy を経由する必要がある場合は、http_proxy、https_proxy、no_proxy 等の設定がハイパーバイザーとアンダークラウドで必要になります)

マシンスペックについては参考までに私の環境で OpenStack をデプロイした直後のメモリとストレージの使用状況を以下に示します。

# df -h /
Filesystem                        Size  Used Avail Use% Mounted on
/dev/mapper/vg01--root            1.7T   78G  1.6T   5% /

# free -h
              total        used        free      shared  buff/cache   available
Mem:          187Gi        79Gi        45Gi        21Mi        62Gi       106Gi
Swap:         4.0Gi          0B       4.0Gi

また繰り返しとなりますが、本手順および本手順で構築された環境は Red Hat としてはサポート対象外であることにご留意ください。

1. ノード構成やネットワーク構成の設計

今回は物理サーバマシン1台を用意し、その上に Qemu/KVM で以下の仮想マシンを作成して RHOSP をデプロイします。 HA(High Availability)の動作が確認できるようにコントローラノードは 3 台、インスタンスのマイグレーションができるようにコンピュートノードは 2 台としてみました。 マシンスペックに自信がない場合はそれぞれ 1 台構成としてデプロイするとリソースが節約できるでしょう。

  • アンダークラウドノード:1 台
  • オーバークラウドのコントローラノード:3 台
  • オーバークラウドのコンピュートノード:2 台

RHOSP 17.1 のデフォルトでは、用途ごとに ctlplane, External, InternalAPI, Storage, StorageMgmt, Tenant といった異なるネットワークが必要になります。 ctlplane ネットワークは主にデプロイに使用されるネットワークで、本ネットワークを介して PXE ブートや OS イメージデータの転送などが行われます。 External ネットワークはデプロイ完了後にオーバークラウドの OpenStack のパブリックエンドポイントが配置されるネットワークであり、ユーザはこのネットワークから OpenStack にアクセスします。 Tenant ネットワークはテナントネットワーク(プライベートネットワーク)を介したインスタンス間の通信に使用されるネットワークで、インスタンスから送信されたパケットは Geneve などのプロトコルでトンネリングされこのネットワークを通ります。 これらのネットワークには物理的に異なるネットワークを用意することもできますし、VLAN で物理ネットワークを分離して割り当てることも出来ます。 本手順では以下のふたつの Libvirt の仮想ネットワークを作成し、br-external ネットワークの上には VLAN で複数のネットワークを乗せることにします。

  • br-provisioning
    • ctlplane 192.168.24.0/24 VLAN なし
  • br-external
    • External 10.0.0.0/24 VLAN なし
    • InternalAPI 172.16.2.0/24 VLAN:20
    • Storage 172.16.1.0/24 VLAN:30
    • StorageMgmt 172.16.3.0/24 VLAN:40
    • Tenant 172.16.0.0/24 VLAN:50

2. サーバやネットワークの用意

まずは用意した物理サーバに Linux を入れましょう。私の環境では RHEL 8.5 を入れました。検証していませんが CentOS Stream 8 でも動くかと思います。

用意した物理 Linux サーバに必要なパッケージをインストールします。 ※必要なパッケージはディストリビューションやバージョンにより異なる場合があります。

# dnf install -y libvirt python3 curl virt-install qemu-kvm libgcrypt libguestfs-tools-c

RHOSP のノードの NTP 時刻同期先となれるよう chronyd をセットアップしておきます。 ※外部にアクセス可能な NTP サーバあればそちらを使用しても構いません。

# sed -i "s/^#local /local /" /etc/chrony.conf 
# echo "local stratum 10" >> /etc/chrony.conf
# echo "allow 10.0.0.0/24" >> /etc/chrony.conf
# echo "allow 192.168.24.0/24" >> /etc/chrony.conf
# systemctl restart chronyd
# systemctl enable chronyd

LIbvirt の仮想ネットワークを作成します。

# systemctl start libvirtd

# cat << EOF > br-provisioning.xml
<network>
  <name>br-provisioning</name>
  <bridge name='br-provisioning' zone="libvirt"/>
  <forward mode='nat'>
    <nat>
      <port start='1024' end='65535'/>
    </nat>
  </forward>
  <ip address='192.168.24.254' netmask='255.255.255.0'/>
</network>
EOF

# virsh net-define br-provisioning.xml
# virsh net-autostart br-provisioning
# virsh net-start br-provisioning
# rm -f br-provisioning.xml

# cat << EOF > br-external.xml
<network>
  <name>br-external</name>
  <bridge name='br-external' zone="libvirt"/>
  <forward mode='nat'>
    <nat>
      <port start='1024' end='65535'/>
    </nat>
  </forward>
  <ip address='10.0.0.1' netmask='255.255.255.0'/>
</network>
EOF

# virsh net-define br-external.xml
# virsh net-autostart br-external
# virsh net-start br-external
# rm -f br-external.xml

アンダークラウドノードを作ります。 空の仮想マシンを作って後で RHEL をインストールしても良いのですが、今回は RHEL 9.2 の KVM ゲストイメージを元に仮想マシンを作ってしまいましょう。 Red Hat Customer Portal にログインし RHEL 9.2 の KVM ゲストイメージをダウンロードします。 ※イメージのダウンロードにはカスタマーポータルのアカウントとサブスクリプションが必要です。

ダウンロードした RHEL 9.2 イメージを使ってアンダークラウドノードを作成します。 virt-customize コマンドではイメージをカスタマイズして root ユーザのパスワードに「p@assword」を設定しています。これはお好きなパスワードに差し替えていただいて構いません。

# mv <ダウンロードしたイメージ> /var/lib/libvirt/images/rhel-9.2-x86_64-kvm.qcow2
# qemu-img create -f qcow2 /var/lib/libvirt/images/director.qcow2 120G
# virt-filesystems --long --parts --blkdevs -h -a /var/lib/libvirt/images/rhel-9.2-x86_64-kvm.qcow2
# virt-resize --expand /dev/sda4 /var/lib/libvirt/images/rhel-9.2-x86_64-kvm.qcow2 /var/lib/libvirt/images/director.qcow2
# virt-customize -a /var/lib/libvirt/images/director.qcow2 --root-password password:p@assword --uninstall cloud-init
# virt-install --name director --memory 24576 --vcpus 8 --disk /var/lib/libvirt/images/director.qcow2 --import --os-variant rhel-unknown --network network=br-provisioning  --network network=br-external --noautoconsole

オーバークラウドノードも作成します。 オーバークラウドノードの OS はオーバークラウドのデプロイ時に自動でストレージに書き込まれますので、ここでは空の qcow2 イメージを作り仮想マシンを作ります。

# qemu-img create -f qcow2 /var/lib/libvirt/images/controller0.qcow2 100G
# virt-install --name controller0 --memory 32768 --vcpus 8 --disk /var/lib/libvirt/images/controller0.qcow2 --import --os-variant rhel-unknown --network network=br-provisioning --network network=br-external --noautoconsole

# qemu-img create -f qcow2 /var/lib/libvirt/images/controller1.qcow2 100G
# virt-install --name controller1 --memory 32768 --vcpus 8 --disk /var/lib/libvirt/images/controller1.qcow2 --import --os-variant rhel-unknown --network network=br-provisioning --network network=br-external --noautoconsole

# qemu-img create -f qcow2 /var/lib/libvirt/images/controller2.qcow2 100G
# virt-install --name controller2 --memory 32768 --vcpus 8 --disk /var/lib/libvirt/images/controller2.qcow2 --import --os-variant rhel-unknown --network network=br-provisioning --network network=br-external --noautoconsole

# qemu-img create -f qcow2 /var/lib/libvirt/images/compute0.qcow2 50G
# virt-install --name compute0 --memory 16384 --vcpus 4 --disk /var/lib/libvirt/images/compute0.qcow2 --import --os-variant rhel-unknown --network network=br-provisioning --network network=br-external --noautoconsole

# qemu-img create -f qcow2 /var/lib/libvirt/images/compute1.qcow2 50G
# virt-install --name compute1 --memory 16384 --vcpus 4 --disk /var/lib/libvirt/images/compute1.qcow2 --import --os-variant rhel-unknown --network network=br-provisioning --network network=br-external --noautoconsole

オーバークラウドノードのデプロイ時には、アンダークラウドが IPMI(BMC)経由でオーバークラウドノードを PXE ブートし、OS イメージを書き込みます。 今回オーバークラウドノードは仮想マシンなので vbmc を使用させていただき仮想の BMC を作成します。 OS を再起動しても vBMC が自動で立ち上がるように systemd のサービスも併せて作ります。 ファイアウォールの穴あけも行います。

# pip3 install --upgrade pip
# pip3 install virtualbmc
# vbmcd
# vbmc add controller0 --port 6230 --username admin --password p@assword
# vbmc add controller1 --port 6231 --username admin --password p@assword
# vbmc add controller2 --port 6232 --username admin --password p@assword
# vbmc add compute0 --port 6233 --username admin --password p@assword
# vbmc add compute1 --port 6234 --username admin --password p@assword
# vbmc start controller0
# vbmc start controller1
# vbmc start controller2
# vbmc start compute0
# vbmc start compute1
# pkill vbmcd

# cat << EOF > /etc/systemd/system/vbmcd.service
[Unit]
After = libvirtd.service
After = syslog.target
After = network.target
Description = vbmc service

[Service]
ExecReload = /bin/kill -HUP $MAINPID
ExecStart = /usr/local/bin/vbmcd --foreground
ExecStartPost = /usr/local/bin/vbmc start controller0
ExecStartPost = /usr/local/bin/vbmc start controller1
ExecStartPost = /usr/local/bin/vbmc start controller2
ExecStartPost = /usr/local/bin/vbmc start compute0
ExecStartPost = /usr/local/bin/vbmc start compute1
Group = root
PrivateDevices = False
PrivateNetwork = False
PrivateTmp = False
PrivateUsers = False
Restart = on-failure
RestartSec = 2
Slice = vbmc.slice
TasksAccounting = True
TimeoutSec = 120
Type = simple
User = root

[Install]
WantedBy = multi-user.target
EOF

# systemctl daemon-reload
# systemctl enable --now vbmcd
# vbmc list

# firewall-cmd --zone libvirt --add-port 6230-6234/udp --permanent
# firewall-cmd --zone libvirt --add-service ntp --permanent
# firewall-cmd --reload

3. アンダークラウドマシンへの RHEL 9.2 インストール

通常はサーバを用意した後アンダークラウドマシンへ RHEL 9.2 のインストールが必要です。 今回は上の手順で RHEL 9.2 インストール済みの仮想マシンを作成済みなのでこの手順はスキップします。

4. アンダークラウドのインストール(openstack undercloud install コマンド)

まずは以下のコマンドでアンダークラウドの仮想マシンのコンソールを開き、ログインしましょう。 virsh console コマンド実行後 Enter キーを叩くとログインプロンプトが表示されます。 パスワードは上の手順の virt-customize で設定したものになります。

# virsh console director
  -> user : root
  -> password : p@assword

ホスト名や IP アドレスの設定などをします。 eth0 が br-provisioning、eth1 が br-external につながっています。 eth0 は後の undercloud インストール時に自動で IP アドレスが設定されますので、ここでは eth1 だけ IP アドレスを設定します。

# hostnamectl set-hostname undercloud.example.com
# hostnamectl set-hostname --transient undercloud.example.com
# nmcli c mod "Wired connection 2" connection.id "eth1"
# nmcli c mod eth1 ipv4.method manual ipv4.address 10.0.0.254/24 ipv4.dns 10.0.0.1 ipv4.gateway 10.0.0.1
# nmcli c up eth1
# nmcli c del "Wired connection 1"
# echo 192.168.24.1 `hostname` >> /etc/hosts
# timedatectl set-timezone Asia/Tokyo

必要なパッケージのダウンロードができるように、RHOSP のサブスリプションのアタッチをし、リポジトリを有効化します。 RHOSP 17.1 は RHEL 9.2 の上でしかサポートされないので、マイナーバージョンを 9.2 に固定することも忘れないようにしましょう。 次にパッケージのインストールと、RHEL 9.2 の最新バージョンへのアップデートをします。

# subscription-manager register
# subscription-manager attach --pool=XXXXXXX
# subscription-manager release --set=9.2
# subscription-manager release 
# subscription-manager repos --disable=*
# subscription-manager repos \
  --enable=rhel-9-for-x86_64-baseos-eus-rpms \
  --enable=rhel-9-for-x86_64-appstream-eus-rpms \
  --enable=rhel-9-for-x86_64-highavailability-eus-rpms \
  --enable=openstack-17.1-for-rhel-9-x86_64-rpms \
  --enable=fast-datapath-for-rhel-9-x86_64-rpms
# dnf install -y python3-tripleoclient crudini ipmitool
# dnf update -y

stack ユーザを作成します。 以降アンダークラウドノードでは基本的に root ユーザで作業をすることはなく、stack ユーザで作業することになります。 下記の passwd コマンドでは stack ユーザのパスワードを「p@assword」に設定しています。これもお好きなパスワードに差し替えていただいて構いません。

# useradd stack
# echo p@assword | passwd --stdin stack
# echo "stack ALL=(root) NOPASSWD:ALL" | tee -a /etc/sudoers.d/stack
# chmod 0440 /etc/sudoers.d/stack

パッケージのインストール・アップデートをしたので、一度アンダークラウドノードを再起動しておきましょう。

# reboot

再起動が問題なく完了したことを確認したら、ctrl+] キーを叩き virsh console から抜けます。 以降はアンダークラウドノードへは SSH で接続します。 SSH 鍵を作成していない場合は ssh-keygen で作っておきましょう。 ssh-copy-id 実行時のパスワードは上の passwd コマンドで設定したものになります。

# echo 10.0.0.254 undercloud director >> /etc/hosts
# ssh-keygen                   # もしまだ SSH キーを作成していない場合
# ssh-copy-id stack@director   # password : p@assword
# ssh stack@director

必要な作業ディレクトリを作ります。 image ディレクトリにはオーバークラウドの OS イメージなどを、templates ディレクトリにはオーバークラウドの設定に使用するテンプレートファイルなどを後に配置します。

$ mkdir ~/images
$ mkdir ~/templates

RHOSP 12 以降、RHOSP の各サービス(nova-api、neutron-api など)はコンテナ化されております。 これらのコンテナイメージをプル(ダウンロード)するための設定ファイルを作成します。 ファイル名は任意ですが、一般的には「containers-prepare-parameter.yaml」です。

$ openstack tripleo container image prepare default \
  --local-push-destination \
  --output-env-file containers-prepare-parameter.yaml

本ファイルには弊社コンテナレジストリからコンテナイメージをプルするために認証情報を記載する必要があります。 ただしユーザIDとパスワードを平文で記載するのは避けたいので、以下の記事を参考にレジストリサービスアカウント(認証トークン)を作成しましょう。

これにより Red Hat カスタマーポータルのユーザIDやパスワードを記載することなくコンテナイメージのプルをすることができます。

作成したレジストリサービスアカウントのユーザIDとパスワードを以下のコマンドで「containers-prepare-parameter.yaml」に記載します。 <username><password> の箇所をレジストリサービスアカウントのユーザIDとパスワードに置き換えて以下のコマンドを実行してください。

$ cat << EOF >> containers-prepare-parameter.yaml
  ContainerImageRegistryCredentials:
    registry.redhat.io:
      <username>: <password>
EOF

アンダークラウドのインストールは undercloud.conf という設定ファイルに基づいて行われます。 以下のコマンドでは undercloud.conf を編集しています。もちろん vi などのテキストエディタで編集していただいても構いません。 ちなみにここで設定している 10.0.0.1 はハイパーバイザーの IP アドレスです。

$ cp /usr/share/python-tripleoclient/undercloud.conf.sample ~/undercloud.conf
$ crudini --set undercloud.conf DEFAULT container_images_file /home/stack/containers-prepare-parameter.yaml
$ crudini --set undercloud.conf DEFAULT local_interface eth0
$ crudini --set undercloud.conf DEFAULT overcloud_domain_name example.com
$ crudini --set undercloud.conf DEFAULT undercloud_nameservers 10.0.0.1
$ crudini --set undercloud.conf DEFAULT clean_nodes true
$ crudini --set undercloud.conf DEFAULT generate_service_certificate true
$ crudini --set undercloud.conf DEFAULT undercloud_ntp_servers 10.0.0.1
$ crudini --set undercloud.conf ctlplane-subnet masquerade true
$ crudini --set undercloud.conf ctlplane-subnet dns_nameservers 10.0.0.1

いよいよアンダークラウドのインストールです。 1時間程度かかる場合もあるので気長に待ちましょう。

$ openstack undercloud install

インストールが成功すると以下のような出力がされます。

########################################################

Deployment successful!

########################################################

Writing the stack virtual update mark file /var/lib/tripleo-heat-installer/update_mark_undercloud

##########################################################

The Undercloud has been successfully installed.

Useful files:

Password file is at /home/stack/tripleo-deploy/undercloud/tripleo-undercloud-passwords.yaml
The stackrc file is at ~/stackrc

Use these files to interact with OpenStack services, and
ensure they are secured.

##########################################################

インストールが成功すると、ホームディレクトリ直下に stackrc というファイルが作成されます。 本ファイルには、アンダークラウドの OpenStack へのアクセスに必要な情報(エンドポイントの URL やユーザID・パスワードなど)が格納されています。 CLI でアンダークラウドの OpenStack にアクセスして操作するには、以下のように stackrc を読み込んでからコマンドを実行する必要があります。

$ source stackrc
$ openstack endpoint list

5. オーバークラウドのデプロイ

ここからはオーバークラウドのデプロイになります。

5-a. ネットワーク情報のプロビジョン(openstack overcloud network provision コマンド)

ネットワーク構成(MTU、VLAN ID、IP アドレスレンジ、デフォルトゲートウェイなど)の設定とプロビジョンを行います。 設定を記載するファイルである network_data.yaml のサンプルがあるので、今回はそれをそのまま使用します。 IP アドレスレンジの変更や VLAN ID の変更などのカスタマイズをしたい場合は本ファイルを編集することになります。

$ cp /usr/share/openstack-tripleo-heat-templates/network-data-samples/default-network-isolation.yaml /home/stack/templates/network_data.yaml
$ #vim /home/stack/templates/network_data.yaml
$ openstack overcloud network provision \
  --output /home/stack/templates/overcloud-networks-deployed.yaml \
  /home/stack/templates/network_data.yaml
$ openstack network list
$ openstack subnet list

上記の openstack overcloud network provision で /home/stack/templates/overcloud-networks-deployed.yaml というファイルが作成されます。 本ファイルは後の openstack overcloud deploy 実行時に使用します。

なお分かりづらいのですが、ここではアンダークラウドの Neutron にネットワークの情報を登録しているだけであり、実際にそのネットワーク上に何かインタフェースの作成や IP アドレスの設定をしているわけではありません。

5-b. VIP 情報のプロビジョン(openstack overcloud network vip provision コマンド)

次にオーバークラウドノードが持つ VIP の情報の設定とプロビジョンを行います。 コントローラノードは 3 台の冗長構成を取ることが一般的ですが、この 3 台のうち 1 台が代表して VIP を持ち、クライアント等はこの VIP に対してアクセスすることになります。 ここではその VIP の設定を行います。 本手順でもやはりサンプルの設定ファイルをそのまま使います。 カスタマイズしたい場合は設定ファイルを編集しましょう。

$ cp /usr/share/openstack-tripleo-heat-templates/network-data-samples/vip-data-default-network-isolation.yaml /home/stack/templates/vip_data.yaml
$ #vim /home/stack/templates/vip_data.yaml
$ openstack overcloud network vip provision \
  --stack overcloud \
  --output /home/stack/templates/overcloud-vip-deployed.yaml \
  /home/stack/templates/vip_data.yaml
$ openstack port list

上記の openstack overcloud network vip provision で /home/stack/templates/overcloud-vip-deployed.yaml というファイルが作成されます。 本ファイルは後の openstack overcloud deploy 実行時に使用します。

ここでもやはりアンダークラウドの Neutron に VIP の情報を登録しているだけであり、実際にどこかのインタフェースで IP アドレスの設定をしているわけではありません。

5-c. オーバークラウドのノード情報のインポート(openstack overcloud node import コマンド・openstack baremetal introspection コマンド)

まずはオーバークラウドノードにデプロイする OS のイメージなどを登録しておかないといけないので以下の手順を実行しましょう。 本手順で /var/lib/ironic/images/overcloud-hardened-uefi-full.raw というファイルが作成され、このイメージが後の手順でオーバークラウドノードのストレージに書き込まれることになります。

$ source ~/stackrc
$ sudo dnf install rhosp-director-images-uefi-x86_64 rhosp-director-images-ipa-x86_64 -y
$ for i in /usr/share/rhosp-director-images/ironic-python-agent-latest.tar /usr/share/rhosp-director-images/overcloud-hardened-uefi-full-latest.tar; do tar -xvf $i -C ~/images; done
$ openstack overcloud image upload --image-path ~/images/
$ ls -l /var/lib/ironic/images
$ ls -l /var/lib/ironic/httpboot

次に、オーバークラウドノードの情報をアンダークラウドの Ironic に登録します。 ここで登録した情報を元に、後の手順で IPMI のアクセスや PXE ブートなどが行われ、OS イメージの書き込みなどががされることになります。 オーバークラウドノードの NIC の MAC アドレスなどを確認しないといけませんので、アンダークラウドノードからログアウトしてハイパーバイザーに戻りましょう。

$ exit

ノードの登録には以下のような情報が必要になります。

  • オーバークラウドノードの IPMI の IP アドレス、ポート番号、ユーザID、パスワード
  • オーバークラウドノードの ctlplane ネットワークに接続されている NIC の MAC アドレス
  • など

今回の手順の場合、IPMI の情報は上の vbmc で設定した情報となります。 MAC アドレスは virsh dumpxml や virsh domiflist コマンドなどで確認できます。

こうして確認した情報をテキストエディタでファイルに書いていくのですが、今回はコピペで動くことがテーマなので、以下のコマンドを実行しましょう。 必要な情報が全て書き込まれた nodes.yaml ファイルが作成されます。

# cat << EOF > nodes.yaml
nodes:
  - ports:
      - address: $(virsh dumpxml controller0|xmllint --xpath "//interface/source[@network='br-provisioning']/parent::*/mac/@address" - |cut -d'"' -f2)
        physical_network: ctlplane
    name: "controller0"
    arch: "x86_64"
    pm_type: "ipmi"
    pm_user: "admin"
    pm_password: "p@assword"
    pm_addr: "192.168.24.254"
    pm_port: "6230"
  - ports:
      - address: $(virsh dumpxml controller1|xmllint --xpath "//interface/source[@network='br-provisioning']/parent::*/mac/@address" - |cut -d'"' -f2)
        physical_network: ctlplane
    name: "controller1"
    arch: "x86_64"
    pm_type: "ipmi"
    pm_user: "admin"
    pm_password: "p@assword"
    pm_addr: "192.168.24.254"
    pm_port: "6231"
  - ports:
      - address: $(virsh dumpxml controller2|xmllint --xpath "//interface/source[@network='br-provisioning']/parent::*/mac/@address" - |cut -d'"' -f2)
        physical_network: ctlplane
    name: "controller2"
    arch: "x86_64"
    pm_type: "ipmi"
    pm_user: "admin"
    pm_password: "p@assword"
    pm_addr: "192.168.24.254"
    pm_port: "6232"
  - ports:
      - address: $(virsh dumpxml compute0|xmllint --xpath "//interface/source[@network='br-provisioning']/parent::*/mac/@address" - |cut -d'"' -f2)
        physical_network: ctlplane
    name: "compute0"
    arch: "x86_64"
    pm_type: "ipmi"
    pm_user: "admin"
    pm_password: "p@assword"
    pm_addr: "192.168.24.254"
    pm_port: "6233"
  - ports:
      - address: $(virsh dumpxml compute1|xmllint --xpath "//interface/source[@network='br-provisioning']/parent::*/mac/@address" - |cut -d'"' -f2)
        physical_network: ctlplane
    name: "compute1"
    arch: "x86_64"
    pm_type: "ipmi"
    pm_user: "admin"
    pm_password: "p@assword"
    pm_addr: "192.168.24.254"
    pm_port: "6234"
EOF

作成したファイルをハイパーバイザーからアンダークラウドにコピーし、

# scp nodes.yaml stack@director:

アンダークラウドでこれをインポートします。 openstack baremetal node list でインポートしたオーバークラウドノードの情報が確認でき、各ノードの Provisioning State が managable になれば成功です。

# ssh stack@director
$ source ~/stackrc
$ openstack overcloud node import --validate-only ~/nodes.yaml
$ openstack overcloud node import ~/nodes.yaml
$ openstack baremetal node list

次にイントロスペクションと呼ばれる処理を実行します。 これにより、オーバークラウドノードが PXE ブートで起動し、ironic-python-agent と呼ばれるプログラムが実行され、オーバークラウドノードのマシンスペックなどの情報が収集され、アンダークラウドノードの Ironic に収集された情報が登録されます。 10 分程度時間がかかる場合があるのでしばらく待ちましょう。 この時オーバークラウドノードのコンソールを見てみると PXE ブートしている様子や ironic-python-agent が動いている様子が確認できて面白いかもしれません。 成功すれば各ノードの Porvisioning State が availabe になり、オーバークラウドのデプロイに使用できる状態になります。

$ openstack overcloud node introspect --all-manageable --provide
$ openstack baremetal node list

Qemu/KVM で作成した仮想マシンはデフォルトでは legacy-BIOS ブートをするので、アンダークラウドの Ironic でもそのように設定します。

$ openstack baremetal node list -f value -c UUID| while read NODE; do openstack baremetal node set --property capabilities="boot_mode:bios,$(openstack baremetal node show $NODE -f json -c properties | jq -r .properties.capabilities | sed "s/boot_mode:[^,]*,//g")" $NODE;done 

5-d. オーバークラウドノードのプロビジョン(openstack overcloud node provision コマンド)

ここではオーバークラウドノードに OS のデプロイやネットワークインタフェースの設定などを行います。

オーバークラウドノードのネットワーク設定を定義するカスタムネットワークインタフェーステンプレートファイルを作成します。 本ファイルではオーバークラウドノードのどのインタフェースにどのネットワークを割り当てるかや、Neutron のプロバイダーネットワークの提供に必要な Open vSwitch のブリッジの定義などをします。 また本ファイルは Jinja2 形式になっており、ロールやネットワークごとにループを回したり、IP アドレスレンジなどの情報を変数から取得したり出来ます。 これもサンプルとなるファイルが /usr/share/ansible/roles/tripleo_network_config/templates 配下にいくつか存在するのですが、残念ながら今回の手順のネットワーク構成に合致するものはないので、手動で作成します。 以下の設定では nic1(eth0)に ctlplane ネットワークの IP アドレスを設定し、nic2(eth1)を Open vSwtich のブリッジにつなぎ External ネットワークの IP アドレス設定や InternalAPI/Storage/StorageMgmt 用の VLAN インタフェースを作成しています。

$ cat << EOF > ~/templates/two_interfaces.j2
---
{% set mtu_list = [ctlplane_mtu] %}
{% for network in role_networks %}
{{ mtu_list.append(lookup('vars', networks_lower[network] ~ '_mtu')) }}
{%- endfor %}
{% set min_viable_mtu = mtu_list | max %}
network_config:
- type: interface
  name: nic1
  mtu: {{ ctlplane_mtu }}
  use_dhcp: false
  addresses:
  - ip_netmask: {{ ctlplane_ip }}/{{ ctlplane_subnet_cidr }}
  routes: {{ ctlplane_host_routes }}
- type: ovs_bridge
  name: {{ neutron_physical_bridge_name }}
  dns_servers: {{ ctlplane_dns_nameservers }}
  domain: {{ dns_search_domains }}
{% if 'External' in role_networks %}
  mtu: {{ external_mtu }}
  use_dhcp: false
  addresses:
  - ip_netmask: {{ external_ip }}/{{ external_cidr }}
  routes: {{ external_host_routes }}
{% endif %}
  members:
  - type: interface
    name: nic2
    mtu: {{ min_viable_mtu }}
    primary: true
{% for network in role_networks if network != 'External' %}
  - type: vlan
    mtu: {{ lookup('vars', networks_lower[network] ~ '_mtu') }}
    vlan_id: {{ lookup('vars', networks_lower[network] ~ '_vlan_id') }}
    addresses:
    - ip_netmask: {{ lookup('vars', networks_lower[network] ~ '_ip') }}/{{ lookup('vars', networks_lower[network] ~ '_cidr') }}
    routes: {{ lookup('vars', networks_lower[network] ~ '_host_routes') }}
{% endfor %}
EOF

次に overcloud-baremetal-deploy.yaml と呼ばれるファイルを作成します。 本ファイルでは、各ロールのノード数や、どのベアメタルノードにどのロールやホスト名を割り当てるかを定義しています。 上で作成した two_interfaces.js への参照もあることにも注目してください。 またデフォルトでは Swift のデータ格納先に使用されるコントローラノードの /srv パーティションのサイズが小さいので、30GB へ拡張しています。

$ cat << EOF > /home/stack/templates/overcloud-baremetal-deploy.yaml
- name: Controller
  count: 3
  defaults:
    networks:
    - network: ctlplane
      vif: true
    - network: external
      subnet: external_subnet
    - network: internal_api
      subnet: internal_api_subnet
    - network: storage
      subnet: storage_subnet
    - network: storage_mgmt
      subnet: storage_mgmt_subnet
    - network: tenant
      subnet: tenant_subnet
    network_config:
      template: /home/stack/templates/two_interfaces.j2
      default_route_network:
      - external
  ansible_playbooks:
  - playbook: /usr/share/ansible/tripleo-playbooks/cli-overcloud-node-growvols.yaml
    extra_vars:
      growvols_args: >
        /=8GB
        /tmp=1GB
        /var/log=10GB
        /var/log/audit=2GB
        /home=1GB
        /srv=30GB
        /var=100%
  instances:
  - hostname: overcloud-controller-0
    name: controller0
  - hostname: overcloud-controller-1
    name: controller1 
  - hostname: overcloud-controller-2
    name: controller2
- name: Compute
  count: 2
  defaults:
    networks:
    - network: ctlplane
      vif: true
    - network: internal_api
      subnet: internal_api_subnet
    - network: tenant
      subnet: tenant_subnet
    - network: storage
      subnet: storage_subnet
    network_config:
      template: /home/stack/templates/two_interfaces.j2
  instances:
  - hostname: overcloud-novacompute-0
    name: compute0
  - hostname: overcloud-novacompute-1
    name: compute1
EOF

必要な情報が一通り揃ったので、ノードのプロビジョンを行います。 これにより、オーバークラウドノードが PXE ブートし、ironic-python-agent と呼ばれるプログラムが実行され、オーバークラウドノードのストレージに OS イメージが書き込まれます。 また Ansible でネットワークの設定やパーティションの拡張なども行われます。 本コマンドで作成された /home/stack/templates/overcloud-baremetal-deployed.yaml ファイルは後の openstack overcloud deploy で使用します。

$ openstack overcloud node provision \
  --stack overcloud \
  --network-config \
  --output /home/stack/templates/overcloud-baremetal-deployed.yaml \
  /home/stack/templates/overcloud-baremetal-deploy.yaml

成功すれば以下のコマンドでオーバークラウドノードの情報を確認することができるようになります。 オーバークラウドノードに割り当てられた IP アドレスも確認でき、ssh tripleo-admin@<IP-address> コマンドで SSH ログインが可能です。

$ metalsmith list

5-e. オーバークラウドのデプロイ(openstack overcloud deploy コマンド)

この手順が最後の手順になります。 この手順でオーバークラウドノードに Nova や Cinder、Neutron といった OpenStack のコンポーネントがデプロイされます。

オーバークラウドのデプロイには内部的に Heat が使用されます。 そのためオーバークラウドの設定のカスタマイズ等には Heat の環境ファイルと呼ばれるものを作成します。 以下の手順では必要最低限の環境ファイルを作成しています。 実際の環境ではカスタマイズすべき点がたくさんあるはずですので、必要な設定の数や環境ファイルの数はもっと多くなるでしょう。

$ cat << EOF > /home/stack/templates/my-environment-file.yaml
parameter_defaults:
  ComputeParameters:
    KernelArgs: "tsx=off"
  CloudDomain: "example.com"
EOF

$ cat << EOF > /home/stack/templates/inject-trust-anchor-hiera.yaml
parameter_defaults:
  CAMap:
    undercloud-ca:
      content: |
$(awk '/BEGIN CERTIFICATE/,/END CERTIFICATE/' /etc/pki/ca-trust/source/anchors/cm-local-ca.pem |sed 's/^/        /g')
EOF

以下のコマンドでオーバークラウドのデプロイを行います。 これまでの手順で作成されたファイルを参照していることに注目してください。 これらの環境ファイルの設定を元にオーバークラウドに Nova や Neutron などといったコンポーネントがデプロイされます。 数時間かかる場合があるので気長に待ちましょう。

$ openstack overcloud deploy --templates \
  -n /home/stack/templates/network_data.yaml \
  -e /home/stack/templates/overcloud-baremetal-deployed.yaml \
  -e /home/stack/templates/overcloud-networks-deployed.yaml \
  -e /home/stack/templates/overcloud-vip-deployed.yaml \
  -e /home/stack/containers-prepare-parameter.yaml \
  -e /home/stack/templates/inject-trust-anchor-hiera.yaml \
  -e /home/stack/templates/my-environment-file.yaml \
  --ntp-server 192.168.24.254

デプロイが完了すると、ホームディレクトリ直下に overcloudrc というファイルが作成されます。 本ファイルには、オーバークラウドの OpenStack へのアクセスに必要な情報(エンドポイントの URL やユーザID・パスワードなど)が格納されています。 CLI でオーバークラウドの OpenStack にアクセスして操作するには、以下のように overcloudrc を読み込んでからコマンドを実行する必要があります。

$ source overcloudrc
$ openstack endpoint list

実際にインスタンスを作成してみる

OpenStack がデプロイ出来たので実際にインスタンスを作成してみましょう。 詳細は割愛しますが、以下の一連のコマンドではインスタンス作成に必要な仮想ネットワークやフレーバーなどを作成し、インスタンスを作成しています。 イメージにはテスト用の OS である CirrOS を使用しています。

$ curl -L -O https://download.cirros-cloud.net/0.6.2/cirros-0.6.2-x86_64-disk.img
$ source overcloudrc
$ openstack image create --public cirros-0.6.2 --file cirros-0.6.2-x86_64-disk.img --disk-format qcow2
$ openstack flavor create --public --ram 1024 --disk 1 --vcpus 1 small
$ openstack security group create my_security_group
$ openstack security group rule create my_security_group --protocol icmp
$ openstack security group rule create my_security_group --protocol tcp --dst-port 22
$ openstack keypair create my_keypair > ~/.ssh/instance.key
$ chmod 400 ~/.ssh/instance.key
$ openstack network create external_network --external --provider-network-type flat --provider-physical-network datacentre
$ openstack subnet create external_subnet --network external_network --dhcp --allocation-pool start=10.0.0.150,end=10.0.0.200 --gateway 10.0.0.1 --subnet-range 10.0.0.0/24
$ openstack network create private_network
$ openstack subnet create --network private_network --subnet-range 192.168.0.0/24 private_subnet
$ openstack router create my_router 
$ openstack router set --external-gateway external_network my_router
$ openstack router add subnet my_router private_subnet
$ openstack server create --flavor small --image cirros-0.6.2 --network private_network --security-group my_security_group --key-name my_keypair my_instance
$ openstack floating ip create external_network --floating-ip-address 10.0.0.160
$ openstack server add floating ip my_instance 10.0.0.160
$ openstack server show my_instance

上記手順でインスタンスが作成できたら、以下のコマンドで SSH 接続が可能です。

$ ssh -i ~/.ssh/instance.key cirros@10.0.0.160

※2023/12/22 追記:ログインユーザが間違っておりましたので正しいユーザ cirros へ変更しました。

おわりに

必要最小限のカスタマイズで OpenStack をデプロイしてみましたが、それでも複雑で長い手順であることがわかるかと思います。 まずは上記手順を実際に試してみてデプロイの流れを掴んでみるのがとっかかりとして良いかと思います。 大まなか手順がつかめたらネットワーク構成をカスタマイズしてみる、ノード構成を変更してみる、設定変更を加えてみるなどするとより理解が深まるかもしれません。

より深く知りたいところがあれば弊社の Installing and managing Red Hat OpenStack Platform with directorその他の RHOSP のドキュメントも参考にしてみてください。 例えばセキュリティに関する強化をしたい場合は Hardening Red Hat OpenStack Platform、IPv6 を使いたい場合は Configuring IPv6 networking for the overcloud、外部の Ceph ストレージと連携したい場合は Integrating the overcloud with an existing Red Hat Ceph Storage Cluster など、目的に応じてデプロイメントに関する手順が各ドキュメントに点在していることにもご注意ください。 本ブログの手順で一度デプロイできたら RHOSP のドキュメントの一覧を眺めてみて、どこに何の説明がありそうかの土地勘を掴んでいただくと、必要な設定手順を見つけやすくなるかと思います。

また弊社のドキュメントの説明だけではよくわからないという場合は、アップストリームの TripleO のドキュメント なども読んでいただくと、同じ事柄が弊社のドキュメントとは違う言葉・文章で説明されていて理解が深まることがあるかと思います。

また本手順で実行した openstack overcloud deploy などのコマンドはシェルスクリプトのファイルに書いていただき、設定ファイルやテンプレートファイルと併せて git で管理しておくと、バージョン管理や環境を跨いでの再利用などがしやすく良いでしょう。

もし手順中のどこかのコマンドでエラーが発生した場合はトラブルシュートのためのドキュメントを参考にトラブルシュートしてみてください。

なお本手順では KVM 仮想マシンを作りその上に OpenStack を構築しましたが、これと同じことを自動で行ってくれる infrared というツールもあります。デプロイ手順を確認するよりも実際に動く環境が欲しいという場合はこちらを利用すると良いでしょう。infrared については次回以降また取り上げることができればと考えています。

なお本記事では Director(TripleO)でのデプロイ手順を紹介いたしましたが、次のメジャーリリースである RHOSP 18 では OpenStack のコントロールプレーンのコンポーネントがベアメタルではなく OpenShift 上で動く構成となったことにより、Director の廃止が決まっております。RHOSP 18 でのデプロイ手順は Development Preview という扱いでリリースされており、デプロイの手順のドキュメントも公開されておりますので、先駆けて確認したい方はぜひこちらのページをご確認ください。

本記事が Director の理解の一助になることを願います。

* 各記事は著者の見解によるものでありその所属組織を代表する公式なものではありません。その内容については非公式見解を含みます。