EC2のユーザーデータ内でcloud-initとシェルスクリプトを使いたい

こんにちは。こんばんは。

たまたま、CloudFormationのテンプレートから起動されるEC2のユーザーデータを利用して、インストールしておきたいモジュールがありました。

ユーザーデータには、cloud-initシェルスクリプト で何らかの処理を書くことができるのですが、 テンプレートにはすでにcloud-initの形式で書かれており、シェルスクリプトを書こうとするとエラーとなりユーザーデータで書いた内容は実行されません。

EC2のユーザーデータ内で、cloud-initシェルスクリプト を併用したいけどそんなことができるのかといろいろ調べていくうちに、この記事に行き着きました。

cloud-initでシェルスクリプトとcloud-configを同時に使う

はい、やりたかったことはこれです!!

ってことで、実際に自分でやってみた手順を書いていきたいと思います。

cloud-utils パッケージをインストールする

まず、cloud-utils パッケージをインストールしましょう。

$ sudo yum install cloud-utils

※ 上記は、Amazon Linux AMI 2018.03.0 から作成したEC2内で作業をしています。

cloud-init 形式で書いてファイルを作成

viを立ち上げてファイルを作成します。

$ vi cloud-config.txt

そして、以下の内容をコピペして保存してください。

#cloud-config
packages:
  - sl

runcmd:
  - echo "HELLO Cloud Config"

シェルスクリプトで書いてファイルを作成

viを立ち上げてファイルを作成します。

$ vi shell.txt

そして、以下の内容をコピペして保存してください。

#!/bin/bash -xe

touch /home/ec2-user/create-by-shellscript.txt
echo "HELLO ShellScript" >> /home/ec2-user/create-by-shellscript.txt

write-mime-multipart で MIMEマルチパート形式のファイルを作成

先ほど作成した、cloud-config.txtshellscript.txt を使って、 MIMEマルチパート形式のファイルを作成します。

以下のコマンドを実行してみましょう。

$ write-mime-multipart --output=output.txt cloud-config.txt:text/cloud-config shell.txt:text/x-shellscript

するとカレントディレクトリに、output.txt が作成されていると思います。

ファイルの内容を確認するとこのように記述されています。

Content-Type: multipart/mixed; boundary="===============2433150631494388583=="
MIME-Version: 1.0

--===============2433150631494388583==
Content-Type: text/cloud-config; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="cloud-config.txt"

#cloud-config
packages:
  - sl

runcmd:
  - echo "HELLO Cloud Config"

--===============2433150631494388583==
Content-Type: text/x-shellscript; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="shell.txt"

#!/bin/bash -xe

touch /home/ec2-user/create-by-shellscript.txt
echo "HELLO ShellScript" >> /home/ec2-user/create-by-shellscript.txt

--===============2433150631494388583==--

このファイルの内容をそのままEC2のユーザーデータにコピペして起動してあげると、 処理が自動で実行されます。

f:id:ryskit:20180516203222p:plain

立ち上げたインスタンスにSSHで入って確認してみましょう!

ユーザーデータの内容が実行されたかどうかは、/var/log/cloud-init-output.txt を見れば確認できます。

$ less /var/log/cloud-init-output.log
:
:
Existing lock /var/run/yum.pid: another copy is running as pid 2597.
Another app is currently holding the yum lock; waiting for it to exit...
  The other application is: yum
    Memory :  38 M RSS (286 MB VSZ)
    Started: Wed May 16 11:30:54 2018 - 00:00 ago
    State  : Running, pid: 2597
Resolving Dependencies
--> Running transaction check
---> Package sl.x86_64 0:5.02-1.6.amzn1 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

================================================================================
 Package     Arch            Version                   Repository          Size
================================================================================
Installing:
 sl          x86_64          5.02-1.6.amzn1            amzn-main           13 k

Transaction Summary
================================================================================
Install  1 Package

Total download size: 13 k
Installed size: 15 k
Downloading packages:
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Installing : sl-5.02-1.6.amzn1.x86_64                                     1/1
  Verifying  : sl-5.02-1.6.amzn1.x86_64                                     1/1

Installed:
  sl.x86_64 0:5.02-1.6.amzn1

Complete!
Cloud-init v. 0.7.6 running 'modules:final' at Wed, 16 May 2018 11:30:58 +0000. Up 25.17 seconds.
HELLO Cloud Config
+ touch /home/ec2-user/create-by-shellscript.txt
+ echo 'HELLO ShellScript'
Cloud-init v. 0.7.6 finished at Wed, 16 May 2018 11:30:58 +0000. Datasource DataSourceEc2.  Up 25.50 seconds

正しくログが吐かれていますね!!

CloudFormationのEC2インスタンスのユーザーデータでも同じことをしたい場合は、 作成したMIMEマルチパート形式のファイルの内容を同じようにコピペしてあげれば動作します。 ただし、JSON形式だとダブルクオテーションで一文一文を囲ってあげないと動作しないと思うのでそこは注意してくださいね。

では!!