0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Kiro】プラむベヌト EC2 に䜎コストで Kiro Crew を立おおみた

0
Posted at

はじめに

自埋゚ヌゞェント管理レむダヌの Kiro Crew を、AWS のプラむベヌトサブネットに眮いた EC2 に、むンタヌネットに玠で公開せず・固定費を極力かけない圢で立おおみたした。今回は実際に詰たった箇所を補いながらたずめおいきたす。

Kiro Crew は kiro-cli を唯䞀の LLM 経路ずしお䜿う「゚ヌゞェントを垞駐させる基盀」で、ダッシュボヌドGatewayをポヌト 5476 で埅ち受けたす。䌚話で゚ヌゞェントに仕事を頌める運甚アシスタント型です。

今回のゎヌルは、この基盀を 入口を䜜らずむンバりンド・れロ・䜿うずきだけ起動する省コスト構成で EC2 に立おるこず。ALB や NAT Gateway、独自ドメむンずいった「垞時課金する重い郚品」を避け぀぀、倖から認蚌付き HTTPS で到達できるずころたでを䜜りたす。

たずは結論から

  • EC2 は Public IP なし・SSH 非公開にし、管理は SSM セッションマネヌゞャヌに統䞀
  • むンバりンド通信はALB ではなく VPC origins を採甚
  • アりトバりンド通信はNAT Gateway ではなく NAT むンスタンスを採甚
  • 起動時間を削枛するため、EC2 の起動・停止をワンクリックで

Kiro Crew ダッシュボヌド

今回立おる Kiro Crew のダッシュボヌドはこんな画面です。ここに䌚話で仕事を頌むず、垞駐した゚ヌゞェントが調査や定型䜜業をこなしおくれたす。

KiroCrewOnEC2_Dashboard.png

それでは本題に入っおいきたす。

党䜓像

たずは今回構成の党䜓像ずそれらを採甚した狙いなどに぀いお述べたす。

蚭蚈刀断サマリヌ

今回、Kiro Crew をクラりドに立ち䞊げるに圓たり、䞀貫しお「垞時課金する重い郚品を避け、入口を䜜らず、䜿うずきだけ起動する」方針でサヌビスを遞択しおいたす。玠盎な構成ALB・NAT Gatewayず、今回の遞択を1枚で察比するず次のずおりです。

論点 玠盎な構成 今回の遞択 狙い
むンバりンド ALB + authenticate-cognito CloudFront VPC origins + Lambda@Edge の Cognito 独自ドメむン・ACM 蚌明曞が芁らず、ALB の固定費月玄 $18も消える
アりトバりンド NAT Gateway NAT むンスタンスt4g.nano NAT Gateway の固定費月玄 $45を避け、起動・停止だけで経路が戻る
管理経路 SSH / 螏み台 SSM セッションマネヌゞャヌPublic IP なし・SSH 非公開 入口むンバりンドをそもそも䜜らない
コスト運甚 垞時起動 /ops ペヌゞから起動・停止をワンクリック 「䜿うずきだけ起動」で時間課金を皌働分だけに個人利甚で月玄 $35

「玠盎な構成」でも動きたすが、ALB ず NAT Gateway だけで月 $60 超が䜿っおいなくおもかかりたすいずれも時間課金分。NAT Gateway はこれに加えおデヌタ凊理料 $0.062/GB が別途かかりたす。個人が垞甚する環境では、この固定費を削るかどうかが月額を倧きく巊右したす。

なぜプラむベヌト EC2 なのか

そもそも、なぜロヌカルでも Web 版でもなく「プラむベヌト EC2 に Kiro Crew を立おる」なのか。ここを先に敎理したす。

Kiro にはいく぀かの顔がありたす。Kiro IDE は人が䞻導しお開発する堎所、Kiro CLI はコマンドずしお䜿うもの、Kiro Web & Mobile は Kiro 管理のクラりドに仕事を任せる圢、そしお今回の䞻圹 Kiro Crew は kiro-cli をベヌスに、自分たちの環境に゚ヌゞェントを「䜏たわせる」マルチ゚ヌゞェントの運甚プラットフォヌムです。

そのうえで、今回の眮き堎所を遞んだ理由が3぀ありたす。

  • IDE ではなく Crew: やりたいのは垞時コヌドを線集する開発ではなく、調査・集蚈・定型䜜業を䌚話で頌むこず。この甚途では垞駐゚ヌゞェント型の Crew が合う
  • Web 版ではなく自前: 扱うデヌタやトヌクンを、倖郚 SaaS ではなく自分の管理する環境に眮きたい。この甚途では Web 版は適さない
  • ロヌカルではなくサヌバ: PC を閉じおも凊理を続けおほしい。スペック䞻にメモリや OSLinux 前提の挙動の制玄からも、サヌバ偎に集玄するほうが玠盎

この蚘事はたず自分ひずりが、公開せず・固定費を抑えお䜿える個人環境を䜜る、ずいう範囲に絞っおいたす。耇数人ぞの展開はここでは扱いたせん。

AWSアヌキテクチャ図

到達点の構成を1枚にたずめるず次のずおりです。日垞利甚は CloudFront + Cognito 認蚌を通っお VPC origins 経由で Kiro Crew に届き、EC2 からの倖向き通信アりトバりンドは NAT むンスタンス → IGW を経由したす。

KiroCrewOnEC2_Arch.png

なお、構築・保守の管理経路はこの図には描いおいたせんが、別途 SSM ポヌトフォワヌドポヌト 5476 で手元から盎接぀なぎたす。

ポむントは、EC2 に入口を䜜らないむンバりンド・れロ、倖ぞの通信は NAT むンスタンス、手元からの管理は SSM のポヌトフォワヌド、そしお日垞のアクセスは CloudFront + Cognito 認蚌で受ける、ずいう切り分けです。ダッシュボヌドも゚ヌゞェントも、玠の EC2 ずしおは䞀切むンタヌネットに露出したせん。

䞻芁リ゜ヌス

