kakakakakku blog

Weekly Tech Blog: Keep Learning!

Bref で SSM パラメータストアの値を Lambda 関数の環境変数に設定する

Bref には AWS Systems Manager Parameter Store に登録したパラメータを AWS Lambda 関数の環境変数に設定する機能がある.環境変数の値を serverless.yml に直接記述したくないときに使える.たとえばシークレットなど❗️

bref.sh

at deployment time(デプロイ時)と at runtime(実行時)

パラメータを環境変数に登録するタイミングとして,大きく「デプロイ時」「実行時」がある.Bref のドキュメントでは以下のように書いてある.

  • at deployment time (simplest)
  • at runtime (more secure)

「デプロイ時」serverless deploy コマンドを実行して AWS Lambda 関数をデプロイするときに AWS Systems Manager Parameter Store に登録したパラメータを環境変数に登録する.よって,AWS Lambda 関数のコンソールを見ると環境変数の値が見える.

「実行時」は AWS Lambda 関数の初回実行時(コールドスタート)に動的に AWS Systems Manager Parameter Store に登録したパラメータを環境変数に設定する.AWS Lambda 関数のコンソールには bref-ssm:xxx というプレフィックス付きの文字列を登録することになる.

さっそく試してみる \( 'ω')/

AWS Systems Manager Parameter Store にパラメータを登録する

まずは検証用のパラメータを「4種類」AWS Systems Manager Parameter Store に登録しておく.

$ aws ssm put-parameter --name '/sandbox-bref-variables/string-deploy-time' --type String --value 'string-deploy-time'
$ aws ssm put-parameter --name '/sandbox-bref-variables/string-runtime' --type String --value 'string-runtime'
$ aws ssm put-parameter --name '/sandbox-bref-variables/secure-deploy-time' --type SecureString --value 'secure-deploy-time'
$ aws ssm put-parameter --name '/sandbox-bref-variables/secure-runtime' --type SecureString --value 'secure-runtime'

👾 composer.json

プロジェクトをセットアップするために composer.json を準備する.

{
    "require": {
        "bref/bref": "^3.0",
        "bref/secrets-loader": "^1.0"
    }
}

今回は bref/bref と AWS Systems Manager Parameter Store に登録したパラメータを取得するために使う bref/secrets-loader をインストールする.

github.com

ちなみに Bref は2026年2月末にリリースされた最新の Bref 3.0 を使う.

bref.sh

最後に composer install を実行しておけば OK👌

$ composer install

👾 serverless.yml

次に Serverless Framework の serverless.yml を準備する.ポイントは環境変数を設定する environment「デプロイ時」の場合は ${ssm:/xxx} というフォーマットで指定して,「実行時」の場合は bref-ssm:/xxx というフォーマットで指定する.

さらに「実行時」の場合は AWS Lambda 関数から AWS Systems Manager Parameter Store にアクセスする権限も必要になるため IAM Role にポリシーを追加しておく⚠️

service: sandbox-bref-variables

provider:
    name: aws
    region: ap-northeast-1
    environment:
        SSM_STRING_DEPLOY_TIME: ${ssm:/sandbox-bref-variables/string-deploy-time}
        SSM_STRING_RUNTIME: bref-ssm:/sandbox-bref-variables/string-runtime
        SSM_SECURE_DEPLOY_TIME: ${ssm:/sandbox-bref-variables/secure-deploy-time}
        SSM_SECURE_RUNTIME: bref-ssm:/sandbox-bref-variables/secure-runtime
    iam:
        role:
            statements:
                - Effect: Allow
                  Action: ssm:GetParameters
                  Resource:
                      - "arn:aws:ssm:${aws:region}:${aws:accountId}:parameter/sandbox-bref-variables/string-runtime"
                      - "arn:aws:ssm:${aws:region}:${aws:accountId}:parameter/sandbox-bref-variables/secure-runtime"

plugins:
    - ./vendor/bref/bref

functions:
    sandbox:
        name: sandbox-bref-variables
        handler: index.php
        runtime: php-84

👾 index.php

最後に AWS Lambda 関数で実行する index.php を実装する.実装自体は超シンプルで4種類の環境変数をそのまま返す.本来は環境変数の値を直接返す意味はなく,あくまで動作確認のためのサンプルコードということで✋️

