AWS ParallelCluster で Docker コンテナを実行する Docker on ParallelCluster を構築してみた

2022.04.29

今やコンテナ技術は Web 界隈だけではなく HPC 界隈でも利用されるほど普及しました。今回は AWS ParallelCluster のコンピュートノード上の計算環境セットアップを省略するべく Docker コンテナを利用した計算処理を実行したいです。

Docker on ParallelCluster を実現する設定ファイルを交え構築方法を紹介します。

Icons made by Freepik from www.flaticon.com

Docker on ParallelCluster

項目
AWS ParallelCluster 3.1.3
Job Scheduler Slurm
OS Ubuntu 20.04 LTS
CPU Intel
Simultaneous Multi-Threading Disabled

コンフィグ

Docker on ParallelCluster 用のサンプルコンフィグを作成しました。Docker に関する部分は postainstall.sh の処理で行うため、クラスターは自体に特殊な設定は必要ありません。

  • ヘッドノードは Docker インストール不要なため、postinsallは未設定

sample-docker-on-parallelcluster.yml

Region: ap-northeast-1
Image:
  Os: ubuntu2004
Monitoring:
  Logs:
    CloudWatch:
        Enabled: true
        RetentionInDays: 30
        DeletionPolicy: "Delete"
  Dashboards:
    CloudWatch:
        Enabled: false
Tags:
    - Key: Name
      Value: DockerOnParallelcluster
HeadNode:
  InstanceType: t3.micro
  Networking:
    ElasticIp: false
    SubnetId: subnet-035be95eeaa091603
  Ssh:
    KeyName: sandbox-key
  LocalStorage:
    RootVolume:
      Size: 35
      Encrypted: false
      VolumeType: gp3
      Iops: 3000
      Throughput: 125
  Iam:
    S3Access:
      - BucketName: hpc-dev-postinstall-files
        EnableWriteAccess: False
    AdditionalIamPolicies:
      - Policy: arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
Scheduling:
  Scheduler: slurm
  SlurmSettings:
    ScaledownIdletime: 5
  SlurmQueues:
    # --- Queue 1 ---
    - Name: cpu-spot
      ComputeResources:
        - Name: large
          InstanceType: c6i.large
          MinCount: 0
          MaxCount: 10
          DisableSimultaneousMultithreading: true
      ComputeSettings:
        LocalStorage:
          RootVolume:
            Size: 35
            Encrypted: false
            VolumeType: gp3
            Iops: 3000
            Throughput: 125
      CapacityType: SPOT
      Networking:
         SubnetIds:
           - subnet-035be95eeaa091603
         PlacementGroup:
           Enabled: true
      CustomActions:
          OnNodeConfigured:
            Script: s3://hpc-dev-postinstall-files/sample-ubuntu-docker/postinstall.sh
      Iam:
        S3Access:
          - BucketName: hpc-dev-postinstall-files
            EnableWriteAccess: False
        AdditionalIamPolicies:
          - Policy: arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore

    # --- Queue 2 ---
    - Name: high-cpu-spot
      ComputeResources:
        - Name: large16x
          InstanceType: c6i.16xlarge
          MinCount: 0
          MaxCount: 10
          DisableSimultaneousMultithreading: true
      ComputeSettings:
        LocalStorage:
          RootVolume:
            Size: 35
            Encrypted: false
            VolumeType: gp3
            Iops: 3000
            Throughput: 125
      CapacityType: SPOT
      Networking:
         SubnetIds:
           - subnet-035be95eeaa091603
         PlacementGroup:
           Enabled: true
      CustomActions:
        OnNodeConfigured:
          Script: s3://hpc-dev-postinstall-files/sample-ubuntu-docker/postinstall.sh
      Iam:
        S3Access:
          - BucketName: hpc-dev-postinstall-files
            EnableWriteAccess: False
        AdditionalIamPolicies:
          - Policy: arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore

postinstall.sh

コンピュートノードの起動時に以下のスクリプトが実行されます。

  • Docker のインストール

postinstall.sh

#! /bin/bash

apt-get update
apt-get install \
    ca-certificates \
    curl \
    gnupg \
    lsb-release -y
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
apt-get update
apt-get install docker-ce docker-ce-cli containerd.io -y

