📝

Azure CycleCloud で Slurm クラスタを展開/活用

に公開

はじめに

オンプレミス環境で High Performance Computing(以降、HPC)クラスタを構築する場合、オープンソースでは xCAT や Warewulf、有償製品では NVIDIA(旧 Bright Computing)の Bright Cluster Manager などのオーケストレーションツールが一般的に利用されています。一方、Microsoft Azure では Azure CycleCloud が HPC クラスタの構築および管理を担うサービスとして提供されています。
※もちろん、CycleCloud を利用せずに IaaS ベースでクラスタを構築することも可能です。

CycleCloud 自体は 無償で利用可能で、ジョブスケジューラとして Slurm、OpenPBS、LSF、Grid Engine などに幅広く対応しています。また、展開したクラスタはジョブ負荷に応じて オートスケールさせることができ、計算需要に応じて柔軟に伸縮する HPC 環境を実現できます。

本記事では、Azure CycleCloud を用いて Slurm クラスタを構築し、Ethernet 経由で 2 ノード MPI ジョブを実行するまでの一連の手順を解説します。

対象読者:クラウドHPCを業務に活用したい方、Azure 上で Slurm クラスタを構築・検証したい方

構築する環境

  • クラウド基盤: Microsoft Azure
  • HPC クラスタ管理: Azure CycleCloud
  • OS: AlmaLinux 8.10(ヘッドノード/計算ノード)
  • ジョブスケジューラ: Slurm

    今回作成するCycleCloudサーバとSlurmクラスタのシステム概要

本記事で構築する環境は検証用途を想定しています。実際の業務利用にあたっては、所属組織のセキュリティポリシーや運用要件に応じて適宜調整してください。

1. 事前準備

まず、Azure 上で HPC クラスタを構築するための 前提リソースを Azure CLI で作成します。

  • 対象サブスクリプション: 11111111-2222-3333-4444-555555555555
  • 作成リージョン: japaneast
  • 企業ポリシーに合わせ、Storage accountへのアクセスは、Private Endpoint 経由
  • 実行環境: Azure CLI が利用可能 (az コマンド)

事前準備では、Azure 上で HPC クラスタを構築するための前提リソースを用意する手順で、以下の設定を行います。

1-1. 構築する環境を定義
1-2. Azure環境へログイン
1-3. リソースグループ作成
1-4. ユーザー割り当てマネージド IDの作成
1-5. Managed IDへロールを割り当て(RBAC)
1-6. VNet, Subnet, Network Security Group(NSG)の作成
1-7. NAT Gateway の作成 & サブネットへの割り当て
1-8. CycleCloud 管理用 Storage Account 作成

1-1. 構築する環境を定義

環境に合わせて以下変数を定義して、env_cyclecloud.txt へ保存します。

$ vim ./env_rg_hpc.txt
# ===== Azure環境 =====
SUBS_ID="11111111-2222-3333-4444-555555555555"   # サブスクリプションID
REGION="japaneast"                               # デプロイ先リージョン
RESOURCE_GROUP="rg-hpc"                          # リソースグループ名
MANAGED_ID="mngdid-ccserver"                     # ユーザ割り当てマネージドID名

VNET_NAME="vnet-hpc"                             # 仮想ネットワーク名
VNET_RANGE="10.0.0.0/16"                         # VNet アドレス範囲

# ===== ネットワーク関連 =====
SUBNET_CLUSTER_NAME="subnet-cluster"             # クラスタ用サブネット名
SUBNET_CLUSTER_RANGE="10.0.0.0/24"               # クラスタ用サブネット範囲
NSG_CLUSTER_NAME="nsg-subnet-cluster"            # クラスタ用サブネットのNSG名

SUBNET_ANF_NAME="subnet-anf"                     # ANF用サブネット名
SUBNET_ANF_RANGE="10.0.50.0/28"                  # ANF 用サブネット範囲
NSG_ANF_NAME="nsg-subnet-anf"                    # ANF 用サブネットのNSG名

DUMMY_SUBNET_NAME="dummy"                        # 作成時だけ必要なダミーサブネット名
DUMMY_SUBNET_RANGE="10.0.255.0/24"               # ダミーサブネット範囲

# ===== NAT Gateway =====
NATGW_NAME="natgw-hpc"                           # NAT Gateway 名
NATGW_PIP="pip-natgw-hpc"                        # NATGW に割り当てる Public IP