<?php

require __DIR__ . '/vendor/autoload.php';

return function ($event) {
    return [
        'string_deploy_time' => getenv('SSM_STRING_DEPLOY_TIME'),
        'string_runtime' => getenv('SSM_STRING_RUNTIME'),
        'secure_deploy_time' => getenv('SSM_SECURE_DEPLOY_TIME'),
        'secure_runtime' => getenv('SSM_SECURE_RUNTIME'),
    ];
};

デプロイする

そして serverless deploy コマンドでデプロイする🚀

$ serverless deploy
Deploying sandbox-bref-variables to stage dev (ap-northeast-1)

✔ Service deployed to stack sandbox-bref-variables-dev (80s)

functions:
  sandbox: sandbox-bref-variables (626 kB)

Want a better experience than the AWS console? Try out https://bref.sh/cloud

AWS Lambda 関数を実行する

期待通りに環境変数を取得できた👌

$ serverless invoke --function sandbox
{
    "string_deploy_time": "hello-deploy-time",
    "string_runtime": "hello-runtime",
    "secure_deploy_time": "hello-secure-deploy-time",
    "secure_runtime": "hello-secure-runtime"
}

環境変数を確認する

マネジメントコンソールで AWS Lambda 関数の環境変数を確認すると以下のようになっていた👌

「デプロイ時」だと環境変数の値が直接設定されていて,「実行時」だと bref-ssm:/xxx というフォーマットになっていた.

まとめ

Bref で AWS Systems Manager Parameter Store に登録したパラメータを AWS Lambda 関数の環境変数に設定する機能(デプロイ時と実行時の2種類)を試してみた❗️

ドキュメントにも書いてある通り,それぞれにメリデメがある.「デプロイ時」はシンプルだけど AWS Lambda 関数のコンソールで環境変数の値が見えてしまう.「実行時」はより安全に使えるけど AWS Lambda 関数の初回実行時(コールドスタート)にパラメータを取得するため API 実行のオーバーヘッドが追加されてしまう.

もっと Bref を試していこう💪

Terraform の AWS Cloud Control Provider (awscc) で CloudWatch Alarm「ミュートルール」を設定しよう

2026年2月に Amazon CloudWatch Alarm の「ミュートルール (Mute Rules)」 という新機能がリリースされた❗️

計画メンテナンスのときなど Amazon CloudWatch Alarm のアクションを一時的に止めたい場合に今までだと「無効化」を設定する必要があった.もしくは計画メンテナンス中に大量にアラートが鳴ってしまって「すいません!今作業中だから無視してください🫡」みたいなアナウンスをしてしまっているチームもあると思う.「ミュートルール」を使えば柔軟にアラートを抑制できる.

aws.amazon.com

現時点では Terraform AWS Provider で未サポート

2026年3月3日時点では Terraform AWS Provider ではサポートされていなかった.issue は出ていてサポートされそうな未来はある😀

github.com

AWS Cloud Control Provider (awscc) ではサポートされている

AWS Cloud Control Provider (awscc) では2026年2月18日にリリースされた v1.72.0 からサポートされている.リソースとしては awscc_cloudwatch_alarm_mute_rule を使えば OK👌

github.com

さっそく試す \( 'ω')/

今回は「1回限り」を試す.他には「定期的なスケジュール」という設定もある🕐️

Amazon CloudWatch Alarm をデプロイする

まずは検証用の Amazon CloudWatch Alarm と Amazon SNS トピックをデプロイする.Amazon CloudWatch Alarm のメトリクスは適当に設定しておく😀

resource "aws_sns_topic" "alarms" {
  name = "sandbox-alarms"
}

resource "aws_sns_topic_subscription" "mail" {
  topic_arn = aws_sns_topic.alarms.arn
  protocol  = "email"
  endpoint  = "y.yoshida22@gmail.com"
}

