EC2を作成後に毎回同様の設定変更をする運用でしたが、「ユーザーデータ」機能を活用して作業時間を短縮できましたので、備忘としてやり方を記載したいと思います。
##対象
OS: Redhat6.7
##手順概要
- 元となるEC2に必要な処理を書いたShellscryptを配置
-
- のEC2インスタンスからAMIを作成
- 以後、EC2インスタンス作成時に2. のAMIとユーザーデータを指定
- 完成
実際はもっと色々設定変更を行っているのですが、例として下記の自動化に絞って書きたいと思います。
・/etc/hosts の変更
・/etc/sysconfig/network の変更
これらのファイルを
127.0.0.1 yaseinohost_number localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
NETWORKING=yes
HOSTNAME=yaseinohost_number
NETWORKING_IPV6=no
NOZEROCONF=yes
このように変更したい(「number」の部分を数字に置き換えたい)
127.0.0.1 yaseinohost_100 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
NETWORKING=yes
HOSTNAME=yaseinohost_100
NETWORKING_IPV6=no
NOZEROCONF=yes
##手順
####1. 元となるEC2にShellScriptを配置します
#!/bin/sh -x
#Get SecurityGroupName from meta-data and extract number
number=`curl -s http://169.254.169.254/latest/meta-data/security-groups |sed -e 's/yaseino-//g' -e 's/-SG//g'`
#Modify file "/etc/hosts"
cp -ip /etc/hosts /etc/hosts`date "+%Y%m%d_%H%M%S"`
sed -i -e "s/number/${number}/g" /etc/hosts
cat /etc/hosts
#Modify file "/etc/sysconfig/network"
cp -ip /etc/sysconfig/network /etc/sysconfig/network`date "+%Y%m%d_%H%M%S"`
sed -i -e "s/number/${number}/g" /etc/sysconfig/network
cat /etc/sysconfig/network
解説:
「number」に入れる数字はセキュリティグループ名の数字と合わせたいため、meta-dataから取得しました。
#meta-dataからセキュリティグループ名を取得できる
$curl -s http://169.254.169.254/latest/meta-data/security-groups
yaseino-100-SG
#さらにsedで不要な文字列をカット
$curl -s http://169.254.169.254/latest/meta-data/security-groups |sed -e "s/yaseino-//g" -e "s/-SG//g"
100
セキュリティグループ以外にも、meta-dataから色々な値が取得可能です。
$ curl -s http://169.254.169.254/latest/meta-data/
ami-id
ami-launch-index
ami-manifest-path
block-device-mapping/
events/
hostname
identity-credentials/
instance-action
instance-id
instance-type
local-hostname
local-ipv4
mac
metrics/
network/
placement/
profile
public-hostname
public-ipv4
public-keys/
reservation-id
security-groups
数字が取得出来たら、あとは各ファイルの内容をsedで書き換えるだけです。
また、/etc/cloud/cloud.cfgに下記を定義しておきます、
(インスタンスの初回起動時にip-XX-XX-XX-XXというPrivate IPを元にしたホスト名に変更されてしまうため)
preserve_hostname: True
####2. EC2からAMIを作成します
AWSマネジメントコンソール>EC2>にて手順1. のインスタンスを選択し、
アクション>イメージ>イメージの作成
####3. 以後、新しいEC2インスタンス作成時に2. のAMIとユーザーデータを指定
Cloudformationのテンプレート(YAML形式)
AWSTemplateFormatVersion: '2010-09-09'
Description: 'AWS CloudFormation Template for EC2'
----
省略
----
Resources:
MyEC2instance:
Type: "AWS::EC2::Instance"
Properties:
ImageId: !Ref 'ImageId' #手順2. で作成したAMIを指定
InstanceType: !Ref 'InstanceType'
SubnetId: !Ref 'SubnetID'
DisableApiTermination: False
BlockDeviceMappings:
- DeviceName: /dev/sda1
Ebs:
VolumeType: gp2
VolumeSize: !Ref 'StorageSize'
SecurityGroupIds: !GetAtt 'MyLinuxEC2SecurityGroups.GroupId'
KeyName: !Ref 'Keyname'
Tags:
- Key: Name
Value: !Ref 'Hostname'
UserData:
Fn::Base64: !Sub |
#cloud-config
runcmd:
- /home/ec2-user/script/auto_setting01.sh >/home/ec2-user/script/auto_setting.log 2>&1
- reboot
----
省略
----
解説:
・「UserData:」プロパティを使用しています。
・#cloud-configを宣言してruncmd: にそのままコマンドが書けます。
・#!/bin/bashを宣言すれば、直接シェルスクリプトを実行することもできます。
・#cloud-configと#!/bin/bashを両方実行するには、少しコツがいるようです。
https://dev.classmethod.jp/cloud/aws/cloud-init-use-shell-and-cloud-config/
・設定を反映させるためにrebootしています。
・Cloudformationからではなく直接EC2を作成する場合も、ユーザーデータの記述が可能です。
(EC2作成途中画面>高度な詳細>ユーザーデータ)
####4. 完成
EC2が作成されたあと、ユーザーデータに記載した処理が自動的に実行されます。
その分少しだけ作成完了まで時間がかかりました。
出力されたログを確認してみます。
上手く動いたようです。
++ curl -s http://169.254.169.254/latest/meta-data/security-groups
++ sed -e s/yaseino-//g -e s/-SG//g
+ number=100
++ date +%Y%m%d_%H%M%S
+ cp -ip /etc/hosts /etc/hosts20191025_031836
+ sed -i -e s/number/100/g /etc/hosts
+ cat /etc/hosts
127.0.0.1 yaseinohost_100 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
++ date +%Y%m%d_%H%M%S
+ cp -ip /etc/sysconfig/network /etc/sysconfig/network20191025_031836
+ sed -i -e s/number/100/g /etc/sysconfig/network
+ cat /etc/sysconfig/network
NETWORKING=yes
HOSTNAME=yaseinohost_100
NETWORKING_IPV6=no
NOZEROCONF=yes
実際にファイルも確認してみます。
127.0.0.1 yaseinohost_100 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
NETWORKING=yes
HOSTNAME=yaseinohost_100
NETWORKING_IPV6=no
NOZEROCONF=yes