0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

TerraformでFramePackをAWS EC2(g6.2xlarge)にデプロイする

0
Posted at

はじめに

FramePack は lllyasviel 氏が開発した動画生成モデルで、1枚の画像からプロンプトに沿った短い動画を生成できます。GPU が必要なため、手元に GPU マシンがない場合は EC2 の GPU インスタンスを使うのが手軽です。

この記事では Terraform を使って EC2 環境を一発構築し、SSH トンネル経由で Gradio UI にアクセスするまでの手順をまとめます。インフラのコード化により、使い終わったら terraform destroy で即削除できるのがメリットです。

構成

項目
インスタンスタイプ g6.2xlarge(NVIDIA L4 GPU)
AMI Deep Learning OSS Nvidia Driver AMI GPU PyTorch 2.10 (Ubuntu 24.04)
リージョン ap-northeast-1
ストレージ gp3 150GB(暗号化)
FramePack lllyasviel/FramePack + kustomzone/FramePack-eichi
PyTorch 2.6.0 + CUDA 12.6
起動方法 systemd サービス(ポート 7860、localhost のみ)

セキュリティグループは SSH(22番)を自分のIPからのみ許可し、Gradio は 127.0.0.1:7860 にバインドして外部公開しない設計にしています。

前提条件

  • Terraform >= 1.5.0
  • AWS CLI が設定済み(aws configure 済み)
  • EC2 キーペアが作成済み
  • g6.2xlarge が利用可能な AZ を確認済み(東京リージョンは ap-northeast-1a で利用可)

g6 系インスタンスはサービスクォータのデフォルト上限に引っかかる場合があります。初回利用時は Running On-Demand G and VT instances のクォータを引き上げておいてください(vcpu換算で8必要)。

ファイル構成

framepack/
├── main.tf
├── variables.tf
├── terraform.tfvars          # 実際の値(git 管理しない)
├── terraform.tfvars.example  # サンプル
└── userdata.sh.tftpl         # EC2 起動時の自動セットアップスクリプト

Terraform コード

variables.tf

variable "aws_region" {
  type    = string
  default = "ap-northeast-1"
}

variable "key_name" {
  type        = string
  description = "EC2 key pair name"
}

variable "my_ip_cidr" {
  type        = string
  description = "Your IP address in CIDR notation (e.g., 123.456.789.0/32)"
}

variable "eichi_github_username" {
  type    = string
  default = "x-access-token"
}

variable "eichi_github_token" {
  type      = string
  default   = ""
  sensitive = true
}

main.tf

terraform {
  required_version = ">= 1.5.0"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = var.aws_region
}

locals {
  instance_type = "g6.2xlarge"
  vpc_cidr      = "10.0.0.0/16"
  az            = "${var.aws_region}a"
}

# g6.2xlarge が指定 AZ で利用可能かチェック
data "aws_ec2_instance_type_offerings" "g6" {
  filter {
    name   = "instance-type"
    values = [local.instance_type]
  }
  location_type = "availability-zone"
}

# VPC
resource "aws_vpc" "framepack" {
  cidr_block           = local.vpc_cidr
  enable_dns_hostnames = true
  enable_dns_support   = true

  tags = { Name = "framepack-vpc" }
}

resource "aws_internet_gateway" "framepack" {
  vpc_id = aws_vpc.framepack.id
  tags   = { Name = "framepack-igw" }
}

resource "aws_route_table" "public" {
  vpc_id = aws_vpc.framepack.id

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.framepack.id
  }

  tags = { Name = "framepack-public-rt" }
}

resource "aws_subnet" "public" {
  vpc_id                  = aws_vpc.framepack.id
  cidr_block              = "10.0.1.0/24"
  availability_zone       = local.az
  map_public_ip_on_launch = true

  tags = { Name = "framepack-public-subnet" }
}

resource "aws_route_table_association" "public" {
  subnet_id      = aws_subnet.public.id
  route_table_id = aws_route_table.public.id
}