resource "aws_cloudwatch_metric_alarm" "sandbox" {
  alarm_name          = "sandbox-for-mute"
  comparison_operator = "GreaterThanThreshold"
  evaluation_periods  = 1
  namespace           = "Sandbox"
  metric_name         = "DummyMetric"
  period              = 300
  statistic           = "Sum"
  threshold           = 1
  treat_missing_data  = "notBreaching"
  alarm_actions       = [aws_sns_topic.alarms.arn]
  ok_actions          = [aws_sns_topic.alarms.arn]
}

Amazon CloudWatch Alarm を発火させる

デプロイした Amazon CloudWatch Alarm の動作確認をするために aws cloudwatch set-alarm-state コマンドを使って一時的に ALARM に変更してアラートを発火する🔥

docs.aws.amazon.com

$ aws cloudwatch set-alarm-state \
  --alarm-name sandbox-for-mute \
  --state-value ALARM \
  --state-reason 'Testing alarm action without mute'

すると ALARM: "sandbox-for-mute" in Asia Pacific (Tokyo) というメールが届いた📩

AWS Cloud Control Provider (awscc) でミュートルールをデプロイする

AWS Cloud Control Provider (awscc) の awscc_cloudwatch_alarm_mute_rule リソースを使ってミュートルールをデプロイする.schedule で開始時刻と期間を指定できる.今回は検証として 12:15 - 12:30 の時間帯でアラートを抑制する🕐️

resource "awscc_cloudwatch_alarm_mute_rule" "maintenance" {
  name        = "maintenance"
  description = "Maintenance schedule for mute"

  rule = {
    schedule = {
      expression = "at(2026-03-03T12:15)"
      duration   = "PT15M"
      timezone   = "Asia/Tokyo"
    }
  }

  mute_targets = {
    alarm_names = [aws_cloudwatch_metric_alarm.sandbox.alarm_name]
  }
}

期待通りにミュートルールをデプロイできた👌

もう一度 Amazon CloudWatch Alarm を発火させる

今度は設定した時間帯でアラートを発火する🔥

$ aws cloudwatch set-alarm-state \
  --alarm-name sandbox-for-mute \
  --state-value ALARM \
  --state-reason 'Testing alarm action with mute'

すると今度はメールは届かず,マネジメントコンソールでも「アラーム状態」「ミュート時間帯」が重なるようになっていた.

ちなみに「アクション履歴」を見たら以下のようなメッセージが出ていた💡

Successfully muted the alarm action arn:aws:sns:ap-northeast-1:000000000000:sandbox-alarms with the one-time alarm mute arn:aws:cloudwatch:ap-northeast-1:000000000000:alarm-mute-rule:maintenance.

まとめ

マネジメントコンソールのメニューにある「クイックミュート」を使えばワンクリックで一時的なミュートルールを追加できて便利だけど,計画メンテナンスや周期性のあるイベントの場合は Terraform などでミュートルールを管理したくなると思う.現状では AWS Cloud Control Provider (awscc) でサポートされていて,Terraform AWS Provider はもう少し待ちという感じ❗️

X ポスト

関連記事

kakakakakku.hatenablog.com

kakakakakku.hatenablog.com

Terraform で moved ブロックを使わなくても count を削除できる

Terraform で環境ごとにリソースの有無を制御する場合や段階的にリソースを有効化するような場合に count を三項演算子のように使って制御できる.

developer.hashicorp.com

しかし count を使うと aws_sqs_queue.sandbox[0] のようにリソース id にインデックスが付いてしまう.最終的に count を使った制御が不要になって常にリソースをデプロイする場合は moved ブロックが必要になるけど,リソース id の変更が面倒になって count をそのまま残しているようなコードも見たことがある.

developer.hashicorp.com

最近 Refactor modules というドキュメントを読んでいたら count を削除する場合は「Terraform 側で自動的に moved を提案してくれる」と書いてあった.これは知らなくて今までずっと moved を実装していた❗️もちろん歴史的な経緯も記録できるので明示的に moved を実装する方が推奨ではあると書いてある👌

When you add count to an existing resource that didn't previously have the argument, Terraform automatically proposes moving the original object to instance 0 unless you write a moved block that explicitly mentions that resource. However, we recommend writing out the corresponding moved block explicitly to make the change clearer to future readers of the module.

developer.hashicorp.com

実際に試してみる \( 'ω')/

1. count を使って Amazon SQS キューをデプロイする