# ===== CycleCloud用ストレージ =====
STGACCT_CC="stgacctccservermngt"           # CycleCloud管理用 Storage Account 名
PEP_STGACC_CC="pep-stgacctccservermngt"    # Storage Account の Private Endpoint 名
PEP_CONN_NAME="stgacctccservermngt-blob-conn"             # Private Endpoint 接続名
PRIVATE_DNSZONE_NAME="privatelink.blob.core.windows.net"  # Private DNS ゾーン名
PRIVATE_DNSZONE_LINKNAME="link-vnet-hpc"                  # DNS ゾーンリンク名

# ===== Azure NetApp Files =====
ANF_ACCOUNT="anf-hpc"               # ANFアカウント名
ANF_POOL="anf-hpc-pool01"           # ANF容量プール名
ANF_VOLUME="anf-hpc-vol01"          # ANF ボリューム名
ANF_TIER="Flexible"                 # ANFサービス階層(Flexible)
ANF_POOL_SIZE=1                     # 作成するPoolのサイズをTiBで指定
ANF_POOL_THPT=128                   # 作成するPoolのスループット性能をMB/TiBで指定
ANF_VOLUME_SIZE=1024                # 作成するVolumeサイズをGiB単位で指定
ANF_VOLUME_THPT=128                 # 作成するVolumeのスループット性能をMB/TiBで指定

# ===== CycleCloudサーバ =====
CC_VM_NAME="ccserver"               # CycleCloudサーバ名
NIC_CC="nic-ccserver"               # CycleCloudサーバのNIC名
IMAGE_CC="azurecyclecloud:azure-cyclecloud:cyclecloud8-gen2:latest"   # CycleCloudサーバOSイメージ URN
CC_ADMIN="azureuser"                               # CycleCloud の管理者ユーザ名
CC_ADMIN_SSH_PUBKEY="ssh-rsa AAA.. kuraishi@xyz"   # 管理者SSH公開鍵
VM_SIZE_CC="Standard_D4as_v5"                      # CycleCloudサーバのVMサイズ

確認後、反映。

$ . ./env_rg_hpc.txt   # もしくは、source ./env_rg_hpc.txt
$ echo $SUBS_ID

1-2. Azure環境へログイン

Azure CLIもしくはAzure Portalから利用可能なCloud shellを用いてAzure環境へログインして下さい。

$ az login
$ az account set --subscription "$SUBS_ID"

1-3. リソースグループ作成

$ az group create \
  --name "$RESOURCE_GROUP" \
  --location "$REGION"

1-4. ユーザー割り当てマネージドIDの作成

# マネージドID作成
$ az identity create \
  --name "$MANAGED_ID" \
  --resource-group "$RESOURCE_GROUP"

# principalId を変数に保持
$ ID_PRINCIPAL_ID=$(az identity show \
  --name "$MANAGED_ID" \
  --resource-group "$RESOURCE_GROUP" \
  --query principalId -o tsv)

1-5. Managed IDへロールを割り当て(RBAC)

  • サブスクリプション レベル: Contributor(共同作成者)
  • リソースグループ レベル: Storage Blob Data Contributor
# (A) サブスクリプションレベル: Contributor
$ az role assignment create \
  --assignee "$ID_PRINCIPAL_ID" \
  --role "Contributor" \
  --scope "/subscriptions/$SUBS_ID"

# (B) リソースグループレベル: Storage Blob Data Contributor
$ az role assignment create \
  --assignee "$ID_PRINCIPAL_ID" \
  --role "Storage Blob Data Contributor" \
  --scope "/subscriptions/$SUBS_ID/resourceGroups/$RESOURCE_GROUP"

Tips: 付与直後は反映に数分かかることがあります。az role assignment list --assignee "$ID_PRINCIPAL_ID" で確認してください。

1-6. VNet, Subnet, Network Security Group(NSG)の作成

# 1) ダミーサブネット付きでVNet作成
$ az network vnet create \
  --resource-group "$RESOURCE_GROUP" \
  --name "$VNET_NAME" \
  --location "$REGION" \
  --address-prefixes "$VNET_RANGE" \
  --subnet-name "$DUMMY_SUBNET_NAME" \
  --subnet-prefix "$DUMMY_SUBNET_RANGE"

# 2) NSG を2本作成(cluster / anf)
$ az network nsg create \
  --resource-group "$RESOURCE_GROUP" \
  --name "$NSG_CLUSTER_NAME" \
  --location "$REGION"

$ az network nsg create \
  --resource-group "$RESOURCE_GROUP" \
  --name "$NSG_ANF_NAME" \
  --location "$REGION"

# 3) 目的のサブネットを NSG 紐付けで作成
$ az network vnet subnet create \
  --resource-group "$RESOURCE_GROUP" \
  --vnet-name "$VNET_NAME" \
  --name "$SUBNET_CLUSTER_NAME" \
  --address-prefixes "$SUBNET_CLUSTER_RANGE" \
  --network-security-group "$NSG_CLUSTER_NAME"