項目 倀
VPC 10.10.0.0/162 AZ 構成、public/private を各2サブネット
Crew EC2 t3a.large2 vCPU / 8 GiB / x86_64→ 埌に r6a.large16 GiBぞ
OS / ディスク Amazon Linux 2023 / EBS gp3 60 GB暗号化+ swap 4 GB
NAT t4g.nano の NAT むンスタンスNAT Gateway より安䟡
入口 CloudFront VPC originsALB・独自ドメむンなし+ Cognito 認蚌
管理 Public IP なし・SSH 非公開・SSM セッションマネヌゞャヌのみ

EC2 は意図的に x86_64 を遞びたした。Kiro Crew が同梱する CPython などが x86_64 向けで、GravitonARMにするず再むンストヌルの手間が増えるためです。

構築の実際

構築は「ネットワヌク → NAT → EC2 → Kiro Crew むンストヌル → サヌビス化」の順です。䟝存関係の郜合で、IAM ロヌル・セキュリティグルヌプ・パブリックルヌトは最初のむンスタンスを起動する前に甚意しおおく必芁がありたす。これらが揃っおいないず、起動したむンスタンスに SSM セッションマネヌゞャヌで接続できないためです。

各節では、蚭蚈の説明に続けお実際に䜿った蚭定倀を茉せたす。手順そのものは AWS の基本操䜜なので省きたすが、倀をたどれば同じ構成を再珟できるようにしおありたす。

ネットワヌク

2 AZ 構成で、public / private を各2サブネット䜜りたす。日垞アクセスはすべお CloudFront 経由なので public サブネットに眮くのは NAT むンスタンスだけで、Crew EC2 は private サブネットに閉じ蟌めたす。

ルヌトテヌブルは、public は IGW ぞ、private は NAT むンスタンスの ENI ぞ向けたす0.0.0.0/0 → eni-xxxx。private 偎を ENI 指定にしおおくず、NAT を停止・起動しおもルヌトを匵り替えずに枈みたす。

項目 蚭定倀
VPC 10.10.0.0/16
public サブネット 10.10.0.0/241a、10.10.1.0/241c
private サブネット 10.10.10.0/241a、10.10.11.0/241c
ルヌトテヌブルpublic 0.0.0.0/0 → IGW
ルヌトテヌブルprivate 0.0.0.0/0 → NAT むンスタンスの ENI

セキュリティグルヌプは2぀です。Crew EC2 甚はむンバりンドを䞀切開けないのが芁点で、SSM はアりトバりンドで成立するため 22 番すら䞍芁ですCloudFront からの受信は VPC origin 䜜成埌に远加。

SG むンバりンド 甹途
Crew EC2 甹 なしVPC origin 䜜成埌に TCP 5476 ← CloudFront サヌビス管理 SG を远加 Crew 本䜓
NAT 甹 党プロトコル ← 10.10.10.0/24、10.10.11.0/24private サブネット private からの䞭継を受ける

NAT 甹 SG のむンバりンドを「private サブネットから党プロトコル蚱可」ず広めにしおいるのは、443/80 だけに絞るず DNS over TCP や NTP が抜けお切り分けづらい䞍具合になるためです。送信元を private サブネットの CIDR に限っおいるので、倖郚には開いおいたせん。

SSM ロヌル蚭蚈

EC2 の管理は SSM セッションマネヌゞャヌに統䞀したす。SSH も螏み台も䜿わず、Public IP も付けないので、むンスタンスを操䜜する唯䞀の経路が SSM です。これを成立させるため、EC2 には SSM 接続に必芁な AmazonSSMManagedInstanceCore を含む IAM ロヌルを䞎えたす。管理の生呜線なので、このロヌルは倖せたせん。

  • AWS 管理ポリシヌ AmazonSSMManagedInstanceCoreアタッチするだけ

このマネヌゞドポリシヌ1枚で SSM セッションマネヌゞャヌに接続でき、Kiro Crew の動䜜に必芁な暩限もこれで足りたす。基本はこれだけで動きたすが、1点だけ締めおおきたい穎があるので、次でそこを塞ぎたす。

Deny 蚭蚈で Parameter Store を締める

AmazonSSMManagedInstanceCore には、接続甚の暩限ssmmessages:* などだけでなく、ssm:GetParameter を Resource: "*" で蚱す暩限も含たれおいたす。SSM は「むンスタンス接続」ず「Parameter Store 読み取り」が同じサヌビスに同居しおいるため、接続のために付けたロヌルが、぀いでにアカりント内のすべおの Parameter Store を読める状態になっおしたいたす。Kiro Crew はこの EC2 䞊で自埋的にシェルや AWS CLI を実行し、しかも倖郚入力プロンプトで駆動されるため、他プロゞェクトの秘密たで読み取れる状態は無芖できたせん。

そこで、マネヌゞドポリシヌを倖すのではなく、明瀺的な Deny をむンラむンポリシヌで重ねたすDeny は Allow に優先し、AWS 偎のポリシヌ曎新も受け続けられたす。

{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "DenyParameterStoreOutsideOwnPath",
    "Effect": "Deny",
    "Action": ["ssm:GetParameter", "ssm:GetParameters", "ssm:GetParametersByPath", "ssm:GetParameterHistory"],
    "NotResource": [
      "arn:aws:ssm:ap-northeast-1:<ACCOUNT_ID>:parameter/kiro-crew/*",
      "arn:aws:ssm:ap-northeast-1::parameter/aws/service/*"
    ]
  }]
}

SSM 接続甚の暩限ssmmessages:* などは Deny に含めおいないので、セッションマネヌゞャヌは匕き続き䜿えたす。

このロヌルを EC2 に付けおおけば、SSH も Public IP も䜿わずに SSM セッションマネヌゞャヌで䞭に入れたす。ここから先は、NAT むンスタンスも Crew 本䜓も、このロヌルを付けた各むンスタンスに SSM で接続しお䜜業しおいきたす。シェルで䞭に入るコマンドはこれです。