まずは create_queue という変数名と count を使って Amazon SQS キューをデプロイする.

variable "create_queue" {
  type    = bool
  default = true
}

resource "aws_sqs_queue" "sandbox" {
  count = var.create_queue ? 1 : 0

  name                      = "sandbox-queue"
  receive_wait_time_seconds = 20
}

terraform plan を実行するとリソース id が aws_sqs_queue.sandbox[0] になっていてインデックスが付いている👀

$ terraform plan

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_sqs_queue.sandbox[0] will be created
  + resource "aws_sqs_queue" "sandbox" {
      + arn                               = (known after apply)
      + content_based_deduplication       = false
      + deduplication_scope               = (known after apply)
      + delay_seconds                     = 0
      + fifo_queue                        = false
      + fifo_throughput_limit             = (known after apply)
      + id                                = (known after apply)
      + kms_data_key_reuse_period_seconds = (known after apply)
      + max_message_size                  = 262144
      + message_retention_seconds         = 345600
      + name                              = "sandbox-queue"
      + name_prefix                       = (known after apply)
      + policy                            = (known after apply)
      + receive_wait_time_seconds         = 20
      + redrive_allow_policy              = (known after apply)
      + redrive_policy                    = (known after apply)
      + region                            = "ap-northeast-1"
      + sqs_managed_sse_enabled           = (known after apply)
      + tags_all                          = (known after apply)
      + url                               = (known after apply)
      + visibility_timeout_seconds        = 30
    }

Plan: 1 to add, 0 to change, 0 to destroy.

そして terraform apply を実行してからステートを確認すると aws_sqs_queue.sandbox[0] として登録されていた.

$ terraform state list
aws_sqs_queue.sandbox[0]

2. moved ブロックを使って count を削除する

もし count が不要になったら moved ブロックを実装すればインデックスなしのリソース id に移行できる.

resource "aws_sqs_queue" "sandbox" {
  name                      = "sandbox-queue"
  receive_wait_time_seconds = 20
}

moved {
  from = aws_sqs_queue.sandbox[0]
  to   = aws_sqs_queue.sandbox
}

terraform plan を実行するとリソースへの影響はなくステートを更新できることがわかる👌

$ terraform plan

Terraform will perform the following actions:

  # aws_sqs_queue.sandbox[0] has moved to aws_sqs_queue.sandbox
    resource "aws_sqs_queue" "sandbox" {
        id                                = "https://sqs.ap-northeast-1.amazonaws.com/354924239642/sandbox-queue"
        name                              = "sandbox-queue"
        tags                              = {}
        # (20 unchanged attributes hidden)
    }

Plan: 0 to add, 0 to change, 0 to destroy.

3. moved ブロックを使わずに count を削除する

最後は moved ブロックを実装せずに count を削除してみる.

resource "aws_sqs_queue" "sandbox" {
  name                      = "sandbox-queue"
  receive_wait_time_seconds = 20
}

terraform plan を実行すると moved ブロックがなくても aws_sqs_queue.sandbox[0] has moved to aws_sqs_queue.sandbox という同じ結果になっていた❗️

$ terraform plan

Terraform will perform the following actions:

  # aws_sqs_queue.sandbox[0] has moved to aws_sqs_queue.sandbox
    resource "aws_sqs_queue" "sandbox" {
        id                                = "https://sqs.ap-northeast-1.amazonaws.com/354924239642/sandbox-queue"
        name                              = "sandbox-queue"
        tags                              = {}
        # (20 unchanged attributes hidden)
    }

Plan: 0 to add, 0 to change, 0 to destroy.

そして terraform apply を実行してからステートを確認すると aws_sqs_queue.sandbox に変更されていた.

$ terraform state list
aws_sqs_queue.sandbox

まとめ

Terraform で count を削除する場合は「自動的に moved を提案してくれる」ことは今まで知らなくて試してみた❗️明示的に moved を実装する方が推奨ではあると書いてあるけど,実装しなくても OK というのは覚えておこうと思う👌

Lambda Managed Instances に入門できるパターン「AWS Lambda Hello World on AWS Lambda Managed Instances (Terraform)」