コンピュートノードで起動する Ubuntu 20.04 に Docker をインストール手順は公式ドキュメントを参考にしました。

Install Docker Engine on Ubuntu | Docker Documentation

postinstall.shはクラスター作成のコンフィグ内で指定した所定のS3バケットに保存します。

ここではhpc-dev-postinstall-filesS3バケットのsample-ubuntu-dockerプレフィックス配下のpostinstall.shを指定しています。 コンピュートノードから対象のS3バケットへアクセスできるように読み取り専用の権限を付与しています。

コンフィグ抜粋

      CustomActions:
        OnNodeConfigured:
          Script: s3://hpc-dev-postinstall-files/sample-ubuntu-docker/postinstall.sh
      Iam:
        S3Access:
          - BucketName: hpc-dev-postinstall-files
            EnableWriteAccess: False

クラスター作成

クラスター作成コマンドを実行して10分ほど待ちます。ヘッドノードが起動したらログインします。

> pcluster create-cluster -n DockerOnParallelcluster -c sample-docker-on-parallelcluster.yml
{
  "cluster": {
    "clusterName": "DockerOnParallelcluster",
    "cloudformationStackStatus": "CREATE_IN_PROGRESS",
    "cloudformationStackArn": "arn:aws:cloudformation:ap-northeast-1:12345679012:stack/DockerOnParallelcluster/59b85490-c3a7-11ec-b7c8-0e8a0cc9f27b",
    "region": "ap-northeast-1",
    "version": "3.1.3",
    "clusterStatus": "CREATE_IN_PROGRESS"
  }
}

ヘッドノードからジョブを投げてみる

Docker コンテナを利用するテストジョブを作成しました。今回は BUSCO の動作検証する機会があったため、BUSCO コンテナを起動しています。

  • コンテナを起動し、コンテナ内で任意のコマンドを実行
  • ジョブを投げたときのカレントディレクトリをコンテナへマウント
    • ヘッドノードのホームディレクトリ、EFS、FSx for Lustre などの共有ストレージを想定
    • コンテナ内で利用したいファイルを事前に共有ストレージに保存しておくことでコンテナからアクセスできる
    • コンテナでの実行結果の出力(保存)先にして永続的なストレージ利用としてもできる

Icons made by Freepik from www.flaticon.com

テストジョブ

Slurm で管理されたジョブがコンピュートノードで実行され、コンピュートノード上のコンテナ内で任意コマンド、共有ストレージをマウントできているか確認します。

  • busco コマンドが実行可能かテストためバージョン情報表示
  • コンテナに共有ストレージ(永続的なストレージ)をマウントできているか確認
    • 事前にmessage.txtを共有ストレージに作成しcatコマンドで開けるかテスト
      • Docker on ParallelCluster.と書き込んだテキストファイルです。
    • ls -lコマンドで共有ストレージがコンテナ内から見えているかテスト

run.sh

#! /bin/bash

#SBATCH -p cpu-spot
#SBATCH -N 1

RUN_CMD="busco -v"
RUN_CMD2="cat message.txt"
RUN_CMD3="ls -l"

CON_WD=/host_mount
CON_ID=`sudo docker run -dit --mount type=bind,src=$(pwd),dst=$CON_WD --workdir $CON_WD quay.io/biocontainers/busco:5.3.2--pyhdfd78af_0`

sudo docker exec -t ${CON_ID} ${RUN_CMD}
sudo docker exec -t ${CON_ID} ${RUN_CMD2}
sudo docker exec -t ${CON_ID} ${RUN_CMD3}

sudo docker stop ${CON_ID} > /dev/null

ジョブの実行結果

ジョブを投げます。コンピュートノードが起動しpostinstall.shが実行され Dockerインストールされた環境が構築されます。その後、run.shの内容が実行され、コンテナイメージの取得、任意のコマンド実行されます。

$ sbatch run.sh

実行結果のファイルを確認しました。

  • sudo doker run ...コマンドの実行結果が載ってきたため、イメージを pull しているときのメッセージが記録されていました。
  • BUSCO 5.3.2の表示を確認でき、buscoコマンドを実行できています
    • すなわちコンテナ内で任意のコマンド実行されたことがわかります。
  • Docker on ParallelCluster.の表示を確認できました。
    • 共有ストレージのファイルをコンテナから開けることを確認

