6
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?

AWS Batch版のMetaflowのデプロイを安価に試したい際に特に注意したい点

Last updated at Posted at 2025-11-19

背景

最近クラウド上で機械学習のパイプラインを実行するツールを調べていてMetaflowを試していました。
MetaflowをAWSなどクラウドへデプロイすることで、クラウド上でパイプラインの実行ができます。

Metaflowではデプロイ用のコードがいくつか配布されており、AWS Batchを使用するものや、Kubernetesを使う構成など、Metaflowの構成ごとに定義が用意されています。

実験としてAWS Batchを利用する構成を試していたのですが、
2025-11-06現在、安くデプロイしたい場合に特に気を付けておきたい設定があったので、注意点を残しておこうと思います。

前提

この記事では以下のバージョンを使用しています。

  • terraform-aws-metaflow: v0.12.1
  • Terraform: 1.6.6
  • AWS Provider: 5.70.0

また、AWSのリージョンはap-northeast-1を使用しています。

Metaflowとは

Metaflowは、Netflixが開発しオープンソース化した機械学習パイプラインのフレームワークです。Pythonでデータサイエンスのワークフローを記述し、ローカル環境からAWS BatchやKubernetesなどのクラウド環境へシームレスに移行できます。

今回はAWS Batchを使った構成を試しました。

Metaflowのパイプライン

Metaflowではステップという単位でパイプラインをコード上で構築し、各ステップをクラウドまたはローカルのサーバ上でコンテナを使って実行できます。

以下はPythonでパイプラインを記述した例です。

from metaflow import step, FlowSpec

class HelloWorldFlow(FlowSpec):

    @step
    def start(self):
        """First step"""
        print("This is the start step")
        self.next(self.hello)

    @step
    def hello(self):
        """Just saying hi"""
        self.my_greet_text = "Hello World!"
        print(self.my_greet_text)
        self.next(self.end)

    @step
    def end(self):
        """Finish line"""
        print("This is the end step")

if __name__ == '__main__':
    HelloWorldFlow()
パイプラインの実行例
$ uv run hello.py run
Metaflow 2.18.13 executing HelloWorldFlow for user:dninomiya
Validating your flow...
    The graph looks good!
Running pylint...
    Pylint not found, so extra checks are disabled.
2025-11-10 14:04:10.756 Workflow starting (run-id 1762751050751473):
2025-11-10 14:04:10.790 [1762751050751473/start/1 (pid 19416)] Task is starting.
2025-11-10 14:04:11.124 [1762751050751473/start/1 (pid 19416)] This is the start step
2025-11-10 14:04:11.178 [1762751050751473/start/1 (pid 19416)] Task finished successfully.
2025-11-10 14:04:11.194 [1762751050751473/hello/2 (pid 19436)] Task is starting.
2025-11-10 14:04:11.541 [1762751050751473/hello/2 (pid 19436)] Hello World!
2025-11-10 14:04:11.574 [1762751050751473/hello/2 (pid 19436)] Task finished successfully.
2025-11-10 14:04:11.587 [1762751050751473/end/3 (pid 19470)] Task is starting.
2025-11-10 14:04:11.873 [1762751050751473/end/3 (pid 19470)] This is the end step
2025-11-10 14:04:11.907 [1762751050751473/end/3 (pid 19470)] Task finished successfully.
2025-11-10 14:04:11.909 Done!

Terraform を使った Metaflow のデプロイの注意点

ここからはAWS Batchを使った構成で、安い維持費でインスタンスを立てるのにいくつか注意が必要なTerraformの設定を挙げておこうと思います。

要件やサービスのその時の価格によりますが、設定次第ではMetaflowの維持費を$60~70/月程度に抑えることができます。

ここからは特にお金がかかりやすい以下の3つの設定について説明します。

  • RDSの設定
  • UIの有効化設定
  • トレーニングに使用するインスタンスの設定

RDSの設定

RDSはこの構成の中でも費用がかかるため、注意が必要です。

PostgreSQLのバージョン設定

特に、デフォルトで立つPostgreSQLのバージョン11が利用されるため、そのまま上げるとサポート切れバージョン用の追加費用がかかります。