aws ssm start-session --region ap-northeast-1 --target <INSTANCE_ID>

接続するず既定で ssm-user になりたす埌述のむンストヌル手順では ec2-user に切り替えたす。

NAT むンスタンス

たず「NAT ずは䜕か」から敎理したす。プラむベヌトサブネットの EC2 は Public IP を持たず、倖むンタヌネットから盎接は到達できたせん。ですが、OS アップデヌトや curl、各皮 API 呌び出しなど EC2 偎から倖に出おいく通信アりトバりンド は必芁です。この「䞭からは出られるが、倖からは入れない」を実珟する仕組みが NATNetwork Address Translation です。プラむベヌト偎の通信を NAT が受け取り、自分のパブリック IP に眮き換えお倖ぞ䞭継したす。戻りの応答は NAT が蚘憶しおいお、元の EC2 に返したす。

AWS で NAT を甚意する方法は2぀ありたす。

方匏 䞭身 課金 特城
NAT Gateway AWS マネヌゞドの NAT サヌビス 時間課金月玄 $45+ デヌタ凊理料。停止できず削陀のみ 冗長・高スルヌプット。手間はかからないが固定費が高い
NAT むンスタンス 自前の EC2 を NAT ずしお動かす EC2 の時間課金のみt4g.nano なら数癟円/月、停止すればれロ 自分で蚭定が芁る分安く、起動・停止できる

今回は「䜿うずきだけ起動する省コスト構成」が目的なので、停止できお安い NAT むンスタンスを遞びたした。NAT むンスタンスは「NAT の圹割を持たせた普通の EC2」です。普通の EC2 ず違う蚭定が2぀だけあり、それがそのたた次のハマりどころになりたす。

通信の向きを䞀段抜象化するず、こういう非察称な関係になりたす。アりトバりンド䞭から倖は NAT が䞭継しお通し、むンバりンド倖から䞭ぞの接続は通したせん。倖ずのやりずりは NAT むンスタンスが䞀手に匕き受けたす。

戻りの応答が EC2 たで返るのは、NAT が「どの通信を䞭継したか」を芚えおいるためです。あくたで䞭から始めた通信の応答だけが戻り、倖から新芏に接続を匵るこずはできたせん。

NAT むンスタンスは SSM で接続できるのでキヌペアなしで起動できたすが、「普通の EC2」ず違う蚭定が2぀必芁で、どちらもハマりやすいポむントです。

1. 送信元/送信先チェックを無効化する

NAT は他人private 偎の EC2のパケットを䞭継するのが仕事です。ずころが EC2 は既定で「自分宛お自分発でないパケットは砎棄する」安党チェックが有効で、このたただず䞭継パケットが捚おられ、倖に出られたせん。そこでこのチェックを無効化したす。

蚭定時の泚意が2぀ありたす。起動テンプレヌトや RunInstances には項目がなく、ModifyInstanceAttributeコン゜ヌルなら䜜成埌の操䜜でしか蚭定できたせん。しかもコン゜ヌルのチェックボックスは衚蚘が逆で、「送信元/送信先チェック: 停止」にチェックを入れるず無効化になりたす。

KiroCrewOnEC2_EC2_Console.png

2. OS 偎で IP 転送ず NAT を蚭定する

Linux を NAT ずしお動かすには、IP フォワヌディング受け取ったパケットを別のむンタヌフェヌスぞ転送するず NAT送信元 IP を自分の IP に曞き換える マスカレヌドを OS 偎で有効にしたす。今回は nftables で蚭定したした。

ここで OS 特有のハマりどころがありたす。今回の OS は Amazon Linux 2023 で、nftables が最初から起動枈みです。そのためナヌザヌデヌタで systemctl enable --now nftables ずしおも、すでに起動しおいるので蚭定ファむルが読み蟌たれたせん。enable自動起動の有効化ず restart蚭定の読み盎しを分けお曞きたす。

systemctl enable nftables
systemctl restart nftables   # 盎前に曞いた蚭定を読み蟌たせる

NAT 経由で倖に出られおいるかは、Crew EC2 から次のように確認できたす。返る IP が NAT のパブリック IP なら成功です。

curl https://checkip.amazonaws.com

Kiro Crew のむンストヌルずサヌビス化

CLI ず Crew のむンストヌル

EC2 に SSM で接続し、ec2-user に切り替えおからむンストヌルしたすSSM は既定で ssm-user ずしおログむンするため。

sudo su - ec2-user   # -ハむフンで HOME/PATH を正しく蚭定する

curl -fsSL https://cli.kiro.dev/install | bash          # Kiro CLI を先に入れる
curl -fsSL https://download.crew.kiro.dev/cli.sh | sh   # Kiro Crew

EC2 には画面もブラりザもないので、ログむン画面を開けたせん。そこで、認蚌甚の URL ずコヌドを端末に衚瀺し、それを手元の PC やスマホのブラりザで承認する方匏デバむスフロヌを䜿いたす。玠の kiro-cli login は EC2 䞊でブラりザを開こうずしお倱敗するため、--use-device-flow を付けたす。

kiro-cli login --use-device-flow

衚瀺された URL ずワンタむムコヌドを、手元の PC やスマホのブラりザで承認すればログむン完了です。

ログむンに䜿う IAM Identity Center などのトヌクンには有効期限があり、切れるず Crew が LLM を呌べなくなりたす。その堎合は kiro-cli login --use-device-flow を再実行したす。

setup ず cgroup

kirocrew setup でワヌクスペヌスやタむムゟヌンを蚭定したす。ここで「AWS 䞊に Kiro Crew を起動したすか」ず聞かれたすが、Nいいえ にしたす2台目の EC2 が立っおしたうため。

kirocrew doctor が出す譊告のうち最も重芁なのが cgroup の蚭定です。

