7. 複数仮想マシンによるクラスタの作成例¶
mdx上にデプロイした複数の仮想マシンを使って簡単なクラスタを構築する例について説明します。
7.1. Ansibleとその概要¶
ここでは、そうしたプロビジョニングツールのひとつである Ansible を使ってmdx上に複数のVMを展開して設定する例を紹介します。
Ansibleを実行するために最低限必要なファイルは、
- playbook
設定するマシンの中で実行する処理を記述したYAML形式のファイル
- inventory
設定を行う対象のマシンのIPアドレスや付加する情報などを記述したファイル
の2つです。
deploy-jupyter.yaml
を用意し、その中にはJupyterlabをデプロイするために必要な処理を記述します。hosts
というファイルを用意し、 ansible-playbook -i hosts deploy-jupyter.yaml
と打てば、複数のVMにJupyterlabを立ち上げることができます。ansible-playbook
コマンド (ないし ansible
コマンド)を実行して他のホストを設定/制御するホストをControl node、逆にControl nodeから設定/制御されるホスト(この場合はVM)をManaged nodeと呼びます。 +---------+
playbook.yaml | |
hosts | Managed |
+---------+ +----->| node1 |
| | | | |
| Control | ssh | +---------+
| node +-----+
| | | +---------+
+---------+ | | |
| | Managed |
+----->| node2 |
| |
+---------+
ansible-playbook
コマンドを実行すると、ssh越しに2台のManaged Nodeが設定されます。7.2. https://github.com/mdx-jp/machine-configs¶
注釈
現在全てのplaybookは ubuntu server 20.04 テンプレートから作成したVMに対して実行することを想定しています。
ansible-playbook
を実行するVM (ControlNode)を1台と、クラスタになるVM (Managed Node)を必要な台数作成します。下の図では、 ansible-playbook
を実行する test というノードをubuntu-2004-serverテンプレートからデプロイし、続いてクラスタになる vm1 から vm8 までの8台のVMを、同様にubuntu-2004-serverテンプレートから、VMデプロイ時の仮想マシン名に vm[1-8]
と入力することで一度にデプロイしました。

