本日も乙

ただの自己満足な備忘録。

ECS GPU-optimized AMIでECSを構築する

ECS で GPU インスタンスを使うときに、以前は自分で NVIDIA ドライバを入れたり、ECS エージェントを入れたりする必要がありましたが、最近(といっても昨年2月ですが)ECS GPU に最適化された AMI が出たことで ECS で GPU が使いやすくなりました。

aws.amazon.com

ECS で GPU を使う機運が高まってきたので試そうと思ったのですが、参考記事が意外と少なく、ドキュメントも質素なので情報が多く出回っていないようでした。

Amazon ECS での GPU の使用 - Amazon Elastic Container Service

そこで本記事は ECS GPU-optimized AMI で ECS クラスタを構築してみました。ECS サービスは作らずに nvidia-smi コマンドを実行するだけの簡単な ECS タスクを実行するだけです。GPU というよりも ECS のチュートリアルに近い内容となっています。
コンテナインスタンスのインスタンスタイプを g4dn.xlarge にしました。G4 インスタンスは最新世代の GPU インスタンスでありながら時間あたりの料金も安いのでちょっとした個人利用に便利です。

EC2 インスタンスの制限緩和申請

AWS アカウントを作成した直後は制限によって GPU インスタンスが起動できないため、サポートに制限緩和を申請する必要があります。申請が通るのに時間がかかるため一番最初にやります。
申請するにあたり、必要な vCPU 数が求められますので、vCPU 制限から確認します。

ec2-vcpu-limit

上図の[制限緩和のリクエスト]のリンクからサポートケースを開き、下図のように入力します。

ec2-limit-request

項目名
リージョン アジアパシフィック(東京)
プライマリインスタンスタイプ All G instances
New limit value 4

[Use case description] は利用用途(ECS クラスタで GPU インスタンスを試してみたいなど)を適宜入れてください。日本語で申請できます。申請後、数分で「担当部署に確認します」というレスポンスがきます。その後、7時間ぐらいして申請が通りました*1

AWS ネットワークの構築

VPC、サブネットの作成は省略します。コンテナインスタンスはプライベートサブネットに配置します。このサブネットに以下の VPC エンドポイントを設定します。

ゲートウェイタイプ

  • com.amazonaws.ap-northeast-1.s3

インタフェースタイプ

  • com.amazonaws.ap-northeast-1.ec2messages
  • com.amazonaws.ap-northeast-1.ecs
  • com.amazonaws.ap-northeast-1.ecs-agent
  • com.amazonaws.ap-northeast-1.ecs-telemetry
  • com.amazonaws.ap-northeast-1.logs
  • com.amazonaws.ap-northeast-1.ssm
  • com.amazonaws.ap-northeast-1.ssmmessages

また、コンテナインスタンスが Docker リポジトリからイメージを取得するために、NAT Gateway を立てる必要があります。もし NAT Gateway を立てたくない場合は、ECR にイメージを置いて ECR への VPC エンドポイントを作成します。

タスク定義の作成

タスク定義のコンソールに行き、[新しいタスク定義の作成]をクリックします。

  1. [起動タイプの互換性の選択]は [EC2] を選択します
  2. [タスクとコンテナの定義の設定]で次のように各項目を入力します。
項目名
タスク定義名 gpu-test
ネットワークモード awsvpc
タスク実行ロール なし
タスクメモリ (MiB) 512
タスク CPU (単位) 512

コンテナの定義

[コンテナの追加]をクリックし、次のように各項目を入力します。ここの設定でコンテナにおける GPU 数を設定することができます。

項目グループ 項目名
スタンダード コンテナ名 gpu
イメージ nvidia/cuda:9.0-base
プライベートレジストリの認証 チェックしない
メモリ制限 (MiB) ソフト制限、256
ポートマッピング 入力しない
ヘルスチェック - すべてデフォルト値
環境 CPU ユニット数 100
GPU 1
基本 チェックする
エントリポイント 入力しない
コマンド sh,-c,nvidia-smi
作業ディレクトリ 入力しない
Environment Files 入力しない
環境変数 入力しない
コンテナタイムアウト - すべてデフォルト値
ネットワーク設定 - すべてデフォルト値
ストレージとログ ログ設定 チェックする
セキュリティ - すべてデフォルト値
リソースの制限 - すべてデフォルト値
DOCKER ラベル - すべてデフォルト値

ECS クラスタの作成

クラスタのコンソールに行き、[クラスターの作成]をクリックします。
[クラスターテンプレートの選択]は[EC2 Linux + ネットワーキング]を選択し[次のステップ]をクリックします。
[クラスターの設定]では次のように各項目を入力して空の ECS クラスタを作成します。

