TerraformでLambda関数とECRリポジトリを同時に作成したい
はじめに
TerraformでImageタイプのLambda関数を作成したい時困りますよね。ECRリポジトリを先に作ってイメージをPushしておかないとエラーで作れなくなってしまいます。
│ Error: creating Lambda Function (test-function): operation error Lambda: CreateFunction, https response error StatusCode: 400, RequestID: hogehoge, InvalidParameterValueException: Source image fugafuga:latest does not exist. Provide a valid source image.
│
│ with module.lambda.aws_lambda_function.this[0],
│ on .terraform/modules/lambda/main.tf line 24, in resource "aws_lambda_function" "this":
│ 24: resource "aws_lambda_function" "this" {
そこで今日ご紹介するのがDocker Providerです。
これを使うと、
- 最新のnginxイメージをPullしてくる
- PullしたイメージにECR用のタグをつける
- ECRにイメージをPush
ということが一回のterraform applyで出来るので、同時にlambda関数も作成出来ます。
サンプルコード
########################################################
# Data Import
########################################################
data "aws_caller_identity" "current" {}
########################################################
# Lambda
########################################################
module "lambda" {
source = "terraform-aws-modules/lambda/aws"
function_name = "test-function"
create_package = false
image_uri = "${aws_ecr_repository.lambda.repository_url}:latest"
package_type = "Image"
depends_on = [aws_ecr_repository.lambda]
}
########################################################
# ECR
########################################################
resource "aws_ecr_repository" "lambda" {
name = "test-function-repo"
encryption_configuration {
encryption_type = "AES256"
}
image_scanning_configuration {
scan_on_push = true
}
image_tag_mutability = "IMMUTABLE"
}
resource "docker_image" "nginx" {
name = "nginx:latest"
keep_locally = false
}
resource "docker_tag" "nginx" {
source_image = docker_image.nginx.name
target_image = "${aws_ecr_repository.lambda.repository_url}:latest"
}
resource "docker_registry_image" "nginx" {
name = docker_tag.nginx.target_image
keep_remotely = true
}
data "aws_ecr_authorization_token" "token" {
}
provider "docker" {
registry_auth {
address = "${data.aws_caller_identity.current.account_id}.dkr.ecr.ap-northeast-1.amazonaws.com"
username = data.aws_ecr_authorization_token.token.user_name
password = data.aws_ecr_authorization_token.token.password
}
}
解説
DataImport
操作対象のAWSアカウントIDを特定するために使います。(${data.aws_caller_identity.current.account_id}の部分)
Lambda関数
package_type = "Image"を指定します。(パブリックモジュールを使ってますが普通にresourceで指定してもおk)
ECR
ここがミソ
aws_ecr_repositoryは普通に指定。
docker_imageを定義するとDockerイメージをPullすることが出来ます。今回はnginxの最新版を指定。
docker_tagでPullしてきたイメージにタグ付けすることが出来ます。docker tagコマンドと同じ。
そしてdocker_registry_image.nameに事後のタグ名(ECRにプッシュするタグ名)を指定することでECRにPushを行えます。
ECRの認証はaws_ecr_authorization_tokenやprovider "docker"で指定したregistry_authを使って一時認証情報を使用して行われるようです。
Apply complete! Resources: 8 added, 0 changed, 0 destroyed.
これでECRの作成とLambda関数の作成を一撃で行うことが出来ました。
後処理
なお作成し終わったらもうDocker Providerのリソースは不要なので、余計な定義は消してしまいましょう。
以下をtfファイルから削除してterraform applyコマンドを実行すれば完了です。
resource "docker_image" "nginx" {
name = "nginx:latest"
keep_locally = false
}
resource "docker_tag" "nginx" {
source_image = docker_image.nginx.name
target_image = "${aws_ecr_repository.lambda.repository_url}:latest"
}
resource "docker_registry_image" "nginx" {
name = docker_tag.nginx.target_image
keep_remotely = true
}
なおECR認証周りは上記定義の削除後に削除してください。同時に削除したいところですがこいつがないとエラーになります。
### 以下はresource3点セット削除後に削除する(terraform applyは不要)
data "aws_ecr_authorization_token" "token" {
}
provider "docker" {
registry_auth {
address = "${data.aws_caller_identity.current.account_id}.dkr.ecr.ap-northeast-1.amazonaws.com"
username = data.aws_ecr_authorization_token.token.user_name
password = data.aws_ecr_authorization_token.token.password
}
}
参考にしたサイト
lambda関数のコンテナイメージサポートをterraformで構築する
【Terraform】Docker Providerを利用してローカルでインフラ環境を構築してみる
Discussion