ECR
コンテナイメージの保管場所。push する主体の AWS 認証情報が必要になる。
Lambda 本体を作る前に、コンテナイメージの置き場、実行時の権限、RDS への通信経路の役割を分けて準備する。
slack-metrics-lambda-stg の ECR と、そこへ push した Docker イメージがある。cp-slack-metrics-lambda-stg の IAM ロールと Security Group がある。教材の順序は ECR → イメージ push → IAM ロール → Security Group → 次の Lesson で Lambda 作成。ここで関数を先に作らないことに意味がある。

コンテナイメージの保管場所。push する主体の AWS 認証情報が必要になる。
Lambda が実行中に AWS API を呼ぶための権限。開発端末の権限ではない。
VPC 内の通信を許可する境界。RDS に届く送信元を Lambda 用 SG として表す。
ECR リポジトリ名は slack-metrics-lambda-stg。Terraform の内部識別子 ecr_slack_metrics_lambda と、AWS コンソールに表示される名前は役割が違う。前者はコード上の参照名、後者は AWS リソース名である。
local → stg:教材では backend ディレクトリを起点に実行する。
cd services/slack-metrics-lambda
ENV=stg make release-image
このコマンドで ECR へ push するのは、ローカルの Docker であり、その時点で有効な AWS 認証情報を使う。Lambda 実行ロールを作っても push 権限にはならない。push には呼び出し元に ECR の認証・アップロード権限が必要で、実行ロールは Lambda サービスの VPC 準備と、起動したアプリケーションの AWS API 操作に使われる。
aws.mk の既定アカウントが自分のアカウントと異なる問題もあった。アカウント設定はその後修正したが、OrbStack を使う場合も Docker を動かす本体が起動済みか確認する。次の Lambda は x86_64 を想定するため、イメージは linux/amd64 で build する。NoCredentials:AWS CLI が認証情報を見つけていない。AWS_PROFILE とログイン状態を確認する。AWS_ACCOUNT_ID はイメージの宛先、AWS_PROFILE は操作する人の認証設定。片方の指定だけでは両方は揃わない。docker.sock に接続できない:docker context show と docker info で接続先と起動状態を確認する。OrbStack が動いていれば、Colima を追加起動する必要はない。自分の環境を明示する実行例。アカウントIDは実行前に置き換える。
AWS_PROFILE=cp-terraform-stg \
AWS_ACCOUNT_ID='<自分のAWSアカウントID>' \
ENV=stg make release-image
ロール名は cp-slack-metrics-lambda-stg。既存の ECS 用 cp-slack-metrics-backend-stg は使い回さない。誰がロールを使えるかを決める信頼ポリシーで lambda.amazonaws.com を指定し、必要なアクセスも ECS タスクとは異なるからである。
| 必要なこと | 権限の意味 | 今回の実装例 |
|---|---|---|
| Parameter Store を読む | 起動時に共有設定を取得する | AmazonSSMReadOnlyAccess |
| VPC 内で起動する | Lambda サービスが ENI を管理するための API 操作を許可する | AWSLambdaVPCAccessExecutionRole |
| ログを出す | CloudWatch Logs へ実行ログを送る | CloudWatchFullAccessV2 |
| SQS を扱う | 後続の用途も見越したキュー操作 | 既存の sqs_read_write ポリシー |
ENI は Lambda が VPC へ接続するために管理する仮想ネットワークカードであり、呼び出しごとに「専用 ENI が 1 枚」作られるものではない。ロールはその管理 API を許可し、Security Group は実際のネットワーク通信を制御する。両者は代替関係ではない。
AmazonSSMManagedInstanceCore は EC2 などを Systems Manager の管理対象にするためのポリシーであり、Lambda が Parameter Store を狭く読む用途には適さない。今回採用した CloudWatchFullAccessV2 は VPC 実行ロールに含まれるログ系権限と重なる範囲がある。実務では必要な操作と対象に権限を絞る。教材では SES との連携を省くため、SES の送信権限は今回付けない。Lambda 用 Security Group cp-slack-metrics-lambda-stg を作り、DB のインバウンドに TCP 5432、送信元としてその SG を追加する。これは「Lambda の SG を DB に付ける」設定ではない。このルールが、この SG を持つネットワークインターフェースからの PostgreSQL 接続を許可するという意味であり、既存の踏み台サーバーなどからの接続許可は維持される。