terraform-aws-metaflow/modules/datastore/variables.tf
variable "db_engine_version" {
  type    = string
  default = "11" # デフォルトでは11になっている
}

料金を抑えたい場合は サポートのかからないバージョンを設定しましょう

terraform.tfvars
# バージョンを指定する際は公式のドキュメントを確認し、サポートの範囲に入っているか必ず確認しましょう
db_engine_version = 15

1ヶ月間のRDS PostgreSQL サポート延長料金

DBインスタンス名 単価 数量 月額
db.t2.small $0.12/vCPU/時間 1 $86.40

計算式:

  • 1 vCPU × $0.12 × 24時間 × 30日 = $86.40

PostgreSQLバージョン変更に伴うDocker Imageの変更

また、Postgresのバージョンが15以上の場合、SSLを使った通信を行うようにTerraform内で設定されています。
以下のバージョンのDocker Imageがデフォルトで使われていますが、SSL通信に対応していないため、SSL通信に対応したDocker Imageを選択する必要があります。

terraform-aws-metaflow/modules/common/locals.tf
locals {
  default_metadata_service_container_image = "netflixoss/metaflow_metadata_service:v2.3.0" # v2.3.0ではSSL通信ができず、エラーが起きてしまった
  ...
}
main.tf
module "metaflow" {
  ...
  # PostgreSQL 15のSSL接続に対応した最新のメタデータサービスイメージを使用
  metadata_service_container_image = "netflixoss/metaflow_metadata_service:v2.4.13"
  ...
}

RDSのマルチAZの設定

デフォルトではマルチAZ設定がtrueになっています。
可用性が減りますが、モジュールファイルを編集してfalseにすることで料金をさらに減らす事が可能です。

この設定はモジュール内で直接定義されているため、クローンしたモジュールファイルを編集する必要があります。

terraform-aws-metaflow/modules/datastore/rds.tf
resource "aws_db_instance" "this" {
  # ...
  multi_az = true  # デフォルトはtrue
  # ...
}

コスト削減のため、以下のように変更します。

terraform-aws-metaflow/modules/datastore/rds.tf
resource "aws_db_instance" "this" {
  # ...
  multi_az = false  # 開発環境ではfalseに変更してコスト削減
  # ...
}

:warning: 注意: マルチAZを無効化すると、単一のAZに障害が発生した場合にRDSが利用できなくなります。本番環境ではtrueのままにすることを推奨します

UIの有効化設定

パイプラインの図やログをブラウザ上で見られるサーバをデプロイすることができます。

UI自体はオプションで、デプロイしなくてもMetaflowの機能を使うことができます。
デフォルトではUIをデプロイしない設定になっています。

terraform-aws-metaflow/variables.tf
variable "ui_certificate_arn" {
  type        = string
  default     = ""
  description = "SSL certificate for UI. If set to empty string, UI is disabled. "
}

ui_certificate_arnを設定するとUIのサーバがECSでデプロイされますが、オンデマンド料金がかかるので注意が必要です。

Metaflowを実験として使用する場合、UIは必須ではないため、料金を抑えたい方はUIをオフにすることをお勧めします。

1ヶ月間UIを起動した際のECS Fargateの料金

UIではecs_ui_backendecs_ui_staticの2つのサービスがデプロイされます。
それぞれ以下のような料金がかかります。

コンポーネント vCPU メモリ(GB) vCPU料金/月 メモリ料金/月 合計/月
ecs_ui_backend 2.0 16 $72.00 $57.60 $129.60
ecs_ui_static 0.5 1 $18.00 $3.60 $21.60

計算式:

  • vCPU料金 = vCPU数 × $0.05/時間 × 24時間 × 30日
  • メモリ料金 = メモリGB × $0.005/時間 × 24時間 × 30日
    • 値段が変わっている可能性があるため、詳細は公式サイトを参照してください

トレーニングに使用するインスタンスの設定

AWS Batchで利用するインスタンスの設定ができます。
デフォルトでは常時EC2インスタンスが立ち続けるため、維持費用が嵩みます。
また、AWS Batchで使うインスタンスを指定できます。

