ゼロから始める AWS Fargate 実践編
概要編に引き続き、 AWS Fargate 実践編になります。
実際に Terraform などのコードをサンプルのリポジトリにあげていて、 VPC の作成から ECS クラスタの作成、更にはモニタリングのための CloudWatch のリソースまで用意しているので実践と言うにふさわしいのではないかなと思います。 README に手順が書いてあるので試したい人は参考にしてください。
サンプルでは ECS クラスタ上で動かすアプリケーションとして、 Redash を選びました。理由は DB と Cache を使うこと、それから Web UI に限らず worker のプロセスもあるので、自前のアプリケーションを動かす際の参考として適していると思いました。実践編の記事、 6 月中に書くぞ とか言ってましたが、フラグ回収して 7 月になってしまいましたw では張り切って実践編に入りましょう。
最初に念のため、サンプルに関しての注意書きをしておきます。
- RDS, ElastiCache ともにマルチ AZ は無効にしている
- RDS, ElastiCache ともにパブリックサブネットに作成しており、踏み台サーバはなしで固定 IP で接続許可している
- PostgreSQL のデータベースもまとめて Terraform で作成している
- Fargate タスクのオートスケーリングは未設定
このあたりは 怠惰で Fargate 用のサンプルと割り切ってプロダクション用の設定を省略した形です。
また、 VPC 関連のリソースの細かい説明は割愛します。パブリックサブネットとプライベートサブネットがそれぞれ 3 つずつ作成されるようになっています。
実践編は以下の 3 ステップで説明します。
Terraform による ECS クラスタのセットアップ
S3 bucket の準備
まずは S3 bucket を 1 つ用意して terraform.tfstate
を管理します。チームなど複数人でリソースを操作する場合や、 機密情報を GitHub リポジトリに入れたくない場合に今では必須となっていますね。
aws --profile dev s3api create-bucket --bucket <BUCKET_NAME> --acl private --create-bucket-configuration LocationConstraint=ap-northeast-1
これだけ用意すればサンプルの Terraform コードを適用できます。
ECS クラスタの作成
さっそく Terraform を実行します。
cd ./terraform terraform apply
実行時に必要な variable が 3 つあるので、 terraform.tfvars
を用意するか実行時の引数 -var
を使用すると良いでしょう。もちろん実行後のプロンプトで入力しても良いです。
terraform.tfvars
の例:
cidr_office = "x.x.x.x/32" # 接続を許可する IP owner = "innossh" # Owner タグに設定する名前 s3_bucket_name = "my-bucket-name" # ALB のログを保存する S3 バケット名
作成される AWS 上のリソースは以下になります。
- ECS クラスタ
- VPC 関連
- RDS
- Redash 用の DB
- ElastiCache
- Redash 用の Redis
- ALB
- Redash の Web UI のエンドポイント用
- IAM role
- ECS 上のタスクに割り当てる用
- Security group
- ECS 上のタスクに割り当てる用など
- CloudWatch 関連
ちなみに ECS クラスタは名前を決めるだけで作成できます。
aws-fargate-example/ecs.tf at v0.0.1 · innossh/aws-fargate-example · GitHub
resource "aws_ecs_cluster" "fargate" { name = "${var.site_id}-fargate" tags = { Owner = "${var.owner}" } }
Terraform の適用は RDS と ElastiCache の作成があるので完了まで時間がかかります。完了すると RDS に接続できるようになります。
postgresql データベースの作成
今度は postgresql provider を使用したデータベースの作成を適用します。
同じディレクトリで同時に RDS 作成 と postgresql provider を適用しようとするとエラーとなるため、 -target
指定を頑張って切り抜けるかディレクトリを分けるかの二択になるわけですが、サンプルでは潔くディレクトリを分けています。
cd ./terraform/postgresql terraform apply
postgresql ディレクトリ用 terraform.tfvars
の例:
db_root_password = "XXXXXX" # RDS の root パスワード owner = "innossh" # Owner タグに設定する名前
ここで同時に Secrets Manager に Redash 用の DB ユーザのパスワードを保存しています。正確に言うと DB 接続の URL の形式で保存しているのですが、これは Fargate 上で Redash のコンテナを動かす際に環境変数としてそのまま渡せるように意図しています。ついでに Redis 接続の URL や REDASH_COOKIE_SECRET
なども保存しています。
aws-fargate-example/secretsmanager.tf at v0.0.1 · innossh/aws-fargate-example · GitHub
resource "aws_secretsmanager_secret" "fargate_redash" { count = "${length(local.secrets)}" name = "${lookup(local.secrets[count.index], "name")}" description = "${lookup(local.secrets[count.index], "description")}" tags = { Owner = "${var.owner}" } } resource "aws_secretsmanager_secret_version" "fargate_redash" { count = "${length(local.secrets)}" secret_id = "${aws_secretsmanager_secret.fargate_redash.*.id[count.index]}" secret_string = "${lookup(local.secrets[count.index], "secret_string")}" }
もし自前の Docker イメージを使用するために Docker プライベートレジストリを使用する場合は、公式ドキュメントのように JSON 形式で Secrets Manager に認証情報を保存します。それ以外の環境変数用の値であればプレーンテキストで単一の文字列を保存するようにしてください。
これで Terraform による AWS のリソースのセットアップは完了です。
ECS CLI によるサービスの実行
今度は ECS CLI を使用して Redash のコンテナをデプロイします。 Fargate の用語で言うと、 Redash の複数のタスク定義をもったサービスをクラスタにデプロイします。
概要編でも説明しましたが、 docker-compose.yml
と ecs-params.yml
を使用して ECS CLI のコマンドでサービスを実行できます。
docker-compose.yml
本筋とずれるので Docker Compose の詳しい説明は省略しますが、 2 年前に書いたベストプラクティスはこちら。
今回は公式の Redash の docker-compose.yml
をもとにしていますが、ログの設定は Fargate 用の特別なものになります。
aws-fargate-example/docker-compose.yml at v0.0.1 · innossh/aws-fargate-example · GitHub
server: image: redash/redash:7.0.0.b18042 ... logging: driver: awslogs options: awslogs-group: /ecs/dev-fargate/redash awslogs-region: ap-northeast-1 awslogs-stream-prefix: ecs
上記のように、 awslogs ログドライバーを使用しています。ロググループは Terraform で作成したものを指定していますね。
ecs-params.yml
一方 ecs-params.yml
は初見の人が多いと思います。
aws-fargate-example/ecs-params.sample.yml at v0.0.1 · innossh/aws-fargate-example · GitHub
version: 1 task_definition: ecs_network_mode: awsvpc task_execution_role: "arn:aws:iam::FIXME:role/dev-fargate-redash" task_size: cpu_limit: 512 mem_limit: 2048 services: server: essential: true secrets: - value_from: "arn:aws:secretsmanager:ap-northeast-1:FIXME:secret:dev-fargate/redash-db-url-FIXME" name: REDASH_DATABASE_URL - value_from: "arn:aws:secretsmanager:ap-northeast-1:FIXME:secret:dev-fargate/redash-redis-url-FIXME" name: REDASH_REDIS_URL - value_from: "arn:aws:secretsmanager:ap-northeast-1:FIXME:secret:dev-fargate/redash-cookie-secret-FIXME" name: REDASH_COOKIE_SECRET - value_from: "arn:aws:secretsmanager:ap-northeast-1:FIXME:secret:dev-fargate/redash-secret-key-FIXME" name: REDASH_SECRET_KEY ... run_params: network_configuration: awsvpc_configuration: subnets: - "subnet-FIXME" - "subnet-FIXME" - "subnet-FIXME" security_groups: - "sg-FIXME" assign_public_ip: DISABLED
FIXME
は正しい ARN で置換すべきところです。それぞれ設定値に関しては以下になります。
task_execution_role
- タスク実行用の IAM role の指定
essential
true
の場合、そのコンテナが停止した時に他のコンテナもあわせて停止する。常駐しないコンテナはfalse
にしておく
secrets
- Secrets Manager の ARN を指定し、環境変数の設定が可能
awsvpc_configuration
- タスクが使用するサブネット、セキュリティグループの指定。パブリック IP をアサインすることも可能
中途半端な説明なので、詳しくは公式ドキュメントを参照するのがいいでしょうね。
サービスの実行
ではようやくサービスの実行ですが、残念ながら ecs-params.yml
が未対応で設定できないパラメータもあるため、実行時にオプションとして指定しているものもあります。コマンドは以下のようになります。
ecs-cli compose --aws-profile dev --cluster dev-fargate --project-name redash service up --launch-type FARGATE --target-group-arn <TARGET_GROUP_ARN> --container-name server --container-port 5000 --tags Owner=<OWNER>
一つポイントとして、 --target-group-arn
で Terraform で作成した ALB のターゲットグループを指定しているのですが、そのターゲットグループはターゲットタイプを IP としており、ターゲットのコンテナは Fargate が自動的に登録してくれるようになっています。
aws-fargate-example/alb.tf at v0.0.1 · innossh/aws-fargate-example · GitHub
resource "aws_lb_target_group" "fargate_redash_http" { name = "fargate-redash-http" port = 5000 protocol = "HTTP" vpc_id = "${aws_vpc.main.id}" deregistration_delay = 300 slow_start = 30 target_type = "ip" health_check { interval = 30 path = "/login" protocol = "HTTP" healthy_threshold = 3 unhealthy_threshold = 3 matcher = "200,302" } }
ECS CLI の実行が成功すると、ブラウザで ALB のエンドポイントにアクセスすることで Redash の Web UI が見れるようになります。
動作確認とモニタリング
Redash の Web UI が見れるということは正常に動作していそうですが、マネージメントコンソールでも確認してみましょう。 ALB の状態は下のようになっています。ターゲットは IP になっていますね。
こちらは ECS のタスクの状態になります。
更に詳細をみると、下のキャプチャのように 3 つのコンテナが動作しています。うち 1 つは DB のマイグレーション実行用なのですでに実行を終えています。前述の essential
が false
のコンテナなので、タスク自体には問題がありません。
ここからはモニタリングについて紹介します。まずは何と言ってもコンテナのログですね。同じくマネージメントコンソールのタスクの詳細からそのままログの確認ができます。もちろん AWS CLI で CloudWatch のログを確認することもできますが。
続いてメトリクスについてです。何も設定しなくても Fargate のタスクの CPU とメモリについては CloudWatch で確認できます。
そして概要編でも取り上げた CloudWatch Metric Filter からのカスタムメトリクスも取得できています。エラーログも警告ログも出ていないので、数値が 0 の地味なグラフになっていますがw
以上で、前回から続いた ”ゼロから始める AWS Fargate” を終わります。 Fargate でシームレスな開発と運用コストを抑えつつ、プロダクション環境にも対応した Web サービスの公開ができることがよくわかりました。
- 作者: 山田明憲
- 出版社/メーカー: 技術評論社
- 発売日: 2018/08/25
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (1件) を見る