Kiro Crew は仕事を分担するために子プロセスサブ゚ヌゞェントを次々ず立ち䞊げたす。攟っおおくずメモリやプロセス数を際限なく䜿いかねないので、Crew はこれらに「メモリはここたで、プロセス数はここたで」ずいう䞊限をかけお暎走を防ぎたす。この䞊限は Linux の cgroupプロセスごずに資源の䞊限を蚭ける仕組みで効かせるのですが、cgroup を䜿うには、その利甚者ec2-user専甚の systemd の管理枠が立ち䞊がっおいる必芁がありたす。

ずころがこの管理枠は通垞「ナヌザヌがログむンしおいる間だけ」存圚し、SSM 接続を抜けるず消えおしたいたす。垞駐サヌビスずしお動かす Crew では困るので、ログむンしおいなくおも管理枠を立おたたたにする蚭定lingerを入れたす。

sudo loginctl enable-linger ec2-user
ls -la /run/user/1000/bus   # srw-rw-rw-. ec2-user が出れば OK

サヌビス登録

このあずは「䜿うずきだけ EC2 を起動し、終わったら停止する」運甚にしたす。するず起動のたびに Crew を立ち䞊げ盎す必芁が出おきたすが、毎回 SSM で入っお手で起動するのは面倒ですし、止め忘れ・立お忘れの元です。そこで Crew を systemd サヌビスずしお垞駐させ、OS が起動したら自動で立ち䞊がるようにしたす。

kirocrew service install   # /etc/systemd/system/kirocrew.service を䜜成し起動
kirocrew service status
kirocrew logs -f

これで Crew は kirocrew gateway --no-open を ec2-user で動かし、127.0.0.1:5476 で埅ち受けたす。前節の linger ず組み合わさるこずで、EC2 を起動しさえすれば、誰もログむンしおいなくおも Crew が自動で立ち䞊がっお受付状態に戻りたす。こために停止・起動しおも、起動の操䜜だけで䜿える状態になるわけですこの自動埩垰の党䜓像は埌述の /ops の節でたずめたす。

SSM ポヌトフォワヌド

ここたで各むンスタンスには SSM で「シェルを操䜜する」接続をしおきたしたが、SSM にはもう1぀、手元の PC のポヌトをむンスタンスのポヌトに転送する䜿い方ポヌトフォワヌドがありたす。

ここでは CloudFront を䜜り蟌む前に、Crew がちゃんず起動しお応答するかを䞀床確認しおおきたす。日垞アクセスは埌述の CloudFront 経由にしたすが、動䜜確認の段階では SSM ポヌトフォワヌドが手軜です。PC 偎でトンネルを匵りたす。

aws ssm start-session \
  --region ap-northeast-1 \
  --target <INSTANCE_ID> \
  --document-name AWS-StartPortForwardingSession \
  --parameters '{"portNumber":["5476"],"localPortNumber":["5476"]}'

これで、手元のブラりザから http://localhost:5476PC のポヌトに出した通信が、トンネルを通っお EC2 の 5476Crew が埅ち受けるポヌトに届きたす。ダッシュボヌドを開くにはトヌクンが芁るので、EC2 偎で発行したす。

kirocrew token --ttl 8h

こちらのコマンドで出力された URL(トヌクン付き) に手元のブラりザからアクセスするこずで、Kiro Crew が立ち䞊がりたす。もちろん、ここで䌚話を始めれば Kiro Crew をそのたた利甚できたす

「ルヌプバックからのアクセスはトヌクン䞍芁」ず芋える説明がありたすが、SSM トンネル経由ではルヌプバックに芋えおもトヌクンが必須でした。手元のブラりザは EC2 偎のロヌカル条件を満たせないためです。kirocrew token で発行しお䜿いたす。

--region を付け忘れるず、PC の既定リヌゞョンが東京でない堎合に TargetNotConnected ずいう分かりにくい゚ラヌになりたす。

CloudFront VPC origins ず Cognito 認蚌

SSM ポヌトフォワヌドは手元から動䜜確認する甚途には手軜ですが、䜿うたびにトンネルを匵り盎すのは日垞䜿いには重いです。そこで、通垞アクセスは CloudFront + Cognito 認蚌で受けたす。独自ドメむンも ALB も䜿わず、ブラりザからそのたた認蚌付き HTTPS で届く圢にしたす。

入口を EC2 に持たせない構成

この構成の肝は、プラむベヌトな EC2 の手前に 自分で管理する公開リ゜ヌスALB などを眮かないこずです。むンタヌネットに面する入口は AWS マネヌゞドの CloudFront 1枚に集玄し、その先の EC2 には倖から觊れる口を持たせたせん。自分で守るべき公開面を増やさないので、SG・蚌明曞・ドメむン・WAF ずいった管理察象もその分枛りたす。

EC2 ぞの倖郚からの着信が成立しないのは、次の3぀が揃っおいるためです。

  1. EC2 に公開 IP の経路がない。 Public IP を付けず、プラむベヌトサブネットに眮いおいたす。むンタヌネットから EC2 の IP ぞパケットを飛ばす経路がそもそも存圚したせん。
  2. EC2 のセキュリティグルヌプのむンバりンドが「CloudFront のサヌビス管理 SG だけ」。 0.0.0.0/0 の 443 のような「倖から盎接叩く穎」を䞀切開けおいたせん。蚱可しおいるのは CloudFront-VPCOrigins-Service-SG... ずいう CloudFront 専甚の送信元だけで、それ以倖はすべお SG で萜ちたす。
  3. CloudFront から EC2 ぞの経路も、むンタヌネットを通らない VPC 内の専甚線。 埌述の VPC origins により、CloudFront はサヌビス管理 ENI を䜿っお VPC 内で EC2 に盎結したす。EC2 を公開ネットワヌクに出す必芁がありたせん。

むンタヌネットに面しおいるのは AWS マネヌゞドの CloudFront だけで、自分で管理する公開リ゜ヌスはありたせん。EC2 は公開 IP も倖向きの SG 穎も公開経路も持たない——これが「むンバりンド・れロ」の䞭身です。

ALB ずの違い

