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

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

Amazon EC2ユーザガイドにもある通り、EC2をLaunchするときに指定できるUser-Dataは、シェルスクリプトとcloud-init形式(cloud-config)で書くことが出来ます。ただし、この2つをそのまま同時に書くとエラーになってしまいます。例えばUser-Dataに

#!/bin/bash
echo "User-Data Script" >> /home/ec2-user/test.txt

#cloud-config
runcmd: 
 - echo "Cloud-Config" >> /home/ec2-user/test.txt

のように両方の形式を併記すると、後に書いたほうがエラーになります。以下は/var/log/cloud-init.logの出力の抜粋です。

Aug 26 06:59:35 cloud-init[1615]: util.py[DEBUG]: Failed running /var/lib/cloud/instance/scripts/part-001 [127]
ProcessExecutionError: Unexpected error while running command.
...
Command: ['/var/lib/cloud/instance/scripts/part-001']
Exit code: 127
Reason: -
Stdout: ''
Stderr: ''
Aug 26 06:59:35 cloud-init[1615]: cc_scripts_user.py[WARNING]: Failed to run module scripts-user (scripts in /var/lib/cloud/instance/scripts)
...
RuntimeError: Runparts: 1 failures in 1 attempted commands

両方を同時に使いたいなぁと思って調べたところ、ubuntsu documentationCloudInitのページに以下の記載がありました。

This list of rules is applied to each part of this multi-part file. 
Using a mime-multi part file, the user can specify more than one type of data. 
For example, both a user data script and a cloud-config type could be specified.

しかもMIMEマルチパート形式のファイルを作るときのサンプルまであります。これだ。

ということでやってみました!

やってみる

上記のヘルプにある通り、MIMEマルチパート形式のファイルの作成には、write-mime-multipartコマンドを使ってみます。このためにMacBook上のVagrantにUbuntu環境を構築しました。

write-mime-multipartコマンドはcloud-utilsパッケージに含まれていますので、このパッケージをインストールします。

$ apt-cache search cloud-utils
cloud-utils - cloud image management utilities
$ sudo apt-get install cloud-utils

シェルスクリプトを記載したファイルと、cloud-init形式を記載したファイルを用意します。

$ vi bash.txt
#!/bin/bash
echo "User-Data:" `date` >> /home/ec2-user/test.txt
exit

$ vi cloud-config.txt
#cloud-config
runcmd:
 - echo "cloud-config:" `date` >> /home/ec2-user/test.txt

それではwrite-mime-multipartコマンドでMIMEマルチパート形式のファイルを作成してみましょう。

$ write-mime-multipart --output=hybrid.txt \
> bash.txt:text/x-shellscript \
> cloud-config.txt:text/cloud-config

$ cat hybrid.txt
Content-Type: multipart/mixed; boundary="===============1993995897=="
MIME-Version: 1.0

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

#!/bin/bash

echo "User-Data:" `date` >> /home/ec2-user/test.txt

exit

--===============1993995897==
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
runcmd:
 - echo "cloud-config:" `date` >> /home/ec2-user/test.txt

--===============1993995897==--

で、この出力されたhybrid.txtの内容を、EC2をLaunchするときにUser-Dataにそのまま入力します。そしてログイン後、/home/ec2-user/test.txtの内容を確認すると...

$ cat test.txt
User-Data: Tue Aug 26 07:26:11 UTC 2014
cloud-config: Tue Aug 26 07:26:11 UTC 2014

はい、両方とも同時に実行されています!

まとめ

ということで、シェルスクリプトとcloud-configを同時に使うことが出来る、というのは分かりました。そうすると実行タイミング、実行順序が気になるところです。次回はその辺を調査してみたいと思います。