2025年11月にリリースされた「AWS Lambda Managed Instances」を使うと Amazon EC2 上で AWS Lambda 関数を実行できる.AWS Lambda の良さ(お手軽さ)を残しつつ,Amazon EC2 で実行することによってコールドスタートを解消できたり,GPU インスタンスを選択できたり,柔軟さのある選択肢になる.what's new には AWS Graviton4 などの最新世代のプロセッサや高帯域幅ネットワーキングオプションを利用できます。 とも書かれている👌

aws.amazon.com

docs.aws.amazon.com

最近 AWS Serverless Patterns Collection に Terraform 前提で AWS Lambda Managed Instances に入門できるパターン「AWS Lambda Hello World on AWS Lambda Managed Instances (Terraform)」が追加された.さっそく試してみた❗️

github.com

デプロイ

README に書いてある手順通りで問題なくデプロイできる👌

しかし 36 to add になっている通り,想像以上にリソース数が多かった.Amazon EC2 を起動するために VPC が必要で,さらに 3 AZ 構成で NAT Gateway も AZ ごとにデプロイする構成になっていた.あくまで個人的には AWS Lambda Managed Instances に入門するためのパターンとしてはガッツリ構成で重いな〜とは思った.試した後に消し忘れないように🗑️

$ terraform init

$ terraform plan
(中略)
Plan: 36 to add, 0 to change, 0 to destroy.

$ terraform apply

動作確認

さっそく AWS Lambda Managed Instances を試す.まずは README に書いてある aws lambda invoke コマンドで AWS Lambda 関数を実行する.

$ export AWS_REGION=us-east-1

$ aws lambda invoke \
  --function-name hello-world-managed-instances-tf:live \
  --payload file://events/hello-world.json \
  --cli-binary-format raw-in-base64-out \
  response.json
{
    "StatusCode": 200,
    "ExecutedVersion": "1"
}

すると Hello AWS Lambda on Lambda Managed Instances というレスポンスが返ってきた.AWS Lambda 関数の実装はイベントに指定したメッセージに Hello を付与してオウム返しをする簡単なものになっている👏

$ cat response.json | jq .
{
  "response": "Hello AWS Lambda on Lambda Managed Instances"
}

今度はイベントを hello-world.json ファイルから渡すのではなく標準入力から渡して AWS Lambda 関数を実行する.

$ echo '{"name":"Lambda Managed Instances"}' | aws lambda invoke \
  --function-name hello-world-managed-instances-tf:live \
  --payload file:///dev/stdin \
  --cli-binary-format raw-in-base64-out \
  custom-response.json
{
    "StatusCode": 200,
    "ExecutedVersion": "1"
}

するとまた同じようにイベントに指定したメッセージに Hello を付与したレスポンスが返ってきた👌

$ cat custom-response.json | jq .
{
  "response": "Hello Lambda Managed Instances"
}

とまぁここまでの動作確認だと普通に AWS Lambda 関数を実行しているだけで,AWS Lambda Managed Instances を使って Amazon EC2 上で実行されているという感覚はないと思う🥲 動作確認の次は Terraform でデプロイしたリソースを確認していく!

キャパシティプロバイダを確認する

AWS Lambda Managed Instances では新しくキャパシティプロバイダ (Capacity Provider) という設定が必要になる.キャパシティプロバイダには VPC 設定・インスタンス条件・スケーリング設定などを設定する.

docs.aws.amazon.com

$ aws lambda get-capacity-provider --capacity-provider-name $(terraform output -raw capacity_provider_name)
{
    "CapacityProvider": {
        "CapacityProviderArn": "arn:aws:lambda:us-east-1:000000000000:capacity-provider:lambda-capacity-provider-tf",
        "State": "Active",
        "VpcConfig": {
            "SubnetIds": [
                "subnet-00481e4aa1e0cf9b6",
                "subnet-01349eb05169192e1",
                "subnet-0dd16fe84335e4182"
            ],
            "SecurityGroupIds": [
                "sg-03c3191cc643797a2"
            ]
        },
        "PermissionsConfig": {
            "CapacityProviderOperatorRoleArn": "arn:aws:iam::000000000000:role/hello-world-managed-instances-tf-capacity-provider-role"
        },
        "InstanceRequirements": {
            "Architectures": [
                "arm64"
            ]
        },
        "CapacityProviderScalingConfig": {
            "ScalingMode": "Auto"
        },
        "LastModified": "2026-02-21T05:21:22.400Z"
    }
}