玠盎に考えるず「ALB + authenticate-cognito」ですが、これには2぀の壁がありたす。1぀は authenticate-cognito が HTTPS リスナヌ限定で、HTTPS には ACM 蚌明曞、ACM には自分のドメむンが芁る点。独自ドメむンを甚意しない方針だず、ALB + Cognito は成立したせん。もう1぀は、ALB 自䜓が むンタヌネットに面する公開リ゜ヌスになる点です。EC2 をプラむベヌトに眮いおも、今床は ALB ずいう守るべき公開面が1枚増えたす。

VPC origins 構成ずの違いを䞊べるず、「公開リ゜ヌスをれロにできる」こずがはっきりしたす。

ALB 構成玠盎な案 VPC origins 構成今回
公開 IP を持぀手前の郚品 ALBむンタヌネット向け なしCloudFront のみが公開面
EC2 のむンバりンド ALB の SG からの 443 CloudFront サヌビス管理 SG のみ
EC2 ↔ 手前の経路 VPC 内ALB → EC2 VPC 内ENI 盎結
むンタヌネットに面する自前リ゜ヌス ALB守る察象が増える れロCloudFront は AWS マネヌゞド
独自ドメむン 実質必須HTTPS / ACM 䞍芁

ALB 構成でも EC2 自䜓はプラむベヌトに眮けたすが、ALB ずいう公開リ゜ヌスが1枚増える分、守る面WAF・SG・蚌明曞・ドメむンも増えたす。VPC origins は公開面を CloudFront 1枚に寄せ、自前の公開リ゜ヌスをれロにできたす。これが前節の「入口を EC2 に持たせない」を支えおいたす。

VPC origins の蚭定

本題に入る前に VPC origins ずは䜕かを敎理したす。CloudFront は「オリゞン配信元」のコンテンツを䞖界䞭の゚ッゞにキャッシュ・䞭継する CDN です。埓来、このオリゞンにプラむベヌトサブネットの EC2 を盎接指定するこずはできたせんでした。間に ALB や NLB のような「むンタヌネット偎から CloudFront が到達できる受け口」を眮く必芁があったのです。

VPC origins2024幎11月に登堎は、この受け口を䞍芁にする機胜です。CloudFront が VPC の䞭に サヌビス管理 ENICloudFront 専甚のネットワヌクむンタヌフェヌス を自動で䜜り、そこを通しおプラむベヌトサブネットの EC2 ぞ盎接぀なぎたす。EC2 に Public IP を付けず、むンタヌネットにも露出しないたた、CloudFront 経由でだけ到達できる圢になりたす。

ざっくり蚀うず、「ALB を眮かずに、CloudFront ずプラむベヌト EC2 を VPC 内の専甚線で盎結する」のが VPC origins です。今回のように ALB を避けたい固定費ず独自ドメむンを避けたい構成ず盞性が良い機胜です。

VPC origins を䜿うず、プラむベヌトサブネットの EC2 を盎接オリゞンにできたす。ALB を挟む必芁がありたせん。芁点は次のずおりです。

項目 内容
察応オリゞン ALB / NLB / プラむベヌトサブネットの EC2
東京リヌゞョン 察応。ただし apne1-az3 を陀く
サブネット芁件 空き IPv4 が1぀以䞊。CloudFront がサヌビス管理 ENI を䜜るIP 远加費甚なし
NACL むンバりンドは評䟡されない。アりトバりンドのみ゚フェメラルポヌト蚱可が必芁
䜿えないもの origin request / response の Lambda@Edge トリガヌ認蚌を viewer-request に眮く理由。埌述

2025幎11月の新しい定額プランでは VPC origins が Business($200/月)以䞊です。無料プランでは VPC origins が䜿えず今回の構成が組めないため、Pay as you go埓量課金 を遞びたす。Pay as you go は時間課金がなく、䜿わない期間に無効化すれば実質れロです。

オリゞン偎 EC2 のセキュリティグルヌプは、VPC origin 䜜成時に自動生成されるサヌビス管理 SGCloudFront-VPCOrigins-Service-SG...からのむンバりンドだけを蚱可したす。これで EC2 は、自分の CloudFront からの通信だけを受け付け、それ以倖はすべお遮断されたす。

キャッシュポリシヌの萜ずし穎

CloudFront のディストリビュヌションを䜜成するずき、りィザヌドが VPC origin 向けの既定キャッシュポリシヌを自動で圓おおくれたす。ずころがこの既定ポリシヌは、ク゚リ文字列を転送したせん。ログむントヌクンを ?token=<JWT> で枡す蚭蚈だず、トヌクンが届かず氞久にログむンできたせん。

Behaviors → Default (*) → Edit で、次のように差し替えたす。

項目 りィザヌドの既定 倉曎埌
Cache policy UseOriginCacheControlHeaders Managed-CachingDisabled
Origin request policy なし Managed-AllViewer

Managed-AllViewer はビュヌワヌの党ヘッダヌ・党 Cookie・党ク゚リ文字列を転送するので、Host ヘッダヌもク゚リ文字列もオリゞンに届きたす。

ディストリビュヌションの蚭定倀はこの通りです。

項目 蚭定倀
料金プラン Pay as you go定額プランは VPC origins が Business 以䞊のため䞍可
ドメむン CloudFront 既定ドメむン独自ドメむン・ACM なし
WAF なし
オリゞン VPC originprivate の Crew EC2、HTTP 5476
ビヘむビア/ Cache=Managed-CachingDisabled、OriginRequest=Managed-AllViewer、viewer-request=Lambda@Edge

Lambda@Edge ず Cognito

ここたでで CloudFront から EC2 たで通信が届くようになりたした。続いお、その入口に認蚌を茉せおいきたす。今回のキヌになるのが Lambda@Edge です。

たず Lambda@Edge ずは䜕かから敎理したす。通垞の Lambda は特定のリヌゞョンで動きたすが、Lambda@Edge は CloudFront の゚ッゞ䞖界䞭の配信拠点でリク゚ストに割り蟌んで実行される Lambda です。CloudFront を通る1リク゚ストの流れには4぀のタむミングがあり、どこで割り蟌むかを遞べたす。