$ az network vnet subnet create \
  --resource-group "$RESOURCE_GROUP" \
  --vnet-name "$VNET_NAME" \
  --name "$SUBNET_ANF_NAME" \
  --address-prefixes "$SUBNET_ANF_RANGE" \
  --network-security-group "$NSG_ANF_NAME"

# 4) ダミーサブネット削除
$ az network vnet subnet delete \
  --resource-group "$RESOURCE_GROUP" \
  --vnet-name "$VNET_NAME" \
  --name "$DUMMY_SUBNET_NAME"

# 作成結果の確認
$ az network vnet show -g "$RESOURCE_GROUP" -n "$VNET_NAME" -o table
$ az network vnet subnet list -g "$RESOURCE_GROUP" --vnet-name "$VNET_NAME" -o table

任意(例): cluster01 の NSG に SSH を許可するルールを追加

$ az network nsg rule create \
  --resource-group "$RESOURCE_GROUP" \
  --nsg-name "$NSG_CLUSTER_NAME" \
  --name Allow-SSH \
  --priority 1000 \
  --direction Inbound \
  --access Allow \
  --protocol Tcp \
  --source-address-prefixes '*' \
  --source-port-ranges '*' \
  --destination-address-prefixes '*' \
  --destination-port-ranges 22

1-7. NAT Gateway の作成 & サブネットへの割り当て

# Public IP 作成
$ az network public-ip create \
  --resource-group "$RESOURCE_GROUP" \
  --name "$NATGW_PIP" \
  --sku Standard \
  --allocation-method Static

# NAT Gateway 作成
$ az network nat gateway create \
  --resource-group "$RESOURCE_GROUP" \
  --name "$NATGW_NAME" \
  --public-ip-addresses "$NATGW_PIP" \
  --idle-timeout 10

# サブネットに NATGW を付与
$ az network vnet subnet update \
  --resource-group "$RESOURCE_GROUP" \
  --vnet-name "$VNET_NAME" \
  --name "$SUBNET_CLUSTER_NAME" \
  --nat-gateway "$NATGW_NAME"

$ az network vnet subnet update \
  --resource-group "$RESOURCE_GROUP" \
  --vnet-name "$VNET_NAME" \
  --name "$SUBNET_ANF_NAME" \
  --nat-gateway "$NATGW_NAME"

1-8. CycleCloud 管理用 Storage Account 作成

# (a) Storage Account(Blob)
$ az storage account create \
  --name "$STGACCT_CC" \
  --resource-group "$RESOURCE_GROUP" \
  --location "$REGION" \
  --sku Standard_LRS \
  --kind StorageV2 \
  --allow-blob-public-access false \
  --public-network-access Disabled

# (b) Private DNS ゾーン(Blob)
$ az network private-dns zone create \
  --resource-group "$RESOURCE_GROUP" \
  --name "$PRIVATE_DNSZONE_NAME"

# (c) VNet を Private DNS ゾーンへリンク
$ az network private-dns link vnet create \
  --resource-group "$RESOURCE_GROUP" \
  --zone-name "$PRIVATE_DNSZONE_NAME" \
  --name "$PRIVATE_DNSZONE_LINKNAME" \
  --virtual-network "$VNET_NAME" \
  --registration-enabled false

# (d) Private Endpoint(Blob グループ)
$ STG_ID=$(az storage account show \
  --name "$STGACCT_CC" \
  --resource-group "$RESOURCE_GROUP" \
  --query id -o tsv)

$ az network private-endpoint create \
  --resource-group "$RESOURCE_GROUP" \
  --name "$PEP_STGACC_CC" \
  --vnet-name "$VNET_NAME" \
  --subnet "$SUBNET_CLUSTER_NAME" \
  --private-connection-resource-id "$STG_ID" \
  --group-id blob \
  --connection-name "$PEP_CONN_NAME"

$ az network private-endpoint dns-zone-group create \
  --resource-group "$RESOURCE_GROUP" \
  --endpoint-name "$PEP_STGACC_CC" \
  --name "default" \
  --private-dns-zone "$PRIVATE_DNSZONE_NAME" \
  --zone-name "blob"
  
# (e) Private DNS A レコード登録
$ PEP_IP=$(az network private-endpoint show \
  --resource-group "$RESOURCE_GROUP" \
  --name "$PEP_STGACC_CC" \
  --query 'customDnsConfigs[0].ipAddresses[0]' -o tsv)

