EC2のユーザーデータでS3に配置したシェルスクリプトを実行してみた
はじめに
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に配置したシェルスクリプトをユーザーデータに読み込んで実行することができました。何かの役に立てば幸いです。