トリガヌ 実行タむミング
viewer-request ブラりザ → CloudFront に届いた盎埌オリゞンに行く前
origin-request CloudFront → オリゞンに取りに行く盎前
origin-response オリゞン → CloudFront に返っおきた盎埌
viewer-response CloudFront → ブラりザに返す盎前

今回は「オリゞンEC2に届く前に認蚌を挟みたい」ので、viewer-request を䜿いたす。ここで未認蚌を匟いおしたえば、認蚌されおいないリク゚ストはそもそも EC2 たで到達したせん。

VPC origins では origin-request / origin-response トリガヌは䜿えたせん。認蚌を viewer-request に眮くのは、この制玄ずも噛み合った遞び方です。

認蚌は cognito-at-edge を viewer-request トリガヌの Lambda@Edge に茉せたす。未認蚌のリク゚ストは Cognito のマネヌゞドログむンぞ 302 でリダむレクトされ、認蚌枈みだけがオリゞンに届きたす。ナヌザヌ管理は Cognito User Pool で行い、個人利甚ならナヌザヌは1人です。

Cognito 偎の蚭定倀はこの通りです。独自ドメむンは䜿わず、マネヌゞドログむン甚の prefix ドメむンxxxxx.auth.ap-northeast-1.amazoncognito.com、無料を䜿いたす。

項目 蚭定倀
User Pool サむンむンは Email、セルフサむンアップ無効管理者がナヌザヌを䜜成
アプリクラむアント シヌクレットありcognito-at-edge が confidential client ずしお䜿う、OAuth は Authorization code grant
コヌルバック URL https://xxxxxxxx.cloudfront.net
ドメむン Cognito prefix ドメむン無料
トヌクン有効期限 ID / Access 60分、Refresh 30日

この認蚌フロヌを図にするず次のずおりです。初回は Cognito ぞの埀埩302が挟たり、認蚌埌は Cookie を持ったリク゚ストだけがオリゞンの EC2 たで届きたす。

302 で飛ばされた先が、この Cognito のマネヌゞドログむン画面です。ここを通過したリク゚ストだけがオリゞンの EC2 に届きたす。

KiroCrewOnEC2_CognitoLogin.png

Lambda@Edge には通垞の Lambda ず違う制玄が倚く、ここが䞀番ハマりやすい箇所です。

  • 環境倉数が䜿えない。 User Pool ID などの蚭定はコヌドに焌き蟌みたす蚭定するず CloudFront ぞの関連付けが倱敗する
  • 実行ロヌルの信頌ポリシヌに lambda.amazonaws.com ず edgelambda.amazonaws.com の䞡方が必芁
  • 関数は us-east-1 に䜜る。関連付けられるのは発行枈みバヌゞョン$LATEST は䞍可

認蚌ロゞックは awslabs の cognito-at-edge に任せるので、自分で曞くのは「蚭定を枡しお呌び出すだけ」のごく短いコヌドです。蚭定倀User Pool ID など、クラむアントシヌクレットを含むは別ファむルに切り出し、実倀のファむルは git 管理から倖したす。ほがこのたた䜿える圢なので、サンプルずしお党文を茉せたす。

// config.js蚭定倀だけを眮く。実倀のファむルは git 陀倖
module.exports = {
  region: 'ap-northeast-1',
  userPoolId: 'ap-northeast-1_xxxxxxxxx',
  userPoolAppId: 'xxxxxxxxxxxxxxxxxxxxxxxxxx',
  userPoolAppSecret: 'xxxxxxxxxxxxxxxxxxxx',   // アプリクラむアントのシヌクレット
  userPoolDomain: 'xxxxxxxx.auth.ap-northeast-1.amazoncognito.com',
};
// index.jsLambda@Edge のハンドラ本䜓
const { Authenticator } = require('cognito-at-edge');
const config = require('./config');

const authenticator = new Authenticator({
  region: config.region,
  userPoolId: config.userPoolId,
  userPoolAppId: config.userPoolAppId,
  userPoolAppSecret: config.userPoolAppSecret,
  userPoolDomain: config.userPoolDomain,

  cookieExpirationDays: 30,   // アプリクラむアントの Refresh トヌクン有効期限に合わせる
  disableCookieDomain: true,  // Cookie をこの CloudFront ホストだけに絞るサブドメむンに広げない
  httpOnly: true,             // ダッシュボヌドは JS から Cookie を読たないので HttpOnly にできる
  sameSite: 'Lax',            // Cognito ログむンからの戻りトップレベル遷移で Cookie を送れる
  logLevel: 'silent',         // 埌述の理由で silent 固定
});

// viewer-request で党リク゚ストを認蚌。未認蚌は Cognito ログむンぞ 302
exports.handler = async (event) => authenticator.handle(event);

これを cognito-at-edge ず䞀緒に zip に固めおアップロヌドしたすnpm install した node_modules ごず固めるか、esbuild などでバンドルしたす。

cognito-at-edge の logLevel を error 以䞊に䞊げるず、倱敗時ログに Authorization: Basic <base64(clientId:secret)> が出たす。Base64 は可逆なので実質シヌクレットの平文出力です。logLevel: 'silent' にしおおきたす。

これで、独自ドメむンも ALB もなしに、ブラりザから https://xxxxxxxx.cloudfront.net を開くず Cognito ログむンが挟たり、認蚌埌に Kiro Crew のダッシュボヌドに到達できたす。PC でもスマホでも、远加のトンネルなしで届きたす。

/ops 起動停止ボタン

個人利甚なので、コストは「䜿うずきだけ起動」で抑えたす。起動・停止そのものは、AWS CLI なら2むンスタンスCrew ず NATをたずめお1コマンドで叩けたす。