$ az network private-dns record-set a create \
  --resource-group "$RESOURCE_GROUP" \
  --zone-name "$PRIVATE_DNSZONE_NAME" \
  --name "$STGACCT_CC"

$ az network private-dns record-set a add-record \
  --resource-group "$RESOURCE_GROUP" \
  --zone-name "$PRIVATE_DNSZONE_NAME" \
  --record-set-name "$STGACCT_CC" \
  --ipv4-address "$PEP_IP"

# (f) Private DNS A レコードが作成されたことを確認
$ az network private-dns record-set a list \
  --resource-group "$RESOURCE_GROUP" \
  --zone-name "$PRIVATE_DNSZONE_NAME" \
  -o table

nslookup ${STGACCT_CC}.blob.core.windows.net と
curl -I https://${STGACCT_CC}.blob.core.windows.net を実行して
名前解決ができることを確認する。

「事前準備」でのトラブルシューティング Tips

  • RBAC の伝播遅延: 付与直後は反映に時間がかかることがあります。az role assignment list で確認して下さい。
  • Storage Account名の重複: グローバルで一意である必要があります。作成に失敗する場合は別名を指定して下さい。
  • Private DNS 解決: VM が、今回作成したVnet(この例では vnet-hpc01)に接続されており、<storageaccount>.blob.core.windows.net が Private Endpoint の IP を解決するか nslookup で確認して下さい。
  • NAT Gateway の経路: Public IP を持たない VM のアウトバウンド通信が NAT Gateway 経由になっているか確認してください。

2. 共有ストレージ Azure NetApp Files(ANF)の展開

次に ANF を Flexible Pool/Flexible Volume(1TiB)構成で Azure CLI によりデプロイする手順を説明します。

以下のステップを順番に実施します:
2-1. Microsoft.NetApp Resource Provider の登録
2-2. ANF 用サブネットを Microsoft.NetApp/volumes に委任
2-3. NetApp アカウントの作成
2-4. Flexible Pool(容量プール)の作成
2-5. Flexible Volume(1TiB)の作成

2-1. Microsoft.NetApp Resource Provider の登録

ANF を利用するには、まずサブスクリプションに Resource Provider を登録する必要があります。

$ az provider register --namespace Microsoft.NetApp --wait

登録状況の確認:

$ az provider show --namespace Microsoft.NetApp -o table

RegistrationStateRegistered であることを確認します。

2-2. ANF用サブネットを Microsoft.NetApp/volumes に委任

ANF は 専用の委任サブネットが必要です。既存の subnet-anf を NetApp 用に委任します。

$ az network vnet subnet update \
  --resource-group "$RESOURCE_GROUP" \
  --vnet-name "$VNET_NAME" \
  --name "$SUBNET_ANF_NAME" \
  --delegations Microsoft.NetApp/volumes

# 確認("provisioningState": "Succeeded"になっていれば正常)
$ az network vnet subnet show \
  --resource-group "$RESOURCE_GROUP" \
  --vnet-name "$VNET_NAME" \
  --name "$SUBNET_ANF_NAME" \
  --query delegations

2-3. NetApp アカウントの作成

$ az netappfiles account create \
  --resource-group "$RESOURCE_GROUP" \
  --location "$REGION" \
  --account-name "$ANF_ACCOUNT"

2-4. Flexible Pool(容量プール)の作成

Flexible レベルを利用する場合、SKU に Flexible(容量は実際の Volume の消費に応じて課金)を指定します。

$ az netappfiles pool create \
  --resource-group "$RESOURCE_GROUP" \
  --location "$REGION" \
  --account-name "$ANF_ACCOUNT" \
  --pool-name "$ANF_POOL" \
  --service-level "$ANF_TIER" \
  --qos-type Manual \
  --custom-throughput-mibps "$ANF_POOL_THPT" \
  --size "$ANF_POOL_SIZE" \
  --cool-access false

--size 1 は 1TiB を表します。

2-5. Flexible Volume(1TiB)の作成

ANF Volume は次の要素が必要です:

  • NetApp アカウント
  • Capacity Pool
  • Subnet(委任済み)
  • Volume 名
  • サイズ(GiB 単位)
    今回は 1TiB = 1024GiB で作成します。
$ ANF_SUBNET_ID=$(az network vnet subnet show \
  --resource-group "$RESOURCE_GROUP" \
  --vnet-name "$VNET_NAME" \
  --name "$SUBNET_ANF_NAME" \
  --query id -o tsv)