デフォルトでは以下のようになっています。

terraform-aws-metaflow/variables.tf
variable "compute_environment_desired_vcpus" {
  type        = number
  description = "Desired Starting VCPUs for Batch Compute Environment [0-16] for EC2 Batch Compute Environment (ignored for Fargate)"
  default     = 8
}

variable "compute_environment_min_vcpus" {
  type        = number
  description = "Minimum VCPUs for Batch Compute Environment [0-16] for EC2 Batch Compute Environment (ignored for Fargate)"
  default     = 8
}

variable "compute_environment_instance_types" {
  type        = list(string)
  description = "The instance types for the compute environment"
  default     = ["c4.large", "c4.xlarge", "c4.2xlarge", "c4.4xlarge", "c4.8xlarge"]
}

以下のようにcompute_environment_min_vcpuscompute_environment_desired_vcpus0に設定することで、トレーニング時のみインスタンスが起動します。

terraform.tfvars
compute_environment_min_vcpus      = 0
compute_environment_desired_vcpus  = 0
compute_environment_instance_types = [
  "c5.large",
  "g4dn.xlarge"
]

GPUのインスタンスの選択の際、機械学習用のコードがNVIDIAのGPU(cuda)を使う設定なら、g4dn.xlargeなどNVIDIAのGPUを積んだインスタンスを選択するといいかと思います。

1ヶ月間常時インスタンスを立てた場合の料金

仮にcompute_environment_min_vcpuscompute_environment_desired_vcpus0にせず、c4.2xlargeがデプロイされ続けるとすると、月に以下の料金がかかります。

インスタンスタイプ vCPU メモリ 時間単価 月額(24h×30日)
c4.2xlarge 8 15 GB $0.398 $286.56

計算式:

  • インスタンス料金 = $0.398/時間 × 24時間 × 30日
    • 料金は変動する可能性があるため、最新の料金はAWS EC2料金ページをご確認ください

最終的なコード

これらのコスト最適化設定を実装したTerraform設定ファイルを以下に示します。

前準備

まず、terraform-aws-metaflowモジュールをクローンします。

git clone https://github.com/outerbounds/terraform-aws-metaflow.git

ディレクトリ構成

.
├── main.tf                    # メインの設定ファイル
├── variables.tf               # 変数定義
├── provider.tf                # AWSプロバイダー設定
├── versions.tf                # バージョン制約
├── terraform.tfvars           # 環境固有の設定値
└── terraform-aws-metaflow/    # Metaflowモジュール(cloneしたリポジトリ)

コード

main.tf
# リソース名の重複を避けるためのランダムなサフィックス
resource "random_string" "suffix" {
  length  = 8
  special = false
  upper   = false
}

locals {
  resource_prefix = "metaflow"
  resource_suffix = random_string.suffix.result
}

data "aws_availability_zones" "available" {
}

data "aws_region" "current" {
}

# VPC の作成
module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "5.1.2"

  name = "${local.resource_prefix}-${local.resource_suffix}"
  cidr = "10.10.0.0/16"

  # 最小限の2つのAZ(RDSの要件を満たす最小構成)
  # 本番環境ではセキュリティのためprivate_subnetsの使用を推奨
  azs             = slice(data.aws_availability_zones.available.names, 0, 2)
  private_subnets = []
  public_subnets  = ["10.10.128.0/21", "10.10.136.0/21"]

  # Public subnetを使用するため、NAT GatewayとPrivate subnetは不要
  enable_nat_gateway      = false
  single_nat_gateway      = false
  enable_dns_hostnames    = true
  map_public_ip_on_launch = true

  tags = {
    "managedBy" = "terraform"
    "project"   = "metaflow"
  }
}

# コスト最適化設定でMetaflowをデプロイ
module "metaflow" {
  source = "./terraform-aws-metaflow"

  resource_prefix = local.resource_prefix
  resource_suffix = local.resource_suffix

