Lambda MicroVMs の TERMINATED から復帰する方法 – 再起動ではなく作り直しだった

タグ:

AWS Lambda MicroVMs を立てたまま放置していたところ、後から同じエンドポイントに curl を送ってもレスポンスが返らなくなりました。get-microvm で状態を確認すると、状態は TERMINAT […]

広告ここから
広告ここまで

目次

    AWS Lambda MicroVMs を立てたまま放置していたところ、後から同じエンドポイントに curl を送ってもレスポンスが返らなくなりました。get-microvm で状態を確認すると、状態は TERMINATED になっていました。

    原因の分析、TERMINATED 後の正しい復帰手順、実際に詰まった箇所の順に整理します。なお、MicroVM イメージの作成自体は完了している前提で進めるため、イメージ作成の手順はここでは扱いません。

    サスペンドから自動終了までの仕組み

    Lambda MicroVMs は、run-microvm 実行時に渡す idle policy で、放置時の挙動を制御します。今回使った設定は次の内容です。

    {
      "autoResumeEnabled": true,
      "maxIdleDurationSeconds": 900,
      "suspendedDurationSeconds": 300
    }
    

    AWS公式ドキュメントによると、MicroVM は RUNNINGSUSPENDEDTERMINATED などの状態を遷移します。トラフィックが maxIdleDurationSeconds(今回は900秒=15分)途絶えると RUNNING から SUSPENDED へ移り、メモリとディスクの状態はそのまま保持されます。ここでさらに SUSPENDED の状態が suspendedDurationSeconds(今回は300秒=5分)続くと、今度は TERMINATED へ自動的に遷移します。

    つまり、この設定のまま放置すると、合計でおよそ20分後には TERMINATED に至る計算になります。ただし、この20分という数字は設定値を単純に合算した見立てであり、放置してから実際に何分で TERMINATED になったかをストップウォッチで計測したものではありません。運用で idle policy を設計する際は、maxIdleDurationSecondssuspendedDurationSeconds の両方を合わせた時間で見積もる必要があります。

    TERMINATED は「再起動」できない

    放置して繋がらなくなった状態を見ると、つい「再起動すればいい」と考えたくなりますが、どうやらそれはできない様子です。ドキュメントには、TERMINATED したMicroVMを再開したり再起動したりすることはできないと明記されていました。

    resume-microvm が有効なのは SUSPENDED 状態から RUNNING へ戻す場合だけであり、TERMINATED に対して resume-microvm を呼んでも復帰しません。

    必要な操作は、同じイメージから新しい MicroVM を作り直すことです。新しい MicroVM には新しい microvmId と新しい endpoint が発行されるため、古い ID や URL を使い続けることはできません。この後の手順で使う ENDPOINTTOKEN は、すべて新しい microvmId に紐づけて取り直す必要があります。

    新しい MicroVM を作ってつなぎ直す

    まず run-microvm で新しい MicroVM を作成します。--image-identifier には既存イメージの ARN を渡します。

    aws lambda-microvms run-microvm \
      --image-identifier "arn:aws:lambda:us-east-1:<account-id>:microvm-image:hidetaka-env-only" \
      --idle-policy '{"autoResumeEnabled":true,"maxIdleDurationSeconds":900,"suspendedDurationSeconds":300}' \
      --region us-east-1
    

    レスポンスには新しい microvmIdendpoint が含まれます。

    {
        "microvmId": "microvm-4b0feb88-ce8b-3d4d-9443-855408db72f4",
        "state": "PENDING",
        "endpoint": "cecfb4fb-c401-f6e2-1fe9-51b8ad55445e.lambda-microvm.us-east-1.on.aws",
        "maximumDurationInSeconds": 28800
    }
    

    state はまだ PENDING なので、get-microvmRUNNING になったことを確認します。PENDING のままリクエストを送ると接続自体が失敗するため、この確認を挟むことで無駄な試行を減らせます。

    aws lambda-microvms get-microvm \
      --microvm-identifier "microvm-4b0feb88-ce8b-3d4d-9443-855408db72f4" \
      --region us-east-1 --query state
    

    "RUNNING"
    

    RUNNING になったら、その新しい microvmId 宛てに認証トークンを発行します。トークンは microvmId ごとに発行されるため、古い microvmId 向けのトークンを新しい MicroVM に使い回すことはできません。

    export ENDPOINT="cecfb4fb-c401-f6e2-1fe9-51b8ad55445e.lambda-microvm.us-east-1.on.aws"
    
    aws lambda-microvms create-microvm-auth-token \
      --microvm-identifier microvm-4b0feb88-ce8b-3d4d-9443-855408db72f4 \
      --expiration-in-minutes 60 \
      --allowed-ports "port=8080" \
      --region us-east-1 > /tmp/v3_token_resp.json
    
    export TOKEN=$(python3 -c "import json; d=json.load(open('/tmp/v3_token_resp.json')); print(d['authToken']['X-aws-proxy-auth'])")
    

    ここまでで ENDPOINTTOKEN が新しい MicroVM のものに揃ったので、curl でリクエストを送ります。今回の検証環境では、MicroVM 内で動かしているアプリ(イメージ「hidetaka-env-only」)が /exec というエンドポイントでシェルコマンドを受け取り、実行結果を JSON で返す作りになっています。これはこのイメージ固有の実装であり、Lambda MicroVMs 自体が汎用的に提供している機能ではありません。

    curl -s "https://${ENDPOINT}/exec" \
      -H "X-aws-proxy-auth: ${TOKEN}" \
      -H "Content-Type: application/json" \
      -d '{"command":"uname -a && nproc && free -m && cat /proc/cpuinfo | grep \"model name\" | head -1"}' | jq .
    

    {
      "exitCode": 0,
      "stdout": "Linux localhost 6.1.166-24.303.amzn2023.aarch64 #1 SMP Wed Mar 25 10:39:29 UTC 2026 aarch64 Linux\n4\n              total        used        free      shared  buff/cache   available\nMem:           8017         128        7712           3         177        7684\nSwap:             0           0           0\n",
      "stderr": ""
    }
    

    unamenprocfree -m の結果が返ってきており、新しい MicroVM に正しく接続できたことが確認できました。

    古い ENDPOINT・TOKEN の使い回しで詰まった点

    今回実際に詰まったのは、新しい MicroVM を作った後も、シェルの履歴に残っていた古い ENDPOINTTOKEN を export し直さずに使い続けてしまったことです。get-microvm で古い microvmId を確認すると状態は TERMINATED と表示されますが、そのままだと古い ENDPOINTTOKEN の組み合わせで curl を送ってしまい、レスポンスが空文字で返ってきます。受け側のスクリプトはその空文字を JSON として parse しようとするため、次のようなエラーになります。

    json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
    

    このエラーメッセージ自体は、JSON として読める文字が1文字もなかったことしか教えてくれません。原因が TERMINATED なのか、TOKEN の期限切れなのか、単なる打ち間違いなのかを見分けるには、まず get-microvm で対象の microvmId の状態を確認するのが早道です。

    放置するなら idle policy を見直す

    Lambda MicroVMs を対話的な用途で使う場合、離席や休憩で maxIdleDurationSeconds を超えるのは珍しくないでしょう。今回のように suspendedDurationSeconds まで超えて TERMINATED に至ると、再起動ではなく新しい MicroVM を作り直すところからやり直しになります。長時間放置する可能性がある運用では、suspendedDurationSeconds を長めに取るか、逆に不要な MicroVM を早めに terminate-microvm で終了させる運用に寄せるかを、意図的に選ぶ必要があります。詳細な設定項目は Lambda MicroVMs の概要ページを参照してください。

    広告ここから
    広告ここまで
    Home
    Search
    Bookmark