$ az netappfiles volume create  
  --resource-group "$RESOURCE_GROUP" --location "$REGION" \
  --account-name "$ANF_ACCOUNT" --pool-name "$ANF_POOL" \
  --service-level  Flexible --volume-name "$ANF_VOLUME" \
  --file-path "$ANF_VOLUME"  --protocol-types NFSv4.1 \
  --subnet-id "$ANF_SUBNET_ID"  --allowed-clients "$SUBNET_CLUSTER_RANGE" \
  --usage-threshold "$ANF_VOLUME_SIZE" --network-features Standard  \
  --throughput-mibps "$ANF_VOLUME_THPT"

これで、Flexible レベルの ANF 1TiB がデプロイできました。ここで作成したANF ボリュームは後で展開するSlurmクラスタのヘッドノード、計算ノードからNFSでマウントしてデータやアプリケーション、ライブラリなどを保存する領域として使用します。

補足

  • --usage-threshold はバイト単位。1TiB = 1024^4 = 1099511627776
  • --file-path は ANF Volume のエクスポートパス。
  • --protocol-types は NFSv4.1(HPC向け標準)。

3. Azure Marketplaceイメージで CycleCloud サーバ展開

Azure Marketplace に登録済みの CycleCloud 8.8 イメージ**を使用して、Azure CLI で CycleCloud サーバを展開します。イメージに CycleCloud がプリインストールされているため、cloud-init によるインストール工程は不要です。

以下のステップを順番に実施します:
3-1. NIC 作成(NSG 紐付け)
3-2. Marketplace イメージの URN を用意
3-3. CycleCloudサーバ用VMの作成
3-4. プライベート IP を固定(Static)
3-5. ユーザー割り当てマネージド ID を CycleCloudサーバに付与
3-6. CycleCloud サービスの確認

3-1. NIC作成(NSG 紐付け)

$ az network nic create \
  --resource-group "$RESOURCE_GROUP" \
  --name "$NIC_CC" \
  --vnet-name "$VNET_NAME" \
  --subnet "$SUBNET_CLUSTER_NAME" \
  --network-security-group "$NSG_CLUSTER_NAME"

3-2. Marketplace イメージ URN(例)

# 例: 事前に確認した URN を使用
$ IMAGE_CC="azurecyclecloud:azure-cyclecloud:cyclecloud8-gen2:8.8.120251212"

参考として az vm image list --publisher azurecyclecloud --offer azure-cyclecloud --all -o table などで該当リージョンの URN を確認してください。(2026/1/5時点で、 azurecyclecloud:azure-cyclecloud:cyclecloud8-gen2:8.8.120251212 が latest版)

3-3. CycleCloudサーバ用VMの作成

$ az vm create \
  --resource-group "$RESOURCE_GROUP" \
  --name "$CC_VM_NAME" \
  --nics "$NIC_CC" \
  --size "$VM_SIZE_CC" \
  --image "$IMAGE_CC" \
  --admin-username "$CC_ADMIN" \
  --ssh-key-values "$CC_ADMIN_SSH_PUBKEY" \
  --storage-sku Premium_LRS --os-disk-size-gb 128

補足

  • パブリック IP は付与していません。Bastion などでのプライベート接続を想定。
  • --ssh-key-values は複数鍵も指定可能(スペース/改行区切り)です。

3-4. プライベートIPを Static に固定

$ IPCONF=$(az network nic ip-config list \
  --resource-group "$RESOURCE_GROUP" \
  --nic-name "$NIC_CC" \
  --query '[0].name' -o tsv)

$ CUR_IP=$(az network nic ip-config show \
  --resource-group "$RESOURCE_GROUP" \
  --nic-name "$NIC_CC" \
  --name "$IPCONF" \
  --query 'privateIPAddress' -o tsv)

$ az network nic ip-config update \
  --resource-group "$RESOURCE_GROUP" \
  --nic-name "$NIC_CC" \
  --name "$IPCONF" \
  --private-ip-address "$CUR_IP"

3-5. ユーザー割り当てマネージドIDを VM に付与

$ MI_ID=$(az identity show \
  --resource-group "$RESOURCE_GROUP" \
  --name "$MANAGED_ID" \
  --query id -o tsv)

$ az vm identity assign \
  --resource-group "$RESOURCE_GROUP" \
  --name "$CC_VM_NAME" \
  --identities "$MI_ID"

用途に応じて、mngdid-cyclecloudserver に RBAC ロール(例:Storage Blob Data Contributor)を必要なスコープで付与してください。

3-6. CycleCloud サービスの状態確認