ACLの設定やssh公開鍵の投入などは、 ネットワーク設定 や 仮想マシン利用の流れ を参照し、利用者自身の環境に合わせて実施してください。
OpenMPIやLustreストレージにRDMAで接続する場合は、ストレージネットワークを SR-IOV で作成してください。
7.3. クラスタの構築: 準備編¶
7.3.1. Ansibleのインストール¶
ansible-playbook
を実行するVM(上記例では test という名前のVM)にログインし、Ansibleをインストールします (最初にわかりやすさのためにホスト名を変更しています)。ssh -A
)などを用いて、このホストから各VMにmdxuserでsshできるようにしてください。mdxuser@ubuntu-2004:~$ sudo hostnamectl set-hostname ansible
mdxuser@ubuntu-2004:~$ bash
mdxuser@ansible:~$ sudo apt install ansible
Reading package lists... Done
Building dependency tree
Reading state information... Done
Suggested packages:
cowsay sshpass
The following NEW packages will be installed:
ansible
0 upgraded, 1 newly installed, 0 to remove and 17 not upgraded.
Need to get 5794 kB of archives.
After this operation, 58.0 MB of additional disk space will be used.
Get:1 http://jp.archive.ubuntu.com/ubuntu focal/universe amd64 ansible all 2.9.6+dfsg-1 [5794 kB]
Fetched 5794 kB in 1s (4666 kB/s)
Selecting previously unselected package ansible.
(Reading database ... 125879 files and directories currently installed.)
Preparing to unpack .../ansible_2.9.6+dfsg-1_all.deb ...
Unpacking ansible (2.9.6+dfsg-1) ...
Setting up ansible (2.9.6+dfsg-1) ...
Processing triggers for man-db (2.9.1-1) ...
7.3.2. machine-configsレポジトリの取得¶
次にplaybookが用意されている machine-configs のGitレポジトリをクローンしてそこに移動します。
mdxuser@ansible:~$ git clone https://github.com/mdx-jp/machine-configs
Cloning into 'machine-configs'...
remote: Enumerating objects: 785, done.
remote: Counting objects: 100% (785/785), done.
remote: Compressing objects: 100% (510/510), done.
remote: Total 785 (delta 376), reused 622 (delta 214), pack-reused 0
Receiving objects: 100% (785/785), 119.50 KiB | 9.96 MiB/s, done.
Resolving deltas: 100% (376/376), done.
mdxuser@ansible:~$ cd machine-configs/
mdxuser@ansible:~/machine-configs$ ls
ansible.cfg mdxcsv2inventory.py playbook.yml roles
files mdxpasswdinit.py README.md vars
7.3.3. inventoryファイルの作成¶
mdxcsv2inventory.py
が用意されています。mdxcsv2inventory.py
にダウンロードしてきたCSVファイルを与えると、CSVファイルに記載されているVMをManaged Nodeとするinventoryファイルを生成します。
mdxuser@ansible:~/machine-configs$ ./mdxcsv2inventory.py user-portal-vm-info.csv
[all:vars]
ansible_user=mdxuser
ansible_remote_tmp=/tmp/.ansible
ethipv4prefix=10.13.200.0/21
rdmaipv4prefix=10.141.200.0/21
ethipv6prefix=2001:2f8:1041:21e::/64
[default]
10.13.204.85 hostname=vm1 ethipv4=10.13.204.85 rdmaipv4=10.141.200.147
10.13.204.83 hostname=vm2 ethipv4=10.13.204.83 rdmaipv4=10.141.200.146
10.13.204.89 hostname=vm3 ethipv4=10.13.204.89 rdmaipv4=10.141.204.70
10.13.200.158 hostname=vm4 ethipv4=10.13.200.158 rdmaipv4=10.141.204.63
10.13.204.90 hostname=vm5 ethipv4=10.13.204.90 rdmaipv4=10.141.200.149
10.13.204.87 hostname=vm6 ethipv4=10.13.204.87 rdmaipv4=10.141.200.150
10.13.204.84 hostname=vm7 ethipv4=10.13.204.84 rdmaipv4=10.141.204.64
10.13.204.86 hostname=vm8 ethipv4=10.13.204.86 rdmaipv4=10.141.204.67
[default]
という表記はグループを示しています。Ansibleでは、inventoryでホストをグループにまとめ、playbookの中ではグループに対してどのような処理を行うかを記述します。mdxcsv2inventory.py
は全てのVMのアドレスを記載したグループとしてこの [default]
を作成しています。hosts.ini
というファイルに保存しておきます。mdxuser@ansible:~/machine-configs$ ./mdxcsv2inventory.py user-portal-vm-info.csv > hosts.ini
7.3.4. Ansibleを実行する前の事前準備¶
mdxpasswordinit.py
を使って、inventoryファイルの [default]
グループのホストに対して一気に初期パスワードを設定します。mdxuser@ansible:~/machine-configs$ ./mdxpasswdinit.py ./hosts.ini
Target hosts: 10.13.204.85, 10.13.204.83, 10.13.204.89, 10.13.200.158, 10.13.204.90, 10.13.204.87, 10.13.204.84, 10.13.204.86
New Password:
Retype New Password:
initializing the first password...
10.13.204.85: Success
10.13.204.83: Success
10.13.204.89: Success
10.13.200.158: Success
10.13.204.90: Success
10.13.204.87: Success
10.13.204.84: Success
10.13.204.86: Success
この操作はVMに対して一回だけ実行すれば大丈夫です。
7.4. Playbookの準備と実行¶
現在machine-configsが提供するVMへの操作は、下記の通りです。
Role |
Desciprition |
---|---|
common |
ホスト名や/etc/hostsを設定し、指定したパッケージをインストールする |
desktop_common |
xrdpをインストールする |
nfs_server |
VMをNFSサーバにし、/homeをexportする |
nfs_client |
NFS越しに/homeをマウントする |
ldap_server |
VMをLDAPサーバにし、LDAPアカウントを作成する |
ldap_client |
VMをLDAPクライアントにし、LDAPサーバを参照するように設定する |
jupyter |
jupyter labをインストールし、デーモンとして起動する |
reverse_proxy |
VMをリバースプロキシにし、特定ポートへのアクセスを他のVMの特定ポートに転送する |
mpi |
OpenMPIを使えるように設定する |
playbook.yml
でホストに対してRoleを適用するブロックは下記のようになっています。- name: setup NFS server
hosts: nfsserver
roles:
- nfs_server
nfsserver
というホストのグループに対して、 nfs_server
のRoleを適用する、という記述です。mdxcsv2inventory.py
はデフォルトでは [default]
というグループしか作成しません。nfsserver
というグループを作成しなければなりません。[nfsserver]
というセクションを追加しても大丈夫ですが、下記のように mdxcsv2inventory.py
を使用してグループを作成することもできます。mdxuser@ansible:~/machine-configs$ ./mdxcsv2inventory.py user-portal-vm-info.csv -g nfsserver vm1
[all:vars]
ansible_user=mdxuser
ansible_remote_tmp=/tmp/.ansible
ethipv4prefix=10.13.200.0/21
rdmaipv4prefix=10.141.200.0/21
ethipv6prefix=2001:2f8:1041:21e::/64
[default]
10.13.204.85 hostname=vm1 ethipv4=10.13.204.85 rdmaipv4=10.141.200.147
10.13.204.83 hostname=vm2 ethipv4=10.13.204.83 rdmaipv4=10.141.200.146
10.13.204.89 hostname=vm3 ethipv4=10.13.204.89 rdmaipv4=10.141.204.70
10.13.200.158 hostname=vm4 ethipv4=10.13.200.158 rdmaipv4=10.141.204.63
10.13.204.90 hostname=vm5 ethipv4=10.13.204.90 rdmaipv4=10.141.200.149
10.13.204.87 hostname=vm6 ethipv4=10.13.204.87 rdmaipv4=10.141.200.150
10.13.204.84 hostname=vm7 ethipv4=10.13.204.84 rdmaipv4=10.141.204.64
10.13.204.86 hostname=vm8 ethipv4=10.13.204.86 rdmaipv4=10.141.204.67
[nfsserver]
# group with regexp 'vm1'
10.13.204.85 hostname=vm1 ethipv4=10.13.204.85 rdmaipv4=10.141.200.147
mdxuser@ansible:~/machine-configs$ ./mdxcsv2inventory.py user-portal-vm-info.csv -g nfsserver vm1 > hosts.ini
mdxcsv2inventory.py
の -g [GROUPNAME] [VMNAME]
オプションを使うことで、指定したVMの所属する任意の名前のホストグループを作成することができます。[VMNAME]
の部分は正規表現になっているので、複数のVMが所属するグループを作成することもできます。[nfsserver]
の他にも playbook.yml にあるように、LDAPサーバにするには [ldapserver]
グループを、リバースプロキシにするには [reverproxy]
グループを上記の手順で作成してください。
playbook.yml
自体を編集して、デプロイしたい環境に合わせて、不必要なRoleの適用箇所をコメントアウトしてください。desktop_common
は必要無いかもしれません。inventoryの作成と playbook.yml
の編集が終わったら、下記のコマンドをすると、Ansibleが全VMに設定を実施します。
mdxuser@ansible:~/machine-configs$ ansible-playbook -i hosts.ini playbook.yml
7.5. machine-configsが提供するRole¶
ここでは、machine-configsに用意されているRoleについて説明します。
7.5.1. common¶
hostname
などの変数のものです。7.5.2. desktop_common¶
7.5.3. nfs_server¶
7.5.4. nfs_client¶
マウントするNFSサーバは、 [nfsserver]
グループの先頭にあるVMになります。
7.5.5. ldap_server¶
machine-configs/files
ディレクトリ配下に ldap_groups.csv
と ldap_users.csv
というファイルを作成してください。7.5.6. ldap_client¶
参照するLDAPサーバは、 [ldapserver]
グループの先頭にあるVMになります。
7.5.7. jupyter¶
7.5.8. reverse_proxy¶
[default]
グループのVMについて、自身の 8000 + n
ポートへのアクセスを各VMの8888番ポートに転送します。 User
|
v
mdx Global IPv4
Address
|
|
+---------+ |
| Nginx | |
| (VM) | |
+----+----+ |
| ^ |
| +-----+
| Ethernet Network (Private Address)
+--------------------+------------------+------------------+
| | | |
v v v v
+--------------+ +--------------+ +--------------+ +--------------+
| Jupyterlab | | Jupyterlab | | Jupyterlab | | Jupyterlab | ...
| (VM1) | | (VM2) | | (VM3) | | (VM4) |
+--------------+ +--------------+ +--------------+ +--------------+
reverse_proxy
Roleを適用したVMに DNAT を使ってグローバルIPv4アドレスをマッピングすることで、外部から各VMのjupyter labにアクセスすることができるようになります。DNATをマッピングしたら、ブラウザで http://[DNATのアドレス]:8001 にアクセスすると、上の図のVM1のJupyterlabに、 http://[DNATのアドレス]:8002 にアクセスすれば、VM2のJupyterlabにアクセスすることができます。
なお、各Jupyterlabは認証無しで起動するので、リバースプロキシになるNginxのVMには適切な ACL を設定してください。
vars/reverse_proxy.yml を編集することで、バックエンドになるVMのグループ(デフォルトは [default]
)やプロキシする先のポート番号(デフォルトは 8888
)を変更することができます。