この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
EC2のユーザーデータを使って起動時に色々とインストールするのはよくあることだと思います。 今回はそのユーザーデータを任意に変更できるよう、S3に配置したシェルスクリプトをユーザーデータに読み込んで実行できるかを試してみました。
シェルスクリプトの準備
ユーザーデータとして読み込ませるシェルを準備し、S3に配置します。今回は以下のような「jq」をインストールするシェルスクリプトを準備しました。
ec2-template.sh
#!/bin/bash
sudo yum update -y
sudo yum -y install jq
上記のシェルスクリプトを、今回は「dev-honda-ec2-test」バケットに保存しました。
CloudFormationテンプレート
EC2を起動するためのCloudFormationテンプレートを準備します。以下のようになりました。
AWSTemplateFormatVersion: '2010-09-09'
Description: 'EC2 template.'
Parameters:
AmiID:
Type: String
Default: ami-0ecb2a61303230c9d
Prefix:
Type: String
SubnetID:
Type: String
UserDataBucket:
Type: String
UserDataShell:
Type: String
Resources:
EC2IAMRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub ${Prefix}-ec2-role
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- ec2.amazonaws.com
Action:
- sts:AssumeRole
Path: /
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
Policies:
-
PolicyName: !Sub ${Prefix}-ec2-policy
PolicyDocument:
Version: 2012-10-17
Statement:
-
Effect: "Allow"
Action:
- s3:GetObject
Resource:
- !Sub "arn:aws:s3:::dev-honda-ec2-test/*"
EC2InstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Path: /
Roles:
- Ref: EC2IAMRole
InstanceProfileName: !Sub ${Prefix}-ec2-instance-profile
Instance:
Type: AWS::EC2::Instance
Properties:
ImageId: !Ref AmiID
InstanceType: t2.micro
IamInstanceProfile: !Ref EC2InstanceProfile
NetworkInterfaces:
- AssociatePublicIpAddress: "true"
DeviceIndex: "0"
SubnetId: !Ref SubnetID
UserData:
Fn::Base64: !Sub |
#!/bin/bash
aws s3 cp s3://${UserDataBucket}/${UserDataShell} /tmp/${UserDataShell}
chmod +x /tmp/${UserDataShell}
./tmp/${UserDataShell}
Tags:
- Key: Name
Value: !Sub ${Prefix}-ec2
「Parameters」ではEC2インスタンス名などに任意のプレフィックスを指定するための「Prefix」、EC2を起動するサブネットを指定する「SubnetID」、先に書いたシェルスクリプトの格納先バケットやスクリプト名を指定する「UserDataBucket」「UserDataShell」を用意しました。AMIは(執筆時時点の)東京リージョンのAmazon Linux 2のAMIである「ami-0ecb2a61303230c9d」をデフォルト値としています。
「Resources」ではEC2のインスタンスロールを作るための「EC2IAMRole」、EC2インスタンスを作成するための「Instance」などを定義しました。「EC2IAMRole」では、後ほどSession Managerでログインするための「AmazonSSMManagedInstanceCore」ポリシーと、S3からシェルスクリプトを取得するためのポリシーを定義しています。
「Instance」の「UserData」では、S3バケット内のシェルスクリプトを「/tmp」ディレクトリに取得して実行するためユーザーデータを定義しています。
実行してみる
上記のCloudFormationテンプレートを使い、実際にスタックを作成してみました。スタック作成時のパラメータは以下のようになりました。
キー | 値 |
---|---|
AmiID | ami-0ecb2a61303230c9d |
Prefix | t-honda-test |
SubnetID | subnet-xxxx |
UserDataBucket | dev-ec2-test |
UserDataShell | ec2-template.sh |
スタックのステータスが「CREATE_COMPLETE」となると、EC2インスタンスが作成されます。先にも書いたようにEC2インスタンスにはSession Managerでログインします。マネージメントコンソールよりEC2を選択し、「接続」ボタンを押すとターミナルが表示されます。
ターミナルでは以下のように「ls -l」でS3に配置したシェルスクリプトがダウンロードされているか、シェルスクリプトに記述した「jq」がインストールされているかを確認してみました。
S3に配置した「ec2-template.sh」がダウンロードされ、「jq」もインストールされているようです。
最後に
以上のようにS3に配置したシェルスクリプトをユーザーデータに読み込んで実行することができました。何かの役に立てば幸いです。