# AMI(最新の Deep Learning AMI を自動取得)
data "aws_ami" "dlami" {
  most_recent = true
  owners      = ["amazon"]

  filter {
    name   = "name"
    values = ["Deep Learning OSS Nvidia Driver AMI GPU PyTorch 2.10 (Ubuntu 24.04) *"]
  }

  filter {
    name   = "architecture"
    values = ["x86_64"]
  }

  filter {
    name   = "state"
    values = ["available"]
  }

  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }
}

# セキュリティグループ(SSH のみ)
resource "aws_security_group" "framepack" {
  name        = "framepack-sg"
  description = "FramePack SSH access"
  vpc_id      = aws_vpc.framepack.id

  ingress {
    description = "SSH from my IP"
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = [var.my_ip_cidr]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = { Name = "framepack-sg" }
}

# EC2 インスタンス
resource "aws_instance" "framepack" {
  ami                         = data.aws_ami.dlami.id
  instance_type               = local.instance_type
  subnet_id                   = aws_subnet.public.id
  vpc_security_group_ids      = [aws_security_group.framepack.id]
  associate_public_ip_address = true
  key_name                    = var.key_name

  user_data = templatefile("${path.module}/userdata.sh.tftpl", {
    eichi_github_username = var.eichi_github_username
    eichi_github_token    = var.eichi_github_token
  })

  root_block_device {
    volume_type = "gp3"
    volume_size = 150
    encrypted   = true
  }

  tags = { Name = "framepack" }

  lifecycle {
    precondition {
      condition     = contains(data.aws_ec2_instance_type_offerings.g6.locations, local.az)
      error_message = "指定した AZ ${local.az} では g6.2xlarge が利用できません。"
    }
  }
}

output "public_ip"  { value = aws_instance.framepack.public_ip }
output "public_dns" { value = aws_instance.framepack.public_dns }
output "ami_id"     { value = data.aws_ami.dlami.id }

AMI は data "aws_ami" で毎回最新を自動取得します。また lifecycle.precondition で g6.2xlarge が対象 AZ で利用可能かを terraform apply 前に確認しています。

userdata.sh.tftpl

EC2 起動直後に自動実行されるセットアップスクリプトです。

#!/bin/bash
set -euxo pipefail
exec > /var/log/framepack-eichi-userdata.log 2>&1

export DEBIAN_FRONTEND=noninteractive
APP_DIR=/home/ubuntu/FramePack
VENV_DIR=/home/ubuntu/FramePack/.venv
EICHI_SRC_DIR=/home/ubuntu/FramePack-eichi-src
EICHI_TOKEN='${eichi_github_token}'
EICHI_GITHUB_USERNAME='${eichi_github_username}'

apt-get update
apt-get install -y git python3.11 python3.11-venv ffmpeg rsync

# FramePack 本体をクローン
if [ ! -d "$APP_DIR/.git" ]; then
  runuser -u ubuntu -- git clone https://github.com/lllyasviel/FramePack.git "$APP_DIR"
fi

# FramePack-eichi をクローン(GitHub Token があれば private repo にも対応)
if [ ! -d "$EICHI_SRC_DIR/.git" ]; then
  if [ -n "$EICHI_TOKEN" ]; then
    runuser -u ubuntu -- git clone \
      "https://${EICHI_GITHUB_USERNAME}:${EICHI_TOKEN}@github.com/kustomzone/FramePack-eichi.git" \
      "$EICHI_SRC_DIR"
  else
    runuser -u ubuntu -- git clone \
      "https://github.com/kustomzone/FramePack-eichi.git" \
      "$EICHI_SRC_DIR"
  fi
fi

# eichi の webui と起動スクリプトを FramePack に上書き
if [ -d "$EICHI_SRC_DIR/webui" ]; then
  runuser -u ubuntu -- rsync -a "$EICHI_SRC_DIR/webui/" "$APP_DIR/"
fi

for f in endframe_ichi.py endframe_ichi_f1.py oneframe_ichi.py; do
  if [ -f "$EICHI_SRC_DIR/$f" ]; then
    runuser -u ubuntu -- cp "$EICHI_SRC_DIR/$f" "$APP_DIR/$f"
  fi
done

# Python 仮想環境を作成し、PyTorch (CUDA 12.6) をインストール
runuser -u ubuntu -- python3.11 -m venv "$VENV_DIR"
runuser -u ubuntu -- "$VENV_DIR/bin/pip" install --upgrade pip
runuser -u ubuntu -- "$VENV_DIR/bin/pip" uninstall -y torch torchvision torchaudio || true
runuser -u ubuntu -- "$VENV_DIR/bin/pip" install \
  torch==2.6.0 torchvision==0.21.0 torchaudio==2.6.0 \
  --index-url https://download.pytorch.org/whl/cu126
runuser -u ubuntu -- "$VENV_DIR/bin/pip" install -r "$APP_DIR/requirements.txt"

# Hugging Face キャッシュ用ディレクトリ
mkdir -p /home/ubuntu/hf_cache
chown -R ubuntu:ubuntu /home/ubuntu/hf_cache

# systemd サービスとして登録
cat > /etc/systemd/system/framepack-eichi.service << 'EOF'
[Unit]
Description=FramePack-eichi Gradio
After=network-online.target

[Service]
Type=simple
User=ubuntu
WorkingDirectory=/home/ubuntu/FramePack
Environment=PYTHONUNBUFFERED=1
Environment=HF_HOME=/home/ubuntu/hf_cache
ExecStart=/home/ubuntu/FramePack/.venv/bin/python \
  /home/ubuntu/FramePack/endframe_ichi.py \
  --server 127.0.0.1 --port 7860
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable framepack-eichi.service
systemctl restart framepack-eichi.service

ポイントは以下の通りです。

  • runuser -u ubuntu -- で各コマンドを ubuntu ユーザーとして実行し、ファイルの所有者が root にならないようにしています
  • PyTorch は DLAMI にプリインストールされているものとバージョンが合わない可能性があるため、一度 uninstall してから cu126 対応版を明示的に入れ直しています
  • Gradio は --server 127.0.0.1 でローカルホストのみにバインドし、外部から直接アクセスできない構成にしています

terraform.tfvars

key_name   = "your-key-pair-name"
my_ip_cidr = "x.x.x.x/32"  # curl ifconfig.me で確認

# FramePack-eichi を private fork から使う場合のみ設定
# eichi_github_username = "x-access-token"
# eichi_github_token    = "ghp_xxxxxxxxxxxxxxxxxxxx"

my_ip_cidrcurl ifconfig.me で取得した自分のグローバル IP を /32 で指定してください。

デプロイ手順

cd framepack/
terraform init
terraform plan
terraform apply

apply が完了すると以下のような出力が得られます。

Outputs:

ami_id     = "ami-xxxxxxxxxxxxxxxxx"
public_dns = "ec2-xx-xx-xx-xx.ap-northeast-1.compute.amazonaws.com"
public_ip  = "xx.xx.xx.xx"

初回起動時は userdata スクリプトが裏で動いています。完了まで 10〜15分程度かかります。進捗は SSH してログで確認できます。

ssh -i your-key.pem ubuntu@$(terraform output -raw public_ip)
tail -f /var/log/framepack-eichi-userdata.log

systemctl status framepack-eichi.serviceactive (running) になっていれば準備完了です。

SSH トンネルで接続する

Gradio は localhost にしかバインドしていないため、SSH トンネルでポートフォワードします。

# ローカルの 7860 を EC2 の 127.0.0.1:7860 に転送
ssh -i your-key.pem \
  -L 7860:127.0.0.1:7860 \
  ubuntu@$(terraform output -raw public_dns)

このターミナルを開いたまま、ブラウザで以下にアクセスします。

http://127.0.0.1:7860

FramePack-eichi の Gradio UI が表示されれば成功です。

使い終わったら削除する

GPU インスタンスは従量課金なので、使い終わったら必ず削除してください。g6.2xlarge のオンデマンド料金は東京リージョンで 約 $1.0/時間です。

terraform destroy

まとめ

  • Terraform でVPC・EC2・セキュリティグループをまとめて管理することで、環境構築と削除を冪等に行えます
  • userdata でセットアップを自動化しているため、terraform apply から15分程度でブラウザからアクセスできる状態になります
  • セキュリティグループで SSH のみ許可し、Gradio を localhost バインドにすることで外部公開しない安全な構成にしています
  • スポットインスタンスを使えばコストを 60〜70% 削減できます(中断リスクとのトレードオフ)

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?