slurm-8.out

Unable to find image 'quay.io/biocontainers/busco:5.3.2--pyhdfd78af_0' locally
5.3.2--pyhdfd78af_0: Pulling from biocontainers/busco
aa44502a478a: Pulling fs layer
bef3901422b5: Pulling fs layer
b6572cc046f2: Pulling fs layer
6dbbfe98ccd4: Pulling fs layer
4ca545ee6d5d: Pulling fs layer
d7cc672bfaf9: Pulling fs layer
6dbbfe98ccd4: Waiting
4ca545ee6d5d: Waiting
d7cc672bfaf9: Waiting
b6572cc046f2: Verifying Checksum
b6572cc046f2: Download complete
6dbbfe98ccd4: Verifying Checksum
6dbbfe98ccd4: Download complete
bef3901422b5: Verifying Checksum
bef3901422b5: Download complete
4ca545ee6d5d: Verifying Checksum
4ca545ee6d5d: Download complete
aa44502a478a: Verifying Checksum
aa44502a478a: Download complete
aa44502a478a: Pull complete
bef3901422b5: Pull complete
b6572cc046f2: Pull complete
6dbbfe98ccd4: Pull complete
4ca545ee6d5d: Pull complete
d7cc672bfaf9: Verifying Checksum
d7cc672bfaf9: Download complete
d7cc672bfaf9: Pull complete
Digest: sha256:900fc79245c3f6df7b2efe986d030c9a5f6fe21f1f000a4e6f09ff41da7def42
Status: Downloaded newer image for quay.io/biocontainers/busco:5.3.2--pyhdfd78af_0
BUSCO 5.3.2
Docker on ParallelCluster.
total 12
-rw-rw-r-- 1 1000 1000   27 Apr 28 11:00 message.txt
-rw-rw-r-- 1 1000 1000  434 Apr 28 11:31 run.sh
-rw-rw-r-- 1 1000 1000 1147 Apr 28 11:55 slurm-8.out

Docker コンテナを利用した ParallelCluster の実行環境の動作確認が取れました。

まとめ

ParallelCluster で Docker コンテナを利用したい場合は、postinstall.shでコンピュートノードに Docker インストールすればコンテナ実行環境が構築できます。 Docker をインストールしても、ジョブを投げてからコンピュートノードが起動しジョブを開始するまで約5分です。Docker をインストール済みのカスタム AMI を作成しなくても実用の範囲内かと思います。

/var/log/slurmctld.log

[2022-04-28T11:40:03.797] _slurm_rpc_submit_batch_job: JobId=8 InitPrio=4294901752 usec=347
[2022-04-28T11:40:03.921] sched/backfill: _start_job: Started JobId=8 in cpu-spot on cpu-spot-dy-large-3
[2022-04-28T11:44:15.760] Node cpu-spot-dy-large-3 now responding
[2022-04-28T11:44:45.361] job_time_limit: Configuration for JobId=8 complete
[2022-04-28T11:44:45.361] Resetting JobId=8 start time for node power up
[2022-04-28T11:44:57.639] _job_complete: JobId=8 WEXITSTATUS 0
[2022-04-28T11:44:57.640] _job_complete: requeue JobId=8 per user/system request
[2022-04-28T11:44:57.640] _job_complete: JobId=8 done

おわりに

Docker コンテナ使うなら AWS Batch で実現できませんか?という疑問があるかと思います。AWS Batch で利用できるホストの EC2 インスタンスタイプの種類は限定的です。現在 AWS Batch は Hpc6a インスタンスは非対応です。最新のパワフルな計算リソースを使ってみたい方はより自由度の高い ParallelCluster を選択することもあるでしょう。

AWS Batch はフルマネージドでユーザーの運用管理の負担が減るため、自由を得るか、制約のあるなかで楽に利用するかはユースケースに応じて検討してみてください。

Dokcer on ParallelCluster につていは本ブログ内でクラスターコンフィグ、postainstall.shの内容を公開しておりますのでお手元で再現できます。ぜひ試して評価してみてください。