$ az vm run-command invoke --resource-group "$RESOURCE_GROUP" --name "$CC_VM_NAME" --command-id RunShellScript --scripts "systemctl status cycle_server_webserver --no-pager || true; systemctl status cycle_server --no-pager || true; journalctl -u cycle_server_webserver -n 50 --no-pager \|| true; ss -lntp | grep 9443 || true; which cyclecloud && cyclecloud --version || true; rpm -qa | grep -i cycle || true" --query 'value[0].message'

出力結果が以下であればCycleCloudサーバは正常に展開されています。

  • cycle_server_webserver Active: active (running)
  • cycle_server Active: active (running)
  • 9443 が LISTEN
  • cyclecloud --version が表示
  • stderr が空(致命的なエラーなし)

この条件が揃っていれば、CycleCloud サーバのコア機能は起動済みと判断して大丈夫です。
このまま、Webブラウザから、https://CycleCloudサーバのIPアドレス:9443 にアクセスし、初期セットアップ(管理者ユーザ設定など)へ進みます。

3-7. CycleCloud サーバ管理ポータルへログイン

PCからWebブラウザを起動して、IPアドレスを指定して、CycleCloudサーバへアクセスします。Bastion経由で、CycleCloudサーバの管理ポータルへアクセスする場合は以下を実行します。

(1) クライアントPCから、コマンドプロンプトを立ち上げ、--target-resource-id でCycleCloudサーバのリソースIDを指定して、以下を実行します。

$ az login
$ az network bastion tunnel --name vnet-hpc-bastion --resource-group rg-hpc \ 
               --target-resource-id /subscriptions/..../virtualMachines/ccserver  \
               --resource-port "9443" --port 19443