| 境界 | 決めること | この構成での指定 |
|---|---|---|
| Lambda 側 SG | 送信元から外へ出る通信 | Lambda の VPC 設定で SG を選ぶ(Lesson 06) |
| DB 側 SG | 受信側が誰から PostgreSQL を受けるか | 送信元 slack_metrics_lambda、TCP 5432 |
| IAM | AWS API の操作可否 | ENI 作成・SSM 読み取り・ログ送信など |
Lambda 側では外向きの通信、DB 側では入ってくる通信の両方を許可する。Lambda 側の送信許可だけでは DB 側の受信許可を代わりに満たせない。SG が通っても、ネットワーク経路と PostgreSQL のユーザー認証は別に必要になる。
Security Group は関数名そのものを識別するものではない。複数の Lambda が同じ SG を使えば、DB から見える許可単位もその SG になる。関数単位のネットワーク境界が必要になった時点で SG を分ける。
IAM / Security Group / ECR の各モジュールがロール ARN、Security Group ID、リポジトリ URL を出力し、stg/aws.tf の親モジュールが将来の Lambda module に渡す。これらの output は AWS リソースでもコスト発生要因でもなく、モジュール間で値を受け渡す名前付きの出口である。まだ Lambda module が無いことは欠落ではなく、Lesson 05 が周辺資源だけを作る段階だからである。

IAM の ARN は iam_role/outputs.tf、SG の ID は security_group/outputs.tf に書く。別のモジュールにあるリソースを、lambda/outputs.tf から直接参照することはできない。
# modules/aws/iam_role/outputs.tf
output "role_arn_cp_slack_metrics_lambda" {
value = aws_iam_role.cp_slack_metrics_lambda.arn
}
# modules/aws/security_group/outputs.tf
output "id_slack_metrics_lambda" {
value = aws_security_group.slack_metrics_lambda.id
}
親の stg/aws.tf からは module.iam_role.role_arn_cp_slack_metrics_lambda のように参照できる。次の課題で Lambda を Terraform 化する際、受け取る側の変数につなぐ。

AWS 上の名前を変えなくても、Terraform 内部の module 名だけ変えると、state との対応が外れる。state mv は AWS の実体を作り直さず、その対応先の住所を移す操作である。2026-09-06 時点では、旧 slack_metrics_lambda を ecr_slack_metrics_lambda へ state mv した後、対象を絞った plan は No changes だった。これは当時の状態移行の記録であり、現在の環境を保証するものではない。terraform state mv の公式ドキュメントも参照する。
通常の terraform apply は、同じ親モジュール / state にある差分を一度に適用するので、すべてを再作成する操作ではない。-target は依存関係を含む限定的な復旧・調査向けであり、日常の apply の代わりにはしない。詳しくは HashiCorp の resource targeting ガイドを参照する。
DB の for_each に ECS 用 SG も含まれていたため、Lambda だけのつもりでも、2026-09-06 の復旧作業では 11 件追加の計画になった。Recommended alternative:今回は削除済みの ECS 系を戻さないため、Lambda から DB への受信ルールを独立したリソースに分ける案を出した。通常の講座環境では既存 SG が揃っており、従来の map への追加で進められる。
同日の全体 plan には 109 件追加と表示されたが、評価エラーで完走していない。削除済みの AWS 環境に対して撤去前のコードを使っていたため、大量の復元候補が出た。これは Lambda を追加するたびに起きる通常動作ではない。ALB を無効にしても ECS / CloudFront まで自動で対象外にはならない。同じ定義から複数のリソースを作る count と for_each では、作成数や各リソースを識別するキーを plan 時点で決められる必要がある。作成後に決まる ARN などを、その判断に使わない。import の成功も、空の状態からの再構築成功を保証しない。
slack-metrics-lambda-stg に対象のイメージが存在する。cp-slack-metrics-lambda-stg が Lambda を信頼し、必要なポリシーを持つ。次の Lesson 06 は、これらを選んで API 用 Lambda を手動作成し、テストタブで API Gateway 形式のイベントを実行する段階である。アプリケーションは ENV により共有の slack-metrics-${ENV} Parameter Store を読み、MODE は API / batch / SQS で直接指定して起動処理を選ぶ。
VPC 内 Lambda と ENI の詳細は AWS Lambda の VPC 設定ドキュメント、Security Group のルールは AWS の Security Group ルールドキュメントで確認できる。