項目名
クラスター名 gpu-test-cluster
空のクラスターの作成 チェックを入れる
Tags 入力しない
CloudWatch Container Insights チェックする

IAM ロールの作成

後で作成するコンテナインスタンスにアタッチするための IAM ロールを作成します。IAM ロールのコンソールに行き、[ロールの作成]をクリックします。
[ユースケースの選択]で[EC2]を選択し、[次のステップ:アクセス権限]をクリックします。[Attach アクセス権限ポリシー]において、次の IAM ポリシーをアタッチします。

  • AmazonEC2ContainerServiceforEC2Role
    • コンテナインスタンスを起動するために必要)
  • AmazonSSMManagedInstanceCore
    • System Manager のセッションマネージャによるログインをするために必要

次のタグ追加の画面をスキップし、IAM ロール名を myEcsInstanceRole と適当に命名します。

コンテナインスタンスの起動

今回は ECS サービスをつかわずに一回かぎりの ECS タスクを実行するためにコンテナインスタンスを起動します。
EC2 インスタンスのコンソールに行き、[インスタンスの作成]をクリックします。
コミュニティ AMI から ECS GPU-optimized AMI(amzn2-ami-ecs-gpu-hvm) を検索して最新の AMI を選択します。今回は amzn2-ami-ecs-gpu-hvm-2.0.20200430-x86_64-ebsami-0206eeb7625e98a0f)にしました。

設定値は次のようにします。

項目名
インスタンスタイプ g4dn.xlarge
インスタンス数 1
ネットワーク 事前に作成した VPC
サブネット 事前に作成したサブネット
自動割り当てパブリック IP 無効化
IAM ロール 先ほど作成した IAM ロール(myEcsInstanceRole
ユーザデータ 後述
タグ(Name) gpu-test-instance
セキュリティグループ 事前に作成したセキュリティグループ
キーペア キーペアなしで続行

ユーザデータでは次のように入力します。ECS エージェント起動時に ECS クラスタ(gpu-test-cluster)のコンテナインスタンスとして登録されるようになります。

#!/bin/bash
echo "ECS_CLUSTER=gpu-test-cluster" >> /etc/ecs/ecs.config

起動後、ECS クラスタの詳細の[ECS インスタンス]タブから EC2 インスタンスが表示されていることを確認します。

ecs-container-instance

もし、表示されていない場合は、コンテナインスタンスにセッションマネージャでログインし、ECS エージェントのログ(/var/log/ecs/ecs-agent.log)を見て原因を調査してください。

Amazon ECS ログファイルの場所 - Amazon Elastic Container Service

ECS タスクの実行

作成した ECS クラスタ(gpu-test-cluster)からタスク実行します。
先ほど作成した gpu-test-cluster の詳細画面に行き、[タスク]タブを選択し[新しいタスクの実行]をクリックします。

タスクの実行画面で次のように入力します。

項目名
起動タイプ EC2
タスク定義 gpu-test:1
クラスター gpu-test-cluster
タスクの数 1
タスクグループ gpu-test-group
クラスター VPC 事前に作成した VPC
サブネット 事前に作成したサブネット
セキュリティグループ 事前に作成したセキュリティグループ
パブリック IP の自動割り当て DISABLED
配置テンプレート AZ バランススプレッド

その他はデフォルトのまま[タスクの実行]をクリックします。
タスクのステータスが STOPPED (Essential container in task exited) になっていることを確認します(今回はコマンド実行だけなので、終了したらタスクも停止します)。
CloudWatch Logs のコンソールにいき、ロググループ /ecs/gpu-test をクリック、ログストリームをクリックすると、nvidia-smi コマンドの実行結果が表示されていることが確認できます。

ecs-gpu-cloudwatch-logs

後片付け

ずっと残しておくと料金がかかりつづけるため、以下のリソースを削除します。ECS や VPC ネットワーク、IAM ロールは料金がかからないので残しても良いです。

  • VPC エンドポイント(Privatelink)
  • NAT Gateway
  • EIP(NAT Gateway を作成したときにアタッチしたもの)
  • EC2 インスタンス
  • CloudWatch Logs

まとめ

ECS GPU に最適化された AMI で ECS クラスタおよびタスク定義を作成し、ECS タスクを実行してみました。コンテナ定義で GPU を設定すること以外は通常の ECS クラスタを作成するのとあまり変わりはありません。GPU を使う機会がある人は ECS で試されると良いかと思います。

参考文献

*1:私の場合なのでタイミングよっては対応速度は変わると思います