terraformでGoのAPIを動かすECSを作ろうとした時、DBの接続で結構手こずった。
初回のterraform実行でRDS構築してさらにECR(コンテナのレジストリ)からdockerイメージをpullしてECS内にコンテナを立ち上げるんだけど、その時に以下の2点がうまくできずにしばらくハマった。
- どうやってRDSのエンドポイントとかDB名、ユーザ、パスワード情報渡そうか
- Migrationのタイミング
で、とりあえず作った内容を書いてみる
1のRDSの情報
terraformならECSのresouce定義内でRDSのエンドポイントやDB名を参照できる。ユーザ、パスワードはterraformの変数として定義して同じように渡せる。
以下タスク定義内に書いたコンテナの情報。dockerイメージはAPIエンドポイントを立ち上げるGoで書いたサーバ。
resource "aws_ecs_task_definition" "movie-backend" { family = "movie_backend" requires_compatibilities = ["FARGATE"] cpu = "256" memory = "512" network_mode = "awsvpc" execution_role_arn = aws_iam_role.ecs_task_execution_role.arn container_definitions = <<EOL [ { "name": "movie_backend", "image": "public.ecr.aws/e9z3g6v3/movie-info-backend:latest", "portMappings": [ { "containerPort": 8080, "hostPort": 8080 } ], "environment": [ { "name": "DB_HOST", "value": "${aws_db_instance.movie-backend.endpoint}" }, { "name": "DB_USER", "value": "${var.db_user}" }, { "name": "DB_PASSWORD", "value": "${var.db_pass}" }, { "name": "DB_NAME", "value": "${aws_db_instance.movie-backend.name}" }, { "name": "DATA_SOURCE", "value": "${var.db_user}:${var.db_pass}@tcp(${aws_db_instance.movie-backend.endpoint})/${aws_db_instance.movie-backend.name}?charset=utf8&parseTime=True&loc=Local" } ], "logConfiguration": { "logDriver": "awslogs", "options": { "awslogs-region": "ap-northeast-1", "awslogs-stream-prefix": "movie-backend", "awslogs-group": "/ecs/movie-backend" } } } ] EOL }
こんな感じでそのままGoのコードに渡せばMySQLにつながるように文字列作れるの便利だな。。
${var.db_user}:${var.db_pass}@tcp(${aws_db_instance.movie-backend.endpoint})/${aws_db_instance.movie-backend.name}?charset=utf8&parseTime=True&loc=Local
2のMigration
ここはとりあえずDB、Migration用のECSのタスク定義を作って手動で実行することにした。今のところ手動だけどここはAWSのCodeBuild使って自動化もできそう
作ったterraformのコード。大体上のサーバ実行用のタスク定義と同じなんだけど、commandオプションでイメージ内で最終的に実行されるコマンドをMigrationに上書きしている
resource "aws_ecs_task_definition" "movie-db-migration" { family = "movie_db_migration"
requires_compatibilities = ["FARGATE"]
cpu = "256" memory = "512"
network_mode = "awsvpc"
execution_role_arn = aws_iam_role.ecs_task_execution_role.arn
container_definitions = <<EOL [ { "name": "movie_db_migrate", "image": "public.ecr.aws/e9z3g6v3/movie-info-backend:latest", "command": ["sql-migrate", "up"], "environment": [ { "name": "DATA_SOURCE", "value": "${var.db_user}:${var.db_pass}@tcp(${aws_db_instance.movie-backend.endpoint})/${aws_db_instance.movie-backend.name}?charset=utf8&parseTime=True&loc=Local" } ], "logConfiguration": { "logDriver": "awslogs", "options": { "awslogs-region": "ap-northeast-1", "awslogs-stream-prefix": "movie-db-migration", "awslogs-group": "/ecs/movie-db-migration" } } } ] EOL }