CloudFormationのメタデータでEC2ユーザーデータの制限を回避する
Posted On 2025-02-16
CloudFormationのMetadata機能を使い、EC2にYAML形式で構成を適用することでユーザーデータの16KB制限を回避できる。Terraformと組み合わせてPyTorchを自動インストールする例を示し、保守性と再利用性を向上させる手法を紹介する。
目次
はじめに
- EC2のユーザーデータには、インスタンス初期化時に読まれるが、Base64でエンコードして16KBまでしか作れない
- エンコードやプレースホルダーなどバグる要因が多い。これまで試したときも結構ここのデバッグが時間かかった
- CloudFormation限定の機能で、EC2のユーザーデータをメタデータとしてYAML形式に分離することができる。これにより16KBの制限を突破でき、保守性や再利用性が良くなる。
作るもの
- EC2 ImageBuilderを試すのときに作った、最新のAmazon Linux 2023にPyTorchを入れる例を試す
- CloudFormationでSession Managerで接続可能なEC2+関連するロールやセキュリティグループを作成する
- CloudFormationのデプロイはTerraformで行う
コード
CloudForamtionのテンプレート
EC2Instance -> Metadata
以下がユーザースクリプトの部分で、ここにYAML形式で記述する- ユーザーデータは
cfn-init
のコマンドを呼び、スタック名とリソース名を参照される。これによりメタデータがユーザーデータとして動的に読み込まれる
AWSTemplateFormatVersion: '2010-09-09'
Description: >
EC2インスタンスを作成するCloudFormationテンプレート
・入力パラメータ(VPC ID、サブネットID、AMI)を利用
・インバウンドなし、アウトバウンド全許可のセキュリティグループを作成
・Session Manager利用用のIAMロールとインスタンスプロファイルを定義
・EC2インスタンスのMetadataにCloudFormation Initを定義し、ユーザーデータから実行
Parameters:
VpcId:
Type: AWS::EC2::VPC::Id
Description: VPC ID(Terraformから渡されます)
SubnetId:
Type: AWS::EC2::Subnet::Id
Description: サブネットID(Terraformから渡されます)
AMI:
Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
Default: /aws/service/ami-amazon-linux-latest/al2023-ami-minimal-x86_64
Description: EC2で使用するAMI(Amazon Linux 2023 の最小AMI)
Resources:
MySecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: "Allow all outbound traffic, deny all inbound traffic"
VpcId: !Ref VpcId
SecurityGroupEgress:
- IpProtocol: -1
CidrIp: 0.0.0.0/0
# インバウンドルールを定義しない(デフォルトは拒否)
SessionManagerRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- ec2.amazonaws.com
Action: sts:AssumeRole
Path: /
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
InstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Path: /
Roles:
- !Ref SessionManagerRole
EC2Instance:
Type: AWS::EC2::Instance
Metadata:
AWS::CloudFormation::Init:
config:
commands:
update:
command: "dnf update -y"
install_pip:
command: "dnf install -y python3-pip"
install_torch:
command: "pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu"
Properties:
ImageId: !Ref AMI
InstanceType: t3.medium
SubnetId: !Ref SubnetId
SecurityGroupIds:
- !Ref MySecurityGroup
IamInstanceProfile: !Ref InstanceProfile
UserData:
Fn::Base64: !Sub |
#!/bin/bash
/opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource EC2Instance --region ${AWS::Region}
Tags:
- Key: Name
Value: "SessionManagerEC2"
Terraformでのデプロイ
CloudFormationのTerraformでのデプロイ。パラメーターをCloudFormationに渡す。Terraformを中継している理由はCloudFormation単体だと、扱いが大変だから。
AMIのIDは、パラメーターストアの値を渡せばよい。実際のAMI IDを渡すとエラーになる。
variable "ami" {
description = "EC2で使用するAMIのID"
type = string
# 公式のパラメーターストアのIDを参照
# https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/parameter-store-public-parameters-ami.html
default = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-x86_64"
}
resource "aws_cloudformation_stack" "session_manager_stack" {
name = "session-manager-ec2-stack"
template_body = file("${path.module}/cloudformation-template.yaml")
parameters = {
VpcId = var.vpc_id
SubnetId = var.subnet_id
AMI = var.ami
}
capabilities = ["CAPABILITY_NAMED_IAM"]
}
結果
Session ManagerでEC2に入り、以下のコードを実行すると、最新版のPyTorchがインストールされているのがわかる。
sh-5.2$ python3
Python 3.9.20 (main, Jan 25 2025, 00:00:00)
[GCC 11.4.1 20230605 (Red Hat 11.4.1-2)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import torch
>>> torch.__version__
'2.6.0+cpu'
所感
- これだけ見るとユーザーデータの面倒くささが軽減されて、CloudFormationいいじゃんとなる
- しかし、CloudFormationの特有の面倒くささが結構あって
- 基本CloudFormationは日本語文字を想定してなくて文字化けするし、GroupDescriptionになると明確にエラーになる。ChatGPTがグループ名を日本語で出してしまうとエラーがよく出る
- ドリフトを直すとき(ユーザーデータをデバッグしてEC2を終了させてapplyみたいな場面)では、手順が結構長くなってしまう。
terraform apply
みたいに簡単にはいかない
- このメタデータの機能をTerraformで使えば最高なのだが残念ながらそういう機能はない。試そうとしている記事はある
- 結論からいうと、どっちもどっちという感じかなーと。そもそもユーザーデータに直書き必要な設計にしてるのが良くないし、どうしてもそういうことするならCodeBuildやDeployを使うべきな気がする。問題で出てきたからやってみたという位置づけです
Shikoan's ML Blogの中の人が運営しているサークル「じゅ~しぃ~すくりぷと」の本のご案内
技術書コーナー
北海道の駅巡りコーナー