Terraform + Amazon EC2で簡単にML用sandbox環境を構築する
こんにちは、デルタです。
ナビタイムジャパンの研究開発部門で道路規制や、渋滞情報などの交通情報提供を担当しています。
このnoteでは研究開発業務で作成したsandbox用クラウド環境構築システムについてご紹介します。
最初に軽く自己紹介させていただきましたが、私は研究開発部門で交通情報提供業務を担当しているチームに所属しており、特に渋滞予測の精度向上について力を入れています。
最近はML(機械学習)を使った業務も多く、sandbox用環境の整備の需要が高まってきたため、チームメンバーが誰でも簡単にクラウド上に環境を作成できるようなシステムの構築を行いました。
構築したシステムの概要
詳細は後述しますが、全体像としてはTerraformを利用してEC2インスタンスを立ち上げるシステムになっています。
必要になった時に立ち上げて使い終わったら破棄する使い方になります。
今回はML用の環境を作成していますが、クラウド上にぱっとリソースを確保したいという目的には汎用的に応用できると思います。
sandbox環境のため、本番運用は想定していないことにご注意ください。
求める要件からシステムを考える
求める要件の整理
まずは取り組んでいるタスクや使い方に合わせて要件を整理します。
わたしたちの主なタスクは渋滞予測です。
全国の道路に対するユーザの走行履歴が主なインプットになるため、膨大なデータの処理が必要です。
生成系やOCRのような汎用タスクではないため、独自のモデル構築が必要になります。
また、ML用の環境構築に詳しくないチームメンバーでも簡単に使えるようなシステムにすることと、研究開発段階のものはサービスに乗らない可能性もあるためギリギリまでコストを抑えたいという要件も加えます。
整理すると次のような要件になりました。
膨大なデータの処理ができる
独自のモデルの構築ができる
チームメンバーが誰でも簡単に使える
コストはなるべく抑える
クラウド上でのリソース確保
自由に色々お試しをしていきたい場合、一番お手軽なのはローカルでの環境構築になりますが、データが膨大なためリソース確保が難しいことや、ML用環境構築は面倒なことも多いためクラウド上での構築にしました。
クラウドサービスについては要件的にどこでも大丈夫でしたが、今回は当社でメインで利用しているAWSを選択しました。
AWSでMLと言えばSageMakerが思い浮かびますが、独自モデルをいじりたいという要件にあまり合わなかったため、今回はシンプルにEC2インスタンスを立ち上げることにしました。
EC2インスタンスの中にもさまざまな種類がありますが、今回の場合は膨大なデータを取り込みたいという要件からある程度のメモリが必要であること、またGPUも利用したいためG4インスタンスを選択しました。
今回はsandboxのため安定稼働が必要ないことと、コストを抑えたいという要件からスポットインスタンスで立ち上げています。
また、自分でPython環境やML系のライブラリ等を全部インストールすると面倒なため、基本的なものがすべて用意されているDLAMIを利用しました。
構築手順のコード化
構築したい環境についてはある程度決まりましたが、この環境をお手軽に立ち上げられて、誰でも同じ環境が作れるようにする必要があります。
また、コスト面から高額インスタンスを常に立ち上げるのは現実的ではないため、使う時だけ立ち上げる破棄する使い捨ての運用が想定されます。
そのため、コード化して構築を自動化する必要が出てきました。
今回は自動化するためのツールとしてTerraformを利用しています。
TerraformはInfrastructure as Code(IaC)ツールの一つであり、クラウドリソース管理の自動化が可能になります。
同様のツールとしてAWS CloudFormationがありますが、yaml記述に慣れているメンバーもいないため、より表現の幅が広いHCLで記述ができるTerraformを採用しました。
Terraformの設定
Terraformの設定と起動・破棄スクリプトは以下のようになっています。
main.tf
provider "aws" {
region = "ap-northeast-1"
assume_role {
role_arn = "${var.role_arn}"
session_name = "${var.session_name}"
}
}
resource "aws_spot_fleet_request" "your_spot_request_name" {
iam_fleet_role = "your_iam_fleet_role"
target_capacity = 1
terminate_instances_with_expiration = true # リクエスト終了時にインスタンスも終了する
wait_for_fulfillment = true #リクエストを待つ
fleet_type = "request" # リクエストの維持をしない
allocation_strategy = "priceCapacityOptimized" # 配分戦略の指定
launch_specification {
ami = "ami-1234" # 今回はDLAMIを使用
instance_type = "g4dn.xlarge" # 使いたいインスタンスタイプにする
key_name = "your_key_name"
vpc_security_group_ids = ["security_group"]
subnet_id = "your_subnet_id"
iam_instance_profile = "your_iam_instance_profile"
user_data = file("user_data.sh") # 起動時に実行したいuser_dataがある場合は指定
root_block_device {
volume_size = 35
volume_type = "gp3"
iops = 3000
throughput = 125
}
tags = {
Hoge = "hoge"
}
}
}
起動方法(run.sh)
terraform init
terraform validate
terraform apply -auto-approve \
-var "role_arn=${ROLE}" \
-var "session_name=${SESSION_NAME}"
破棄方法(destroy.sh)
terraform destroy -auto-approve \
-var "role_arn=${ROLE}" \
-var "session_name=${SESSION_NAME}"
躓いたポイント
AMIによっては要求ボリュームサイズが大きいことがあるので適宜変更が必要です。逆に使いたいAMIによってはこれより小さくしてもいいと思います。
リクエストタイプ(fleet_type)の設定のデフォルトはmaintainになっている(中断時自動補充)ため、使い捨てしたい場合はrequestに変更しておく必要があります。
配分戦略(allocation_strategy)の設定のデフォルトはlowestPriceになっている(最低価格のプールから確保するため中断率が高い)ため、可用性を高めたい場合は別の戦略を指定した方が良いと思います。スポットインスタンスの配分戦略についてはこちらに解説があります。
Terraformはtfstateファイルにリソース情報を保存しているため、こちらのファイルを削除するとterraform destroyができなくなります。例えば起動と停止を別のフローから行いたい場合などはtfstateファイルの保存をするなどの工夫が必要です。
構築した結果
構築したsandbox環境作成システムを使ってみたところ、
MLの環境構築がローカル上にできていないメンバーを含めたモブでもすんなりドライバー交代ができた
違う設定のsandbox環境が必要になったときもコード化されているので簡単に増やすことができた
という効果が出てきました。
今までML系の開発が詳しいメンバーに偏ってしまっていたため、環境構築が楽になったことは属人化解消に向けての大きな前進になりそうです。
まとめ
TerraformからAWS EC2インスタンスを起動するsandbox用のクラウド環境構築システムをご紹介させていただきました。
今回は前処理から学習・推論までを一つの環境で行う予定ですが、研究開発が進んできた場合ステップごとにインスタンスタイプを変えたくなることが想定されるため、インスタンス設定を外出しすると使いやすそうです。
また、連続起動時間によって自動でインスタンスを終了する処理を組み込むとより安全に高額インスタンスを扱えるかと思います。