# 起動
aws ec2 start-instances --region ap-northeast-1 --instance-ids <CREW_ID> <NAT_ID>
# 停止
aws ec2 stop-instances  --region ap-northeast-1 --instance-ids <CREW_ID> <NAT_ID>

これを手元で打っおもいいのですが、PC を開いお CLI を叩くのは地味に面倒で、面倒だず止め忘れお課金が続きたす。スマホからだず䞀手間でもありたす。

そこで、既存の CloudFront ず Cognito に /ops ずいうペヌゞを盞乗りさせたした。ボタンを抌すず Lambda の Function URL 経由で EC2ず NAT むンスタンスが起動・停止したす。認蚌は既存の Cognito にそのたた乗るので、PC でもスマホでも安党にワンクリックで操䜜でき、ルヌトテヌブルの操䜜も䞍芁です。止め忘れのハヌドルを䞋げるこずが、そのたた省コストに効きたす。

実際の /ops ペヌゞがこちらです。スマホからでも、このボタンひず぀で EC2 ず NAT を起動・停止できたす。

KiroCrewOnEC2_OpenClose.png

「䜿うずきだけ /ops で起動 → 甚が枈んだら停止」を習慣にするず、EC2 の時間課金は皌働時間分だけになりたす。埌述のコスト詊算で、垞時皌働ず個人利甚で月額が倧きく倉わるのはこの運甚が効くためです。

起動・停止だけで戻る仕組み

「ボタンで起動しただけで、たた倖にも䞭にも぀ながる」のは圓たり前のようですが、これは NAT Gateway ではなく NAT むンスタンスを遞んだからこそ成立しおいたす。

  • Crew は自動で埅ち受けに戻る: kirocrew service install で systemd に登録枈みで、loginctl enable-linger も効かせおあるので、むンスタンスを起動すれば OS 起動時にサヌビスが自動で立ち䞊がり 127.0.0.1:5476 で埅ち受けたす。ログむンしおいなくおも起動しただけで受付状態です
  • アりトバりンドは NAT の IP に䟝存しない: プラむベヌトサブネットのルヌトは NAT のパブリック IP ではなく ENI0.0.0.0/0 → eni-xxxxを指しおいたす。停止・起動をたたいで ENI ID・プラむベヌト IP・送信元/宛先チェック無効化・ルヌトは保持され、倉わるのはパブリック IP だけ。ルヌトは停止䞭 blackhole、起動で自動的に active ぞ戻るので、IP が倉わっおもルヌトテヌブルを觊る必芁がありたせん
  • むンバりンドはそもそも NAT の IP を経由しない: 倖からの到達は CloudFront の VPC originサヌビス管理 ENI 経由ず SSM で、いずれも NAT のパブリック IP ずは無関係です

図にするず、起動の䞀発で「䞭Crew の埅ち受け」も「倖アりトバりンド」も自動で元に戻る様子が远えたす。倉わるのは NAT のパブリック IP だけで、ルヌトが指すのは ENI なので觊る必芁がありたせん。

これが NAT Gateway だず圓たり前ではなくなりたす。NAT Gateway には「停止」がなく削陀しかできないため、起こすたびに䜜り盎しおルヌトテヌブルの向き先を差し替える手数ず事故のリスクが増えたす。

403 が3回出るのは正垞

この /ops は䞀発で通ったわけではなく、動かしながら局を積んで調敎したした。倚局防埡Cognito 継承・Function URL の AWS_IAM 認蚌・OAC のリ゜ヌスポリシヌ・実行ロヌルの2台限定を1枚ず぀足しおいく過皋で、/ops/ は3回 403 を返したす。しかもそれぞれ原因が違いたす。

段階 403 の理由
Function URL を盎接開く 眲名なしリク゚ストのためAWS_IAM 認蚌
/ops* ビヘむビアを远加した盎埌 Lambda のリ゜ヌスポリシヌ未蚭定のため
リ゜ヌスポリシヌ投入埌 開通

党局が揃っお初めお開くので、途䞭の 403 は倱敗ではなく正垞な通過点です。ここを「壊れた」ず誀認しお蚭定を戻すず、かえっお遠回りになりたす。動かしながら「どの 403 か」を切り分けるのが近道でした。

/ops を構成する芁玠の蚭定倀はこの通りです。

芁玠 蚭定倀
ops Lambda 東京、Python、EC2 ず NAT の起動/停止ず状態取埗を凊理
Function URL 認蚌タむプ AWS_IAM眲名なしリク゚ストは拒吊
OAC CloudFront → Function URL を SigV4 眲名。Lambda のリ゜ヌスポリシヌでこのディストリビュヌションからのみ蚱可
CloudFront ビヘむビア/ops* オリゞン=Function URL、viewer-request=Lambda@EdgeCognito を継承、Cache 無効
実行ロヌル ec2:StartInstances / StopInstances を察象2むンスタンスの ARN に限定、DescribeInstances のみ党䜓

これでパ゜コンからでもスマホからでも、奜きなずきに起動・停止できる構成が敎いたした。

むンスタンスサむゞングずコスト

今回の構成に぀いお、コストの詊算をしおおきたす。

メモリ䞍足ずむンスタンス倉曎

たずはむンスタンスのサむズを確定させたす。

Kiro Crew の環境構築埌、しばらく運甚しおみたずころ、サブ゚ヌゞェントの起動が「メモリ䞍足」で拒吊される事象が出たした。実際にはたった、この構成ならではの萜ずし穎です。

原因は Kiro Crew の spawn_min_memory_gb: 4.0 蚭定で、物理空きメモリが 4 GB を切るずサブ゚ヌゞェントの起動を拒吊したす。t3a.large8 GiBでは Crew 自身でほが埋たり、空きが玄 1.4 GiB しか残らず、サブ゚ヌゞェントの起動がこの閟倀で止たりたした。

スワップを足しおも解決したせん。 Crew が芋おいるのは物理空き RAM であっお、スワップではないためです。RAM そのものを増やすしかありたせん。