Amazon EC2 インスタンスを確認する

キャパシティプロバイダ経由で自動的に起動する Amazon EC2 インスタンスを確認する.今回は m8g.xlarge のインスタンスが3つ起動していた.

$ CAPACITY_PROVIDER_ARN=$(terraform output -raw capacity_provider_arn)
$ aws ec2 describe-instances \
  --filters "Name=tag:aws:lambda:capacity-provider,Values=$CAPACITY_PROVIDER_ARN" \
  --query 'Reservations[*].Instances[*].[InstanceId,InstanceType,State.Name,LaunchTime,SubnetId,PrivateIpAddress]' \
  --output table
---------------------------------------------------------------------------------------------------------------------------
|                                                    DescribeInstances                                                    |
+---------------------+-------------+----------+----------------------------+----------------------------+----------------+
|  i-035a166b1fa59c0a7|  m8g.xlarge |  running |  2026-02-21T05:21:58+00:00 |  subnet-0dd16fe84335e4182  |  10.0.119.70   |
|  i-0227e3232ea01b0ab|  m8g.xlarge |  running |  2026-02-21T05:21:58+00:00 |  subnet-01349eb05169192e1  |  10.0.166.226  |
|  i-050c137b5640ee1bb|  m8g.xlarge |  running |  2026-02-21T05:21:59+00:00 |  subnet-00481e4aa1e0cf9b6  |  10.0.137.160  |
+---------------------+-------------+----------+----------------------------+----------------------------+----------------+

ちなみに AWS Lambda Managed Instances で使えるインスタンスタイプの一覧は料金ページにあった💡(見つからなくて結構探した...😇)

aws.amazon.com

Amazon CloudWatch Logs を確認する

次に AWS Lambda 関数のログを確認すると initializationType の値が AWS Lambda Managed Instances になっていた.いくつかのログを抜粋して載せておく📝

platform.initStart

{
    "time": "2026-02-21T05:22:38.931Z",
    "type": "platform.initStart",
    "record": {
        "initializationType": "lambda-managed-instances",
        "phase": "init",
        "runtimeVersion": "python:3.13.mainlinev2.v3",
        "runtimeVersionArn": "arn:aws:lambda:us-east-1::runtime:15b6277d72513ff8127d4dd2d54a7ff6c0dd1340a8508cc2decb1ac9ba7c3441",
        "functionName": "hello-world-managed-instances-tf",
        "functionVersion": "1",
        "instanceId": "2026/02/21/hello-world-managed-instances-tf[1]c125de18cc6b4e578550d7372a1ce776",
        "instanceMaxMemory": 2147483648
    }
}

platform.initReport

{
    "time": "2026-02-21T05:22:38.973Z",
    "type": "platform.initReport",
    "record": {
        "initializationType": "lambda-managed-instances",
        "phase": "init",
        "status": "success",
        "metrics": {
            "durationMs": 41.91
        }
    }
}

platform.start

{
    "time": "2026-02-21T05:43:58.477Z",
    "type": "platform.start",
    "record": {
        "requestId": "3590dba7-b7ee-43ee-92f2-1566efe4e4b2",
        "functionArn": "arn:aws:lambda:us-east-1:000000000000:function:hello-world-managed-instances-tf:1",
        "version": "1"
    }
}

platform.report

{
    "time": "2026-02-21T05:43:58.479Z",
    "type": "platform.report",
    "record": {
        "requestId": "3590dba7-b7ee-43ee-92f2-1566efe4e4b2",
        "metrics": {
            "durationMs": 2.588
        },
        "spans": [
            {
                "name": "responseLatency",
                "start": "2026-02-21T05:43:58.478Z",
                "durationMs": 0.837
            },
            {
                "name": "responseDuration",
                "start": "2026-02-21T05:43:58.479Z",
                "durationMs": 0.078
            }
        ],
        "status": "success"
    }
}

