はじめに
本記事の目的
本記事では、Terraformを用いてAWS上にGPU搭載のEC2インスタンスを使ったECSクラスターを自動構築し、CUDA対応コンテナを簡単に動作させる基盤を作る方法を解説します。
特に、深層学習やGPGPUによる高負荷計算処理など、GPUリソースを必要とするユースケースにおいて、インフラの構築・運用を効率化することを目的としています。
「GPU付きEC2を起動して、CUDAが動くDockerコンテナをECSで動かしたいけど、設定が多くて大変そう...」という方に向けて、構築の自動化と再現性の確保を主眼に置いています。
作成されたレポジトリーはこちらです。
使用技術スタック
技術 | 用途 |
---|---|
AWS ECS | GPUコンテナの実行・管理基盤(EC2ベースのクラスター) |
AWS EC2 | GPU搭載のg4dnインスタンス(CUDA処理の実行) |
Terraform | インフラ構成のコード化と自動構築 |
Docker | CUDA対応コンテナの作成・実行 |
NVIDIA ドライバ + CUDA | GPUによる高速処理を可能にする |
PyTorch | 深層学習フレームワーク(動作確認用に使用) |
処理の流れ(起動~実行まで)
1. Terraformスクリプトの実行
bin/terraform_apply により、以下のリソースを自動作成:
- VPC、サブネット、セキュリティグループ
- ECSクラスター(EC2起動タイプ)
- g4dn.xlargeのGPU搭載EC2インスタンス(NVIDIAドライバ付きAMI)
- ECSタスク定義とサービス(CUDAコンテナ)
2. ECS上でコンテナ起動
GPU対応のDockerイメージ(PyTorch + CUDA)を使って、ECSタスクが起動。GPUが認識されていることをログで確認可能
3. CUDA・PyTorchの動作確認
起動したコンテナで torch.cuda.is_available() を実行し、CUDAが有効なことを検証
4. 停止・破棄
環境を不要にした場合は bin/terraform_destroy によりすべてのリソースを削除
ECSの基本概念とFargateとの違い
Amazon ECS は、AWS が提供するフルマネージドなコンテナオーケストレーションサービスです。Docker コンテナの起動・停止・スケジューリング・スケーリングなどを自動で管理できます。
ECS には主に以下の2つの実行タイプがあります:
実行タイプ | 概要 | 適したユースケース |
---|---|---|
EC2 | ユーザーがEC2インスタンスを用意し、その上でコンテナを実行 | GPU・特殊ドライバが必要なケース、細かなチューニング |
Fargate | サーバーレスで、AWSがコンテナのインフラを自動管理 | 小規模アプリ、スケーラビリティ重視、手軽に試したいとき |
本構成でEC2を選ぶ理由
Fargate は便利ですが、現時点(2025年4月)では GPUサポートがない ため、CUDAコンテナなどGPUを必要とするワークロードでは EC2 実行タイプ一択 となります。
このため、本記事では EC2ベースの ECS クラスターを構築し、GPUリソースを持つコンテナを直接実行します。
コンテナの構成とCUDA対応:実装方法
本セクションでは、PyTorch + CUDA で GPU 処理を行うコンテナの作成方法について、具体的な Dockerfile と Python スクリプトを交えて解説します。
このコンテナは、ECS 上で起動した際に GPU が正しく認識されているかどうかを検証するためのものです。
Dockerfile:PyTorch + CUDA対応イメージ
以下は、CUDA 11.8 + cuDNN 8 対応の PyTorch ベースイメージを使った Dockerfile です。
# ベースイメージ(CUDA11.8 + cuDNN8 対応 PyTorch)
FROM pytorch/pytorch:2.1.0-cuda11.8-cudnn8-runtime
# pip のアップグレード(依存関係のエラー回避)
RUN pip install --upgrade pip
# アプリケーションコードをコンテナ内にコピー
COPY main.py /main.py
# コンテナ起動時に main.py を実行
CMD ["python", "/main.py"]
main.py:GPUが使えるか確認するPythonコード
以下は、PyTorch で GPU(CUDA)が正しく動作しているかを確認するための Python スクリプトです。
import torch
print("CUDA Available:", torch.cuda.is_available())
print("Device Name:", torch.cuda.get_device_name(0))
x = torch.tensor([1.0, 2.0, 3.0]).cuda()
y = torch.tensor([9.0, 8.0, 7.0]).cuda()
z = x + y
print("Result:", z)
CUDA対応ECS AMIの取得
ECS GPU 対応インスタンスを立ち上げるには、Amazon が提供する ECS 対応 GPU AMIを使用します。
data "aws_ami" "app" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["amzn2-ami-ecs-gpu-hvm-*-x86_64-ebs"]
}
filter {
name = "architecture"
values = ["x86_64"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
filter {
name = "root-device-type"
values = ["ebs"]
}
}
Launch Template の作成
ECS クラスタに参加する EC2(GPU搭載)のインスタンスを定義します。
resource "aws_launch_template" "ecs_gpu_launch_template" {
name_prefix = "ecs-gpu-"
image_id = data.aws_ami.app.id
instance_type = "g4dn.xlarge"
key_name = aws_key_pair.keypair.key_name
iam_instance_profile {
name = var.instance_profile_name
}
network_interfaces {
associate_public_ip_address = true
security_groups = [var.sg_ecs_id]
subnet_id = var.public_subnet_1a_id
}
user_data = base64encode(<<-EOF
#!/bin/bash
set -euo pipefail
# ECS クラスター名と GPU サポート設定
cat <<EOT > /etc/ecs/ecs.config
ECS_CLUSTER=chatbot-cluster
ECS_ENABLE_GPU_SUPPORT=true
EOT
# ECS 再起動スクリプト
cat <<'EOT' > /usr/local/bin/start-ecs.sh
#!/bin/bash
systemctl stop ecs || true
systemctl enable ecs
systemctl start ecs
EOT
chmod +x /usr/local/bin/start-ecs.sh
# cloud-init 完了時に ECS を起動
cat <<'EOT' > /etc/cloud/cloud.final.d/99-start-ecs.cfg
#cloud-config
runcmd:
- [ /usr/local/bin/start-ecs.sh ]
EOT
EOF
)
instance_market_options {
market_type = "spot"
spot_options {
instance_interruption_behavior = "terminate"
spot_instance_type = "one-time"
}
}
tag_specifications {
resource_type = "instance"
tags = {
Name = "gpu-ecs-instance"
}
}
}
Auto Scaling Group の設定
ECS の GPU インスタンスを ASG(Auto Scaling Group)で管理します。
resource "aws_autoscaling_group" "ecs_gpu_asg" {
name = "ecs-gpu-asg"
desired_capacity = 1
max_size = 1
min_size = 1
vpc_zone_identifier = [var.public_subnet_1a_id]
health_check_type = "EC2"
health_check_grace_period = 300
launch_template {
id = aws_launch_template.ecs_gpu_launch_template.id
version = "$Latest"
}
tag {
key = "Name"
value = "gpu-ecs-instance"
propagate_at_launch = true
}
lifecycle {
create_before_destroy = true
}
}
EC2 キーペアの管理
SSHログインやトラブル時のデバッグ用にキーペアもTerraformで定義します。
resource "aws_key_pair" "keypair" {
key_name = "${var.app_name}-keypair"
public_key = file("./modules/ec2/src/keypair.pub")
tags = {
Name = "${var.app_name}-keypair"
}
}
CloudWatch ロググループの作成
ECS コンテナのログは CloudWatch Logs に出力させるのが定番です。
resource "aws_cloudwatch_log_group" "ecs_log" {
name = "/ecs/pytorch-gpu"
retention_in_days = 7
}
ECS クラスターの作成
ECS クラスターを作成し、Container Insights を有効化することで CloudWatch でリソースの可視化が可能になります。
resource "aws_ecs_cluster" "gpu_cluster" {
name = "${var.app_name}-cluster"
setting {
name = "containerInsights"
value = "enabled"
}
tags = {
Name = "${var.app_name}-cluster"
}
}
ECSタスク定義(GPUリソース付き)
CUDA コンテナを ECS 上で動かすには、GPUリソース要求を明示的に設定する必要があります。
resource "aws_ecs_task_definition" "pytorch_gpu_task" {
family = "pytorch-gpu-task"
network_mode = "bridge"
requires_compatibilities = ["EC2"]
execution_role_arn = var.iam_role_ecs_role_arn
task_role_arn = var.iam_role_ecs_role_arn
container_definitions = jsonencode([
{
name = "pytorch-gpu-container"
image = "${var.ai_repository_url}:latest"
essential = true
cpu = 4096,
memory = 15000,
resourceRequirements = [
{
type = "GPU"
value = "1"
}
],
logConfiguration = {
logDriver = "awslogs",
options = {
awslogs-group = "/ecs/pytorch-gpu",
awslogs-region = "ap-northeast-1",
awslogs-stream-prefix = "ecs"
}
}
}
])
}
ECSサービスの作成
1つのタスクを常に動作させるシンプルなサービス構成です。
resource "aws_ecs_service" "pytorch_gpu_service" {
name = "pytorch-gpu-service"
cluster = aws_ecs_cluster.gpu_cluster.id
task_definition = aws_ecs_task_definition.pytorch_gpu_task.arn
desired_count = 1
launch_type = "EC2"
deployment_controller {
type = "ECS"
}
}
実行結果
クラウドコンソール上で、以下の画面が出たら成功