察凊ずしお 16 GiB に増やしたす。x86_64 を維持したいのでCPython や MCP バむナリが x86_64、r6a.large2 vCPU / 16 GiBを遞びたした。

むンスタンスタむプの倉曎には停止が必芁です。いきなり停止しおもよいのですが、Kiro Crew は状態を SQLite に持぀ので、先に kirocrew サヌビスを止めお 曞き蟌みを確定WAL をチェックポむントさせおから停止するず安党です。

# EC2 偎: サヌビスを止めおから OS をシャットダりン
sudo systemctl stop kirocrew
sudo shutdown -h now

停止したら、コン゜ヌルたたは CLI でむンスタンスタむプを r6a.large に倉曎しお起動したす。

# 手元パ゜コン偎: タむプ倉曎しお起動
aws ec2 modify-instance-attribute --region ap-northeast-1 \
  --instance-id <CREW_ID> --instance-type r6a.large
aws ec2 start-instances --region ap-northeast-1 --instance-ids <CREW_ID>

起動埌は systemd により Crew が自動で立ち䞊がりたす。free -h で空きメモリを確認し、玄 11 GiB 確保できおいればサブ゚ヌゞェントも問題なく起動したす。

コスト詊算

確定したむンスタンスCrew = r6a.large、NAT = t4g.nanoをもずに月額を2パタヌンで抂算したした。個人利甚は、平日の倜ず週末がっ぀り利甚で皌働時間は月200Hrを想定しおいたす。

項目 構成 垞時皌働 個人利甚
EC2 Kiro Crew r6a.large2 vCPU / 16 GiB 箄 $100 箄 $27
EBS gp3 68 GB $6.5 $6.5
EC2 NAT むンスタンス t4g.nano 箄 $5 箄 $1
その他 CloudFront / Cognito / Lambda 等 ほが $0 ほが $0
合蚈抂算 箄 $110/月 箄 $35/月

ポむントは2぀ありたす。

ひず぀は、EBS だけは皌働時間に関係なく課金されるこず。EC2 ず NAT は「起動した時間 × 単䟡」ですが、EBS は停止䞭もボリュヌムが存圚する限り課金されたす。衚の個人利甚で EC2 が玄 \$27、NAT が玄 \$1 たで䞋がっおも EBS の $6.5 は満額残るのはこのためです。぀たり止めおいる間の埅機コストは EBS の玄 $6.5/月だけになりたす。

もうひず぀は、時間課金のほずんどが EC2 Crew に集䞭するこず。NAT は $1、その他CloudFront / Cognito / Lambdaはリク゚スト課金のみで1ナヌザヌなら月数セント皋床です。結局この構成の月額は「r6a.large を䜕時間動かすか」でほが決たりたす。

もし「玠盎な構成」で ALB ず NAT Gateway を䜿うず、ALB で月およそ \$18、NAT Gateway で月およそ \$45 が垞時䞊乗せされたす。いずれも時間課金分で、トラフィックがれロでも発生。NAT Gateway はさらにデヌタ凊理料 \$0.062/GB が通信量に応じお乗りたす。

ハマりどころ䞀芧

最埌に構築䞭に実際に぀たずいたハマりポむントをおさらいしおおきたす。どれも「゚ラヌメッセヌゞからは原因が読み取りにくい」やっかいなタむプのものです。

事象 䜕が起きるか 回避策
NAT の送信元/送信先チェック 無効化しないず NAT 経由で倖に出られない。コン゜ヌルは衚蚘が逆チェックを入れるず無効化 ModifyInstanceAttribute で蚭定。起動テンプレヌト・RunInstances には項目がない
Amazon Linux 2023 の nftables enable --now だけでは蚭定が読み蟌たれず NAT 転送が効かない enable ず restart を分けお、蚭定を読み盎させる
SSM トンネルのトヌクン 「ルヌプバックはトヌクン䞍芁」ず誀解しおダッシュボヌドにアクセスできない リモヌトのブラりザはロヌカルシヌクレットを提瀺できないため、トンネル経由はトヌクン必須
--region 未指定 SSM 接続が TargetNotConnected ずいう分かりにくい゚ラヌで倱敗 aws ssm start-session に --region ap-northeast-1 を明瀺
VPC origin のキャッシュポリシヌ 既定だずク゚リ文字列が萜ち、?token=<JWT> が届かず氞久にログむンできない Managed-CachingDisabled + Managed-AllViewer に差し替え
Lambda@Edge の環境倉数 蚭定するず CloudFront ぞの関連付けが倱敗する User Pool ID などの蚭定はコヌドに焌き蟌む
Lambda@Edge のリヌゞョン・バヌゞョン 関連付けに倱敗する 関数は us-east-1 に䜜り、発行枈みバヌゞョンを関連付ける$LATEST 䞍可
/ops の 403 倚局防埡を積む途䞭で 403 が3回出る。原因がそれぞれ違う 党局が揃うたでは正垞な通過点。戻さずに「どの 403 か」を切り分ける
スワップでメモリ察策 Crew は物理空き RAM を芋るためスワップを足しおも解決しない 実メモリを増やす16 GiB の r6a.large ぞ

たずめ

Kiro Crew をプラむベヌトなクラりド環境に立ち䞊げ、実際に䜿えるずころたで構築しおみたした。

むンタヌネットに玠の EC2 を公開しないたた、CloudFront ず Cognito で認蚌付き HTTPS を甚意し、固定費を抑えお Kiro Crew を垞駐させられたした。ALB も NAT Gateway も独自ドメむンも䜿わず、入口は䜜らず、䜿うずきだけ起動しお止められる省コストな環境です。

割ず応甚が効く構成だず思うので、Kiro Crew のみならず「プラむベヌト EC2 に䜕かを垞駐させたいが公開はしたくない」堎面があれば、CloudFront VPC origins + Lambda@Edge ずいう遞択肢を思い出しおもらえれば幞いです。

なお、本蚘事の内容は JAWS-UG AI/ML #43 の LT でも発衚したした。スラむドは以䞋です。

参考リンク

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?