追加検証: メモリサイズを減らしてみる

AWS Lambda Managed Instances ではメモリサイズの最低要件が 2 GB になっている.

docs.aws.amazon.com

意図的に 128 MB に変更して plan / apply を実行してみた.

   runtime          = "python3.13"
   architectures    = ["arm64"]
   description      = "Simple Hello World Lambda function on Managed Instances"
-  memory_size      = 2048
+  memory_size      = 128
   publish          = true

すると apply で Lambda Managed Instance functions must have memory size greater than or equal to 2048 というエラーが出ることを確認できた💡

╷
│ Error: updating Lambda Function (hello-world-managed-instances-tf) configuration: operation error Lambda: UpdateFunctionConfiguration, https response error StatusCode: 400, RequestID: f3d9ccb5-00d0-47cc-94fb-4d5c2e94e4e2, api error ValidationException: 'MemorySize' value failed to satisfy constraint: Lambda Managed Instance functions must have memory size greater than or equal to 2048
│ 
│   with aws_lambda_function.hello_world_function,
│   on main.tf line 412, in resource "aws_lambda_function" "hello_world_function":
│  412: resource "aws_lambda_function" "hello_world_function" {
│ 
╵

追加検証: インスタンスタイプを制限してみる

もともと m8g.xlarge のインスタンスが3つ起動されていた.キャパシティプロバイダの設定で許可するインスタンスタイプを制限できるため m8g.large のみを許可するようにしてみた.Terraform だと aws_lambda_capacity_providerallowed_instance_types で設定できる.

ちなみにキャパシティプロバイダの許可するインスタンスタイプは1度デプロイすると変更できないため新しく作り直した.

resource "aws_lambda_capacity_provider" "lambda_capacity_provider_2" {
  name = "lambda-capacity-provider-tf-2"
  
  vpc_config {
    subnet_ids         = [aws_subnet.private_subnet_1.id, aws_subnet.private_subnet_2.id, aws_subnet.private_subnet_3.id]
    security_group_ids = [aws_security_group.lambda_security_group.id]
  }

  instance_requirements {
    architectures = ["arm64"]
    allowed_instance_types = ["m8g.large"]
  }

  permissions_config {
    capacity_provider_operator_role_arn = aws_iam_role.capacity_provider_role.arn
  }

  tags = {
    Name        = "lambda-capacity-provider-tf-2"
    Environment = "demo"
  }
}

期待通りに AWS Lambda 関数に紐付くキャパシティプロバイダを変更できた.

少し待っていると m8g.large のインスタンスが4つ起動されていた.

まとめ

最近 AWS Serverless Patterns Collection に追加されたパターン「AWS Lambda Hello World on AWS Lambda Managed Instances (Terraform)」を試してみた❗️さらに気になるところは追加検証もしてみた.あくまで AWS Lambda Managed Instances の基本的なデプロイを体験するパターンなのでスケーリングなどは体験できず,別途試す必要がある.

github.com

ちなみに main.tf を読んでいたら不要なタグ実装があって削除するプルリクエストを出しておいた.同じパターンを CDK でデプロイする lambda-managed-instances-cdk もあるからそこからコピーされた系なのかなーと.

github.com

関連記事

aws.amazon.com

X ポスト

Terraform で Amazon ECR のブロブマウンティングを有効化する(Terraform AWS Provider v6.29.0 から)

2026年1月に発表された Amazon ECR のブロブマウンティング (Blob mounting) を有効化すると Amazon ECR リポジトリ間で同じレイヤーを共有できてイメージのプッシュを高速化できる.

aws.amazon.com

docs.aws.amazon.com

Terraform AWS Provider v6.29.0

Terraform だと2026年1月28日にリリースされた Terraform AWS Provider v6.29.0 から aws_ecr_account_setting リソースを使ってブロブマウンティング (Blob mounting) を有効化できるようになっていた👌

github.com

👾 ecr.tf

以下のように実装すれば OK❗️

resource "aws_ecr_account_setting" "blob_mounting" {
  name  = "BLOB_MOUNTING"
  value = "ENABLED"
}

apply すると期待通りにブロブマウンティング (Blob mounting) を有効化できた \( 'ω')/

余談