  # VPC設定
  subnet1_id      = module.vpc.public_subnets[0]
  subnet2_id      = module.vpc.public_subnets[1]
  vpc_cidr_blocks = [module.vpc.vpc_cidr_block]
  vpc_id          = module.vpc.vpc_id
  with_public_ip  = true

  # Step Functionsを無効化
  enable_step_functions = false

  # UI設定(デフォルトでは無効)
  ui_certificate_arn = var.ui_certificate_arn

  # PostgreSQL 15のSSL接続に対応した最新のメタデータサービスイメージを使用
  metadata_service_container_image = "netflixoss/metaflow_metadata_service:v2.4.13"

  # RDS PostgreSQLのバージョン設定
  db_engine_version = var.db_engine_version
  db_instance_type  = var.db_instance_type

  # AWS Batch - 必要時のみインスタンス起動
  compute_environment_min_vcpus      = var.compute_environment_min_vcpus
  compute_environment_desired_vcpus  = var.compute_environment_desired_vcpus
  compute_environment_instance_types = var.compute_environment_instance_types

  tags = {
    "managedBy"   = "terraform"
    "environment" = "development"
    "project"     = "metaflow"
  }
}

# Metaflowモジュールの全ての出力をエクスポート
output "metaflow" {
  value     = module.metaflow
  sensitive = true
}

# Metaflow設定ファイルを出力
resource "local_file" "metaflow_config" {
  content  = module.metaflow.metaflow_profile_json
  filename = "${path.module}/metaflow_profile.json"
}
variables.tf
# AWSリージョンの設定
variable "aws_region" {
  type        = string
  description = "AWS region to deploy Metaflow infrastructure"
  default     = "us-east-1"
}

# RDSの設定
variable "db_engine_version" {
  type        = string
  description = "PostgreSQL version for RDS. Use version 15+ to avoid extended support charges."
  default     = "15"
}

variable "db_instance_type" {
  type        = string
  description = "RDS instance type. db.t3.micro is suitable for development/testing."
  default     = "db.t3.micro"
}

# AWS Batchの設定
variable "compute_environment_min_vcpus" {
  type        = number
  description = "Minimum VCPUs. Set to 0 to avoid idle costs."
  default     = 0
}

variable "compute_environment_desired_vcpus" {
  type        = number
  description = "Desired VCPUs. Set to 0 to avoid idle costs."
  default     = 0
}

variable "compute_environment_instance_types" {
  type        = list(string)
  description = "Instance types for Batch compute environment. Include GPU instances if needed for ML workloads."
  default = [
    "c5.large",
    "g4dn.xlarge"
  ]
}

# UI設定
variable "ui_certificate_arn" {
  type        = string
  description = "SSL certificate ARN for UI. Leave empty to disable UI and save ~$151/month."
  default     = ""
}
provider.tf
provider "aws" {
  region = "ap-northeast-1"
}
versions.tf
terraform {
  required_version = ">= 0.13"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "5.70.0"
    }
    random = {
      source  = "hashicorp/random"
      version = "~> 3.0"
    }
    local = {
      source  = "hashicorp/local"
      version = "~> 2.0"
    }
  }
}
terraform.tfvars
# PostgreSQL 15以上を使用すると、SSL接続が自動的に有効化されます
db_engine_version                  = "15"
db_instance_type                   = "db.t3.micro"
compute_environment_min_vcpus      = 0
compute_environment_desired_vcpus  = 0
compute_environment_instance_types = ["c5.large", "g4dn.xlarge"]
terraform-aws-metaflow/modules/datastore/rds.tf(マルチAZ設定の変更)

クローンしたモジュール内のファイルを編集します。114行目付近のmulti_azfalseに変更してください。

resource "aws_db_instance" "this" {
  ...
  multi_az                              = false  # デフォルトはtrue、開発環境ではfalseに変更してコスト削減
  ...
}

デプロイ手順

# 初期化
terraform init

# デプロイ
terraform apply

終わりに

他にも追加で安価にする設定もいくつかありますが、これらの設定のコストが特に高いため、注意が必要です。
クラウド上で機械学習パイプラインを構築する際の参考になれば幸いです。

6
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
6
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?