(2) PC上のWebブラウザから以下のURLを入力して、CycleCloudサーバ管理画面へアクセスします。以下のような初期設定画面が表示されることを確認してください。
(上記の場合は、https://localhost:19443 を指定)

4. CycleCloud サーバの初期設定

4-1. CycleCloud サーバの初期設定1

サイト名を指定します。こちらはお好みの名前を指定して下さい。

次にCycleCloud サーバのWeb管理ポータルにログインするユーザ名、パスワード、sshでログインする際の公開鍵を登録します。

その後、以下の指定を行って下さい。

項目
Subscription Name CycleCloudサーバの管理者名。サブスクリプション名やIDでない点に注意。
(例:azureuser)
Marketplace Terms Termの内容に問題がなければチェックを入れて下さい。
Authentication Managed identityを指定します。
Subscription ID ご利用のSubscription IDを入力して下さい。
(例:11111111-2222-3333-4444-555555555555)
Client ID 前に作成したCycleCloudに割り当てるManaged IDのClient IDを指定します。
Client IDはAzure Portalから、Managed IDの「概要」から確認できます。

その後、「Validate Credentials」をクリックして、"Test succeeded" が表示されることを確認して下さい。"Test succeeded" が表示された後

Default Location Japan East を選択。
Resource Group CycleCloud サーバを展開したリソースグループ を指定。(例:rg-hpc)
Authentication Use managed identity for storage access を選択。
Locker identity CycleCloudサーバに割り当てたManaged ID。(例:mngdid-ccserver)
Storage account CycleCloudサーバの管理用ストレージアカウント。(例:stgacctccservermngt)

各項目の指定が終わったら、「Save」で保存します。

上記画面が出たら、「Back to clusters」を選択してフロント画面に移動し、一度、CycleCloud 管理ポータルからログアウトして、再度、ログインできることを確認して下さい。

4-2. CycleCloud サーバの初期設定2

ssh 経由で CycleCloud サーバへログインし、以下のコマンドを実行して、CycleCloud CLI の初期化**を行ってください。

$ cyclecloud -v    # バージョンの確認
$ cyclecloud initialize
CycleServer URL: [http://localhost] http://localhost  # デフォルト値で進めてください
Detected untrusted certificate.  Allow?: [yes] yes    # yes を指定
CycleServer username: [azureuser] azureuser           # CycleCloud サーバ管理者を指定
CycleServer password: xxxxxxxxxx                      # 上記ユーザーのパスワードを指定

初期化が完了したら、以下のコマンドでクラスターの状態を確認します。

$ cyclecloud show_cluster    # 以下、実行結果の例
----------------------
fileserver01 : started
----------------------
Resource group: rg-hpc
Cluster nodes:
    filer: Started ip-0A000001 10.0.0.7
Total nodes: 1

5. Slurm クラスタの展開

CycleCloud サーバの準備が完了したので、ここから Slurm クラスタの展開を行います。まず、CycleCloud サーバのWeb管理画面から下図のように「Slurm」を選択します。
deploy1

その後「Cluster Name」をお好みの名前で指定します。ここでは " slurm_cluster01" で作成しています。
deploy2

次に左メニュー「Required Settings」項目では、「Virtual Machines」でヘッドノード("Scheduler VM Type" で表示)と計算ノード("HPC VM Type"、"HTC VM Type"、"GPU VM Type"、Dyn VM Type" で表示)について "Choose" ボタンから VM を変更することができます。今回はデフォルト値で指定された VM を使用します。
deploy3

同じ画面に、この Slurm クラスタのヘッドノードや計算ノードが属するサブネットを指定する項目があるので、こちらも忘れずに指定しておきます。
deploy4

次に左メニュー「Network Attached Storage」項目へ進み、外部共有ストレージのマウントでは、「2. 共有ストレージ Azure NetApp Files(ANF)の展開」で作成した Azure NetApp Files を指定します。"IP Address"、"Mount Point(ヘッドノードや計算ノード側のマウントポイント)"、”Export Path(Azure NetApp Files側のマウントポイント)"、"Mount Options" については、展開したAzure NetApp Files のボリュームをクリック後、左メニューの「ストレージサービス」→「マウントに関する指示」を開くと「ファイルシステムのマウント」という項目があるので、ここでそれぞれの値が確認できます。
deploy5

その後、左メニュー「Advanced Settings」で、ヘッドノードや計算ノードのOSを指定します。ここでもお好みのOSやカスタムイメージを指定することができますが、今回はデフォルトでgccコンパイラや各種MPIを含んだHPC向けのAlmaLinux8.10のイメージを指定します。"Scheduler OS" から "Dynamic OS" の各項目で、”Custom Image" のチェックボックスにチェックを入れて、図にあるように "almalinux:almalinux-hpc:8_10-hpc-gen2:latest" をOSイメージとして指定して下さい。
deploy6

次に左メニュー「Monitoring」「Virtual Machines」「Security」はデフォルト値のまま進め、「Cloud-init」では、図にあるように imapd.conf の設定を入れておきます。
deploy7

#!bin/bash
cp -p /etc/idmapd.conf /etc/idmapd.conf.org
sed -e s/'#Domain = local.domain.edu'/'Domain = defaultv4iddomain.com'/g /etc/idmapd.conf.org > /etc/idmapd.conf

補足

  • このスクリプトはAzure NetApp Files で NFS v4.1 を使用する時に必須のもので、ユーザ/グループIDのマッピング設定を変更しています。具体的にはNFSv4 で使われる ID マッピング用ドメイン名 (Domain) を明示的に記載し、UID/GID の不一致による Permission エラーを防ぐ設定を行っています。

全てを設定したら、「Save」をすると以下のような画面がでるので、「Start」をクリックしてください。Slurm クラスタのヘッドノードが起動します。
deploy8

ヘッドノードの起動完了は10分弱かかりますが、起動に成功すると以下の様に "Status" の部分が緑色のバーで表示されます。
deploy9

6. サンプル MPI ジョブの実行

最後に、展開した Slurm クラスタ を用いて、OpenMPI を用いた簡単な MPI ジョブを 2ノード/4プロセスで並列実行します。今回は InfiniBand 非搭載の VM を使用しているため、ノード間通信は Ethernet 経由で行います。

6-1. 作業ディレクトリの作成

Slurm のヘッドノードへ ssh でログイン(Bastion経由でも可能)し、共有ストレージ配下の以下ディレクトリへ移動します。

$ df -h
Filesystem                Size  Used Avail Use% Mounted on
devtmpfs                  7.8G     0  7.8G   0% /dev
tmpfs                     7.9G     0  7.9G   0% /dev/shm
tmpfs                     7.9G   25M  7.8G   1% /run
tmpfs                     7.9G     0  7.9G   0% /sys/fs/cgroup
/dev/sdc4                  63G   41G   23G  65% /
/dev/sdc3                1014M  442M  573M  44% /boot
/dev/sdc2                 200M  5.9M  194M   3% /boot/efi
/dev/sdd1                 147G  348K  140G   1% /mnt
/dev/sda                   30G  247M   30G   1% /sched
/dev/sdb                  100G  746M  100G   1% /shared
10.0.50.4:/anf-hpc-vol01  1.0T  512K  1.0T   1% /anf-hpc-vol01
tmpfs                     1.6G     0  1.6G   0% /run/user/20001
$ cd /anf-hpc-vol01/data/azureuser   # Azure NetApp Files 共有ストレージ
$ mkdir work; cd work

6-2. サンプル MPI プログラムの作成

MPI のランク番号とホスト名を表示する簡単なプログラムを使います。

$ vim mpi_test.c
#include <mpi.h>
#include <stdio.h>
#include <unistd.h>

int main(int argc, char **argv)
{
    int rank, size;
    char hostname[256];

    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);

    gethostname(hostname, sizeof(hostname));

    printf("Message from rank %d / %d on host %s\n", rank, size, hostname);

    MPI_Finalize();
    return 0;
}

6-3. OpenMPI を用いてコンパイル

mpicc を使って MPI プログラムをコンパイルします。
補足:

  • 本来であれば実行する計算ノード上でコンパイルすべきですが、今回はAzureでのクラスタ展開から実行までの全体の流れを理解するところが主目的なので、便宜的にヘッドノードでコンパイルしてしまったものを使っています。
$ module avail
$ module load mpi/openmpi-5.0.8
$ mpicc mpi_test.c -o mpi_test

コンパイル後、実行ファイルが作成されていることを確認します。

$ ls -l mpi_test

6-4. Slurm ジョブスクリプトの作成

各ノード2プロセス x 2ノード(= 合計 4 MPIプロセスで実行する Slurm ジョブスクリプトを作成します。

$ vim mpi_test.sh
#!/bin/bash
#SBATCH --job-name=mpi_test_slurm
#SBATCH --partition=htc
#SBATCH --nodes=2
#SBATCH --ntasks-per-node=2
#SBATCH --time=00:05:00
#SBATCH --output=output-%x-%j.log

# モジュラで OpenMPI をロード
module load mpi/openmpi-5.0.8

# 作業ディレクトリへ移動
cd $SLURM_SUBMIT_DIR

# Slurm 経由で MPI 実行
srun --mpi=pmix --cpu-bind=none ./mpi_test

補足

  • Slurm 環境では mpirun を直接呼び出すよりも、srun を用いた実行が推奨されています。Slurm が割り当てたリソース情報を正しく MPI ランタイムへ引き渡すことができ、設定も簡潔になります。

6-5. ジョブ投入

sbatch コマンドにジョブスクリプトを引数で与えて、ジョブを投入します。

$ sbatch mpi_test.sh

6-6. ジョブ状態、実行結果の確認

ジョブ投入後、以下の様に 2 台の計算ノードが起動し始めます。
jobrun1

暫くして計算ノードの起動が完了すると "Status" の部分が緑色のバーで表示されます。
jobrun2

CycleCloud サーバの管理ポータルで計算ノードの起動状態を確認し、squeue コマンドで、ジョブの状態を確認して下さい。

$ squeue
  JOBID PARTITION     NAME     USER ST    TIME  NODES  NODELIST(REASON)
      1       htc mpi_test azureuse CF    0:05      2  slurm-cluster01-htc-[1-2]

計算ノード2台が起動した後、投入されたジョブが実行され、以下の様な結果が出力されます。正しく実行されていることを確認して下さい。

Message from rank 0 / 4 on host slurm-cluster01-htc-3
Message from rank 1 / 4 on host slurm-cluster01-htc-3
Message from rank 2 / 4 on host slurm-cluster01-htc-4
Message from rank 3 / 4 on host slurm-cluster01-htc-4

ジョブの実行が完了した後、5分アイドル状態が続くと、計算ノードは自動的に停止処理が開始され、削除されます。

7. Slurm クラスタ、CycleCloud サーバの停止

Slurm クラスタを停止する場合は、CycleCloud Web管理ポータルで、クラスタを選択した後、図の赤枠で示したように「Terminate」ボタンでヘッドノードを停止させることができます。また、Slurm クラスタを完全に削除したい場合は、クラスタを停止した後、図の青枠にある「ごみアイコンを押すと完全にクラスタを消去することになります。

またCycleCloudサーバを停止する場合は、通常の VM の起動停止と同様で、Azure Portalで CycleCloud VM を選択した後、「停止」ボタンを押します。

8. まとめ

本記事では、Azure CycleCloud を用いて検証用の Slurm クラスタを構築し、OpenMPI の簡単なサンプルジョブを実行するまでの流れを紹介しました。サンプルコード部分を実際のシミュレーションコードや解析アプリケーションに置き換えることで、オンプレミス環境と同様の HPC ワークロードをクラウド上で実行できます。

Azure では、InfiniBand 対応の HPC VM や GPU VM も利用可能であり、オンプレミス環境からの クラウドバーストや、クラウド専用の大規模解析環境の構築も容易です。既に製造業、金融、ライフサイエンス、エネルギー分野を中心に、多くの企業や研究機関で Azure HPC が活用されています。

ぜひ、クラウドベースの HPC 環境も選択肢の一つとして検討してみてください。

参考情報

Discussion