はじめに – HyperPodのMulti-userの必要性
AWS SageMaker HyperPodは、大規模な機械学習(ML)ワークロードやHPCに最適な環境を提供する強力なクラスタリングソリューションです。
しかし、多くの企業や研究機関では、複数のユーザーが同じHyperPod環境を共有するケースが一般的 です。例えば、AI/MLエンジニア、データサイエンティスト、研究者 など、異なるチームが一つのHyperPodクラスターを利用し、それぞれのタスクを並行して実行する必要があります。
本記事では、HyperPodでMulti-user導入方法を詳しく説明します。
HyperpodのMulti-user設定における前提条件
- HyperPodの基本な仕組みを理解していること
- HyperPod環境が事前に構築されていること
Multi-user環境の設計
1. 全体構成
AWS HyperPodのMulti-user環境を構築するにあたり、数十人規模のユーザーが利用するケースを想定し、単にユーザーを作成するだけでなく、効率的な運用が可能な仕組みを設計しました。その結果、上記のアーキテクチャ図のような構成を実現しました。
本環境では、複数のユーザー(図の左側) が、それぞれの開発環境からHyperPodにアクセスし、AI・機械学習モデルの開発を行えるように設計されています。
各ユーザー環境には、開発に必要な基本ソフトウェア(図の右側) を導入し、以下のような標準的なAI開発環境を提供しました。
- Condaの仮想環境 を用意し、ユーザーごとに独立した開発環境を構築
- 初期インストール済みのSW: CUDA、PyTorch、Jupyter Notebook をプリセット
- FSx for Lustre を活用し、データ共有・高速ストレージを提供
さらに、ユーザー作成時の運用負担を軽減するため、Bulk処理を導入しました。各ユーザーを手動で管理するのではなく、スクリプトを活用し、複数のノードに対して一括でユーザー作成や環境構築を実行できるよう設計しました。
2. Muti-user環境の詳細構成
運用の効率化を考慮し、以下の2つのポイントを中心に設計しました。
A. Bulk処理: 複数のユーザーを一括で作成・管理
B. 各ユーザーのアクセス情報の統合管理
A. Bulk処理
複数のノードに対して、複数のユーザーを一括作成するためにスクリプトを活用した自動化を実施しました。
AWSの公式WorkshopsにもMulti-user環境の例がありましたが、実際に運用してみると以下の課題が発生しました。
-
OSユーザーの整合性(UID/GIDの管理)
- 各ユーザーのUID(ユーザーID)やGID(グループID)が衝突する可能性がある
- そのため、UID/GIDを統一的に管理し、一貫性を持たせる仕組みを導入
-
ジョブ実行中のユーザー管理
- srun コマンドを利用すると、ジョブ実行時にノードが占有され、ユーザー管理が難しくなる
- そのため、PythonのParamikoライブラリを活用 し、各ノードにSSHで直接接続し、ユーザー作成を実施
B. アクセス情報の統合管理
HyperPod環境では、ユーザーごとに以下の2種類のアカウントが必要となります。
- IAMユーザー(AWS SSMログイン用)
- OSユーザー(ノード内での計算・開発作業用)
これらの情報を手動で管理すると運用コストがかかるため、Terraformを活用し、IAMユーザーの管理とともにアクセス情報を自動生成・集約しました。
具体的には、各ユーザーのアクセス情報をCSVファイルにまとめ、統一的なフォルダに出力することで、管理負担を軽減しました。
3. 各User向けの開発環境構成
今回、各ユーザーにはCUDA、PyTorch、Jupyter Notebookを活用したAI/ML開発環境を提供しました。
-
開発環境の分離と管理
- Condaの仮想環境を活用 し、ユーザーごとに独立した環境を提供
- 各ユーザーが必要なSWを追加でインストール可能な設計
-
環境の一括導入
- Condaはグローバル環境として配置 し、Lifecycle Scriptsの初期セットアップ時に自動インストール
- CUDA、PyTorch、Jupyter Notebookは、各ユーザーごとに導入 するスクリプトを作成
- FSx for Lustreをマウント し、Head Nodeから1回のスクリプト実行で全Compute Nodeに適用
これにより、ユーザーごとの環境構築を最小限の工数で自動化し、運用負担を大幅に削減しました。
AWS HyperPodにおけるMulti-user設定の実装
1. Multi-user作成-OS User部分
本記事では、既にHyperPodが構築されていることを前提として解説します。そのため、HyperPodのセットアップ手順については省略します。
ubuntu@ip-10-1-15-235:~$ sinfo
PARTITION AVAIL TIMELIMIT NODES STATE NODELIST
dev* up infinite 2 idle ip-10-1-58-72,ip-10-1-63-151
partition-1 up infinite 2 idle ip-10-1-58-72,ip-10-1-63-151
1-1. Head Node から Compute Node への SSH アクセス設定
UbuntuユーザーでHead Nodeにログインし、Compute NodeへSSHでアクセスできるように設定してください。
具体的には、SSH鍵の作成と配置を行い、各Compute Nodeにアクセスできる状態を準備します。
# Run the command in headnode
cd ~/.ssh
ssh-keygen -t rsa -q -f "$HOME/.ssh/id_rsa" -N ""
cat id_rsa.pub >> authorized_keys
1-2. Conda環境の確認
次に、Condaのバージョンを確認します。
本例では、HyperPodのセットアップ時にLifecycle Scriptsを使用し、すべてのNodeにCondaをインストール済みです。
環境によってはCondaが未インストールの場合があるため、その場合は私のGitHubにあるLifecycle Scriptsを参考にセットアップしてください。
ubuntu@ip-10-1-15-235:~$ conda --version
conda 25.1.1
1-3. Multi-user環境のセットアップ
Multi-userの作成には、ParamikoのSSHプロトコルを使用します。そのため、Condaの仮想環境上で以下のコマンドを実行し、必要なPythonライブラリをセットアップしてください。
conda create -y -p ./python3_11 python=3.11
conda activate ./python3_11
conda install -y conda-forge::paramiko
1-4. ユーザー情報のCSVとPythonスクリプト
Multi-userの作成には、ユーザー情報を記載したCSVファイルとPythonスクリプトを使用します。
次の手順で実装を進めます。
1. CSVファイルの準備
- 各ユーザーの ユーザー名、UID、GID、ホームディレクトリ などをリスト化
- ファイル形式例: user_info.csv
2. Pythonスクリプトの実行
- 上記のCSVを基に、各NodeにOSユーザーを作成
- Python Scripts例:create_multi_user.py
(/fsx/ubuntu/python3_11) ubuntu@ip-10-1-15-235:~$ nano user_info.csv
(/fsx/ubuntu/python3_11) ubuntu@ip-10-1-15-235:~$ nano create_multi_user.py
1-5. Multi-user scripts実行結果
Pythonスクリプトを実行すると、各Nodeに指定したUser&Groupが作成されます。
(/fsx/ubuntu/python3_11) ubuntu@ip-10-1-15-235:~$ python3 create_multi_user.py
Creating group group1 on head nodes.
--------------------------------------------------
Creating user user1 on head nodes.
Password for user 'user1' is not set.
Setting password for user 'user1'...
Password set for user 'user1'.
Creating ssh key user1 on head nodes.
User user1 added to sudo group with no-password configuration on the headnode.
--------------------------------------------------
Checking compute node: ip-10-1-58-72
Creating group group1 on compute nodes.
Creating user user1 on compute nodes.
User user1 added to sudo group with no-password configuration (updated or added if missing).
--------------------------------------------------
Checking compute node: ip-10-1-63-151
Creating group group1 on compute nodes.
Creating user user1 on compute nodes.
User user1 added to sudo group with no-password configuration (updated or added if missing).
--------------------------------------------------
Group group1 already exists on the head node. Skipping creation.
--------------------------------------------------
Creating user user2 on head nodes.
Password for user 'user2' is not set.
Setting password for user 'user2'...
Password set for user 'user2'.
Creating ssh key user2 on head nodes.
User user2 added to sudo group with no-password configuration on the headnode.
--------------------------------------------------
Checking compute node: ip-10-1-58-72
Group group1 already exists on compute nodes. Skipping group creation.
Creating user user2 on compute nodes.
User user2 added to sudo group with no-password configuration (updated or added if missing).
--------------------------------------------------
Checking compute node: ip-10-1-63-151
Group group1 already exists on compute nodes. Skipping group creation.
Creating user user2 on compute nodes.
User user2 added to sudo group with no-password configuration (updated or added if missing).
--------------------------------------------------
Creating group group2 on head nodes.
--------------------------------------------------
Creating user user3 on head nodes.
Password for user 'user3' is not set.
Setting password for user 'user3'...
Password set for user 'user3'.
Creating ssh key user3 on head nodes.
--------------------------------------------------
Checking compute node: ip-10-1-58-72
Creating group group2 on compute nodes.
Creating user user3 on compute nodes.
--------------------------------------------------
Checking compute node: ip-10-1-63-151
Creating group group2 on compute nodes.
Creating user user3 on compute nodes.
--------------------------------------------------
Creating group group3 on head nodes.
--------------------------------------------------
Creating user user4 on head nodes.
Password for user 'user4' is not set.
Setting password for user 'user4'...
Password set for user 'user4'.
Creating ssh key user4 on head nodes.
--------------------------------------------------
Checking compute node: ip-10-1-58-72
Creating group group3 on compute nodes.
Creating user user4 on compute nodes.
--------------------------------------------------
Checking compute node: ip-10-1-63-151
Creating group group3 on compute nodes.
Creating user user4 on compute nodes.
--------------------------------------------------
Creating group group4 on head nodes.
--------------------------------------------------
Creating user user5 on head nodes.
Password for user 'user5' is not set.
Setting password for user 'user5'...
Password set for user 'user5'.
Creating ssh key user5 on head nodes.
--------------------------------------------------
Checking compute node: ip-10-1-58-72
Creating group group4 on compute nodes.
Creating user user5 on compute nodes.
--------------------------------------------------
Checking compute node: ip-10-1-63-151
Creating group group4 on compute nodes.
Creating user user5 on compute nodes.
--------------------------------------------------
Userが生成されました。
ubuntu@ip-10-1-15-235:~$ cat /etc/passwd
~~~
user1:x:1010:1010::/fsx/user1:/bin/bash
user2:x:1011:1010::/fsx/user2:/bin/bash
user3:x:1012:1011::/fsx/user3:/bin/bash
user4:x:1013:1012::/fsx/user4:/bin/bash
user5:x:1014:1013::/fsx/user5:/bin/bash
Groupも生成されました。
ubuntu@ip-10-1-15-235:~$ cat /etc/group
~~~
group1:x:1010:
group2:x:1011:
group3:x:1012:
group4:x:1013:
1-6. Multi-user scripts実行結果のテスト
Compute Nodeにユーザーやグループが正しく作成されたかは、コマンドを使用して手動で確認できますが、より効率的に検証するために、次のPythonスクリプトを利用して自動テストを実行することも可能です。
- Python Scripts例:multi_user_test.py
(/fsx/ubuntu/python3_11) ubuntu@ip-10-1-15-235:~$ python3 multi_user_test.py
==================================================
Testing for user: user1
==================================================
Testing if group 'group1' exists on head node...
Group 'group1' exists on head node.
Testing if user 'user1' exists on head node...
User 'user1' exists on head node.
Checking compute node: ip-10-1-58-72
- Group 'group1' exists on compute node.
- User 'user1' exists on compute node.
- User 'user1' can SSH into compute node.
--------------------------------------------------
Checking compute node: ip-10-1-63-151
- Group 'group1' exists on compute node.
- User 'user1' exists on compute node.
- User 'user1' can SSH into compute node.
--------------------------------------------------
==================================================
Testing for user: user2
==================================================
Testing if group 'group1' exists on head node...
Group 'group1' exists on head node.
Testing if user 'user2' exists on head node...
User 'user2' exists on head node.
Checking compute node: ip-10-1-58-72
- Group 'group1' exists on compute node.
- User 'user2' exists on compute node.
- User 'user2' can SSH into compute node.
--------------------------------------------------
Checking compute node: ip-10-1-63-151
- Group 'group1' exists on compute node.
- User 'user2' exists on compute node.
- User 'user2' can SSH into compute node.
--------------------------------------------------
==================================================
Testing for user: user3
==================================================
Testing if group 'group2' exists on head node...
Group 'group2' exists on head node.
Testing if user 'user3' exists on head node...
User 'user3' exists on head node.
Checking compute node: ip-10-1-58-72
- Group 'group2' exists on compute node.
- User 'user3' exists on compute node.
- User 'user3' can SSH into compute node.
--------------------------------------------------
Checking compute node: ip-10-1-63-151
- Group 'group2' exists on compute node.
- User 'user3' exists on compute node.
- User 'user3' can SSH into compute node.
--------------------------------------------------
==================================================
Testing for user: user4
==================================================
Testing if group 'group3' exists on head node...
Group 'group3' exists on head node.
Testing if user 'user4' exists on head node...
User 'user4' exists on head node.
Checking compute node: ip-10-1-58-72
- Group 'group3' exists on compute node.
- User 'user4' exists on compute node.
- User 'user4' can SSH into compute node.
--------------------------------------------------
Checking compute node: ip-10-1-63-151
- Group 'group3' exists on compute node.
- User 'user4' exists on compute node.
- User 'user4' can SSH into compute node.
--------------------------------------------------
==================================================
Testing for user: user5
==================================================
Testing if group 'group4' exists on head node...
Group 'group4' exists on head node.
Testing if user 'user5' exists on head node...
User 'user5' exists on head node.
Checking compute node: ip-10-1-58-72
- Group 'group4' exists on compute node.
- User 'user5' exists on compute node.
- User 'user5' can SSH into compute node.
--------------------------------------------------
Checking compute node: ip-10-1-63-151
- Group 'group4' exists on compute node.
- User 'user5' exists on compute node.
- User 'user5' can SSH into compute node.
--------------------------------------------------
Test results have been saved to test_results_20250314_042441.txt
2. Multi-user作成-開発環境の部分
Multi-user作成が完了したので、次は各Userに必要な開発環境をセットアップしていきます。
2-1. 各User向けの開発環境セットアップ
上でも説明した通り、HyperPodとFSxのマウント設定により、HeadNode上でPythonスクリプトを実行するだけで環境が整います。
本例では、1ユーザーあたり約10分のセットアップ時間がかかります。
- Python Scripts例:multi_user_sw.py
(/fsx/ubuntu/python3_11) ubuntu@ip-10-1-15-235:~$ python3 create_multi_user_sw.py
Executing as user1: conda create -y -p /fsx/user1/pytorch-cuda12_1 python=3.11 && conda activate /fsx/user1/pytorch-cuda12_1 && conda install -y pytorch=2.3.0 pytorch-cuda=12.1 aws-ofi-nccl torchvision torchaudio transformers datasets fsspec=2023.9.2 --strict-channel-priority --override-channels -c https://aws-ml-conda.s3.us-west-2.amazonaws.com -c nvidia -c conda-forge && pip install jupyter notebook && python -m ipykernel install --user --name 'pytorch-cuda12_1' && conda deactivate
~~~省略~~~
2-2. 開発環境の確認
セットアップ後、各Userの環境が正常に適用されているか確認してみましょう。
まず、例として作成した user1 に切り替えます。
ubuntu@ip-10-1-15-235:~$ su - user1
Password: #user_info.csv参考
pytorch-cuda11_8
と pytorch-cuda12_1
の2つのCUDAバージョンの環境があるはずです。
ここでは、pytorch-cuda12_1
のConda環境に入ります。
drwxr-xr-x 19 user1 group1 33280 Mar 14 05:02 pytorch-cuda11_8
drwxr-xr-x 19 user1 group1 33280 Mar 14 04:45 pytorch-cuda12_1
user1@ip-10-1-15-235:~$ conda activate ./pytorch-cuda12_1/
その後、PyTorchのインストールが正しく完了しているか確認します。
(/fsx/user1/pytorch-cuda12_1) user1@ip-10-1-15-235:~$ python -c "import torch; print(torch.__version__)"
2.3.0
CUDAのインストールが正しく完了しているか確認します。
(/fsx/user1/pytorch-cuda12_1) user1@ip-10-1-15-235:~$ python -c "import torch; print(torch.version.cuda)"
12.1
最後に、Jupyter Notebookのインストールが正しく完了しているか確認します。
(/fsx/user1/pytorch-cuda12_1) user1@ip-10-1-15-235:~$ jupyter --version
Selected Jupyter core packages...
IPython : 9.0.2
ipykernel : 6.29.5
ipywidgets : 8.1.5
jupyter_client : 8.6.3
jupyter_core : 5.7.2
jupyter_server : 2.15.0
jupyterlab : 4.3.5
nbclient : 0.10.2
nbconvert : 7.16.6
nbformat : 5.10.4
notebook : 7.3.2
qtconsole : not installed
traitlets : 5.14.3
これで、HyperPod内のMulti-user環境(OS User, 開発環境)が整いました。
各Userが個別の開発環境を利用できる状態になっています。
3. HyperPod Login User作成
HyperPodのLogin Userは、Terraformで管理しています。
これは、HyperPodのOS Userと統一的に管理するため、また各Userに渡すAccess情報を自動的に生成できるようにするためです。
3-1. Terraformの実行
本記事では、Terraformの基本的な説明は省略します。
Terraformのコードについては、私が作成したGitHubリポジトリを参考にしてください。
なお、Tree構造は以下のように整理しました。
.
├── infra # HyperPod Infra用
├── modules
│ └── multi_user
└── user # HyperPod Login User用
├── README.md
├── files
│ ├── sagemaker_ssm_access_policy.json.tpl
│ └── user_info.csv
├── iam.tf
├── iam_user_access_info.tf
├── locals.tf
├── main.tf
├── output.tf
├── provider.tf
└── vars.tf
Terraformを実行すると、AWSコンソール上に、今回使用する5つのUserと各Groupが作成されます。
また、各GroupにはSSM Loginに必要なIAM Policyが適用されています。
3-2. Access情報の確認
Terraformのiam_user_access_info.tf
によって、Access関連情報を自動的にフォルダおよびファイルとして作成するようにしています。
この仕組みにより、手動で情報を集める手間を省き、そのままUserに渡せる形で管理できます。
特に複数のUserを扱う場合、一つ一つ手作業で情報を整理する負担を解消するための仕組みを取り入れました。
3-3. SSM Integration
HyperPodの仕様上、IAM Userを利用したログインはSession Managerを経由します。
そのため、Session Managerの設定を適切に変更する必要があります。
設定方法は、以下のイメージ(赤いボックス)を参考にしてください。
# Linux shell profile
/bin/bash -c 'export HOME=/fsx/$(whoami) && cd ${HOME} && exec /bin/bash'
また、補足として、IAM User作成時にTagとしてSSMSessionRunAs
をKeyに設定し、ValueにOS_USER_NAME
を指定すると、SSM Integrationが適用されます。
このTagの設定は、Terraformで自動化しています。もし手動でIAM Userを作成する場合には、この設定を忘れないように注意してください。
3-4. SSMを利用したHeadNodeへのアクセス
作成したuser1
を使ってログインを試みます。
easy-ssh.sh
./easy-ssh.sh -c leo-stg-head-ig leo-stg-hyperpod-cluster ok | 53s | 18:23:53
Cluster id: wmvulrbbeaom
Instance id: i-0c8909365ef20e3a9
Node Group: leo-stg-head-ig
aws ssm start-session --target sagemaker-cluster:wmvulrbbeaom_leo-stg-head-ig-i-0c8909365ef20e3a9
Add the following to your ~/.ssh/config to easily connect:
cat <<EOF >> ~/.ssh/config
Host leo-stg-hyperpod-cluster
User ubuntu
ProxyCommand sh -c "aws ssm start-session --target sagemaker-cluster:wmvulrbbeaom_leo-stg-head-ig-i-0c8909365ef20e3a9 --document-name AWS-StartSSHSession --parameters 'portNumber=%p'"
EOF
Add your ssh keypair and then you can do:
$ ssh leo-stg-hyperpod-cluster
Starting session with SessionId: leo-stg-user1-xud9v2lpgvr5khr64g2l4inyiq
# sudo su - user1
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.
user1@ip-10-1-15-235:~$ sinfo
PARTITION AVAIL TIMELIMIT NODES STATE NODELIST
dev* up infinite 2 idle ip-10-1-58-72,ip-10-1-63-151
partition-1 up infinite 2 idle ip-10-1-58-72,ip-10-1-63-151
ログイン後、ファイルを確認すると、Python Scriptsによって作成されたUser環境がFSx上に配置されているのがわかります。
具体的には、fsx/{OS_USER_NAME}
配下に pytorch-cuda*
のConda環境もセットアップされています。
user1@ip-10-1-15-235:~$ pwd
/fsx/user1
user1@ip-10-1-15-235:~$ ls -al
total 377
drwxr-xr-x 10 user1 group1 33280 Mar 14 10:02 .
drwxr-xr-x 11 root root 33280 Mar 14 04:23 ..
-rw------- 1 user1 group1 386 Mar 14 09:49 .bash_history
-rw-r--r-- 1 user1 group1 220 Feb 25 2020 .bash_logout
-rw-r--r-- 1 user1 group1 3771 Feb 25 2020 .bashrc
drwx------ 5 user1 group1 33280 Mar 14 04:45 .cache
drwxr-xr-x 3 user1 group1 33280 Mar 14 04:28 .conda
drwx------ 3 user1 group1 33280 Mar 14 04:24 .config
drwxr-xr-x 2 user1 group1 33280 Mar 14 04:47 .ipython
drwxr-xr-x 3 user1 group1 33280 Mar 14 04:47 .local
-rw-r--r-- 1 user1 group1 807 Feb 25 2020 .profile
drwx------ 2 user1 group1 33280 Mar 14 04:24 .ssh
-rw-r--r-- 1 user1 group1 0 Mar 14 10:02 .sudo_as_admin_successful
drwxr-xr-x 19 user1 group1 33280 Mar 14 05:02 pytorch-cuda11_8
drwxr-xr-x 19 user1 group1 33280 Mar 14 04:45 pytorch-cuda12_1
これで、新規UserがSSMを利用してHeadNodeにアクセスできることを確認できました。
最後に
HyperPodのMulti-user管理には、Ubuntuのユーザー管理に関する知識も必要でした。
今回の記事では、HyperPodのUser管理に焦点を当てていますが、私が担当したプロジェクトではEC2も関与し、さらにFSxも利用していたため、ユーザー管理の不整合が発生するとHyperPodだけでなく、他のインスタンスでも正常に動作しなくなるリスクがありました。
そのため、ユーザー管理を一元化し、その情報を基にUser/Groupの作成を自動化するとともに、HyperPodの仕様に適したfsx/配下の配置やディレクトリのパーミッション設定まで考慮した構成を採用しました。その結果、数十人のユーザー情報を管理し、IAM UserやOS Userの作成からファイル権限の設定まで自動化できる仕組みを構築しました。
この経験を通じて、Cluster環境におけるMulti-user管理の知識が深まり、試行錯誤を重ねながら設計を進める自信がつきました。
以上、「AWS HyperPodのMulti-user導入方法」に関する記事でした。ご覧いただき、ありがとうございました!