CentOS 6 (HVM)にcloud-initを設定してAmazon Linuxぽくする

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

CentOS6でcloud-init

CentOS7には最初からcloud-initが設定されていますが、まだまだCentOS6を使いたい方が多いかと思います。さらに、新型インスタンスを使えるHVMを使いたい方も多いのではと思います。ということで、初期設定を手順にまとめてみました。

CentOS6(HVM)を指定して起動

AWS MarketPlaceからCentOS 6 (x86_64) - with Updates HVMのAMIを選択しましょう。

screenshot 2014-11-02 13.31.42

HVMを選択することで、インスタンスタイプにt2とかr3を選択できるようになります!

screenshot 2014-11-02 13.32.20

awscliの動作確認するので、IAM RoleでPowerUserあたり選択しておいてください。

基本セットアップ

まずはログインしてセットアップしましょう。CentOS6の初期ユーザはrootですので気をつけてください。後でec2-userのみ接続できるようにします。

$ ssh -i hoge.pem root@IPアドレス

基本的なインストールは以下のコマンドで完了です。

$ sudo yum update -y
$ rpm -Uvh https://download.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
$ yum install cloud-init
$ cloud-init -v
cloud-init 0.7.4
$ easy_install pip
$ pip install awscli

Amazon Linuxをマネる

使い慣れたAmazon Linuxと同じようにcloud-initの設定をしたいと思います。

$ ls /etc/cloud/
cloud.cfg  cloud.cfg.d  template

以下のように設定ファイルを書き換えます。

/etc/cloud/cloud.cfg

データソースとしてEc2を指定しています。再起動時の自動リポジトリアップデートをOFFにし、言語設定を日本語にして、タイムゾーンを東京にしています。

user: ec2-user
disable_root: 1
ssh_pwauth:   0
 
locale: ja_JP.UTF-8
timezone: Asia/Tokyo
 
repo_upgrade: none
repo_upgrade_exclude:
 - kernel
 - nvidia*
 - cudatoolkit

datasource_list: [Ec2]
datasource:
  Ec2:
    metadata_urls: ['http://169.254.169.254']
 
mount_default_fields: [~, ~, 'auto', 'defaults,nofail', '0', '2']
resize_rootfs: noblock
resize_rootfs_tmp: /dev
ssh_deletekeys: true
ssh_genkeytypes: [ 'rsa', 'dsa', 'ecdsa' ]
syslog_fix_perms: ~

cloud_init_modules:
  - rsyslog
  - migrator
  - bootcmd
  - write-files
  - growpart
  - resizefs
  - set-hostname
  - update-hostname
  - update-etc-hosts
  - users-groups

cloud_config_modules:
  - locale
  - ssh
  - set-passwords
  - mounts
  - yum-configure
  - yum-add-repo
  - package-update-upgrade-install
  - timezone
  - puppet
  - disable-ec2-metadata
  - runcmd

cloud_final_modules:
  - scripts-per-once
  - scripts-per-boot
  - scripts-per-instance
  - scripts-user
  - ssh-authkey-fingerprints
  - keys-to-console
  - phone-home
  - final-message
  - power-state-change

system_info:
  distro: rhel
  default_user:
    name: ec2-user
    lock_passwd: true
    gecos: EC2 Default User
    shell: /bin/bash
  paths:
    cloud_dir: /var/lib/cloud/
    templates_dir: /etc/cloud/templates/
    upstart_dir: /etc/init/

mounts:
 - [ ephemeral0, /media/ephemeral0 ]
 - [ swap, none, swap, sw, "0", "0" ]

ssh用ユーザーのec2-userを作成する

CentOSへrootユーザでログインするのは推奨されていませんのでAmazon Linuxと同様にec2-userを作成します。

$ groupadd -g 500 ec2-user
$ useradd -g ec2-user ec2-user
$ mkdir /home/ec2-user/.ssh
$ visudo

visudo

ec2-user ALL=(ALL)       ALL
%ec2-user ALL=(ALL)       ALL
%ec2-user ALL=(ALL) NOPASSWD: ALL
$ cp /root/.ssh/authorized_keys /home/ec2-user/.ssh/authorized_keys
$ chown -R ec2-user:ec2-user /home/ec2-user/
$ rm /root/.ssh/authorized_keys

rootでsshできないようにします。

/etc/ssh/sshd_configを修正

PermitRootLogin no

一旦ログアウトしてrootで接続確認してみましょう。

$ ssh -i hoge.pem root@IPアドレス
Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
$ ssh -i hoge.pem ec2-user@IPアドレス
Last login: Sun Nov 2 20:40:55 2014 from XXX.XXX.XXX.XXX
[ec2-user@hoge ~]$

次にawsコマンドで入力補間できるか確認します。

.bash_profileに追記

complete -C aws_completer aws

補間できるか確認

$ source .bash_profile 
$ aws (Tabを押す)
autoscaling         configure           elb                 redshift            storagegateway 
cloudformation      datapipeline        emr                 route53             sts 
cloudsearch         directconnect       iam                 route53domains      support 
cloudsearchdomain   dynamodb            importexport        s3                  swf 
cloudtrail          ec2                 kinesis             s3api               
cloudwatch          elasticache         logs                ses                 
cognito-identity    elasticbeanstalk    opsworks            sns                 
cognito-sync        elastictranscoder   rds                 sqs

STOP/UserData編集/START

インスタンスをSTOPしてUserDataを埋め込みSTARTします。

screenshot 2014-11-02 19.32.00

#cloud-config
packages:
 - httpd

runcmd:
 - service httpd start
 - chkconfig httpd on

動作の確認

cloud-init経由でhttpdが動作しているか確認します。

$ chkconfig
acpid          	0:off	1:off	2:on	3:on	4:on	5:on	6:off
auditd         	0:off	1:off	2:on	3:on	4:on	5:on	6:off
cgconfig       	0:off	1:off	2:off	3:off	4:off	5:off	6:off
cgred          	0:off	1:off	2:off	3:off	4:off	5:off	6:off
cloud-config   	0:off	1:off	2:on	3:on	4:on	5:on	6:off
cloud-final    	0:off	1:off	2:on	3:on	4:on	5:on	6:off
cloud-init     	0:off	1:off	2:on	3:on	4:on	5:on	6:off
cloud-init-local	0:off	1:off	2:on	3:on	4:on	5:on	6:off
crond          	0:off	1:off	2:on	3:on	4:on	5:on	6:off
htcacheclean   	0:off	1:off	2:off	3:off	4:off	5:off	6:off
httpd          	0:off	1:off	2:on	3:on	4:on	5:on	6:off
ip6tables      	0:off	1:off	2:on	3:on	4:on	5:on	6:off
iptables       	0:off	1:off	2:on	3:on	4:on	5:on	6:off
netconsole     	0:off	1:off	2:off	3:off	4:off	5:off	6:off
netfs          	0:off	1:off	2:off	3:on	4:on	5:on	6:off
network        	0:off	1:off	2:on	3:on	4:on	5:on	6:off
postfix        	0:off	1:off	2:on	3:on	4:on	5:on	6:off
rdisc          	0:off	1:off	2:off	3:off	4:off	5:off	6:off
restorecond    	0:off	1:off	2:off	3:off	4:off	5:off	6:off
rsyslog        	0:off	1:off	2:on	3:on	4:on	5:on	6:off
saslauthd      	0:off	1:off	2:off	3:off	4:off	5:off	6:off
sshd           	0:off	1:off	2:on	3:on	4:on	5:on	6:off
udev-post      	0:off	1:on	2:on	3:on	4:on	5:on	6:off

$ curl localhost

ちゃんとインストールされて自動起動の設定がされていました。curlコマンドでも表示されます。しかし、ブラウザでは正しく表示されません。セキュリティがらみのようですね。

iptablesでポートを開ける

httpdを80番ポートで起動していますので、AWSのセキュリティグループで80番をオープンしています。しかし、繋がりません。これは、CentOSがiptables接続を拒否する設定にしているからです。

$ sudo iptables -L --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination         
1    ACCEPT     all  --  anywhere             anywhere            state RELATED,ESTABLISHED 
2    ACCEPT     icmp --  anywhere             anywhere            
3    ACCEPT     all  --  anywhere             anywhere            
4    ACCEPT     tcp  --  anywhere             anywhere            state NEW tcp dpt:ssh 
5    REJECT     all  --  anywhere             anywhere            reject-with icmp-host-prohibited 

Chain FORWARD (policy ACCEPT)
num  target     prot opt source               destination         
1    REJECT     all  --  anywhere             anywhere            reject-with icmp-host-prohibited 

Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination

それでは、5番目に新しいルールを追加したいと思います。

$ sudo iptables -I INPUT 5 -p tcp -m tcp --dport 80 -j ACCEPT
$ service iptables save
$ sudo iptables -L --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination         
1    ACCEPT     all  --  anywhere             anywhere            state RELATED,ESTABLISHED 
2    ACCEPT     icmp --  anywhere             anywhere            
3    ACCEPT     all  --  anywhere             anywhere            
4    ACCEPT     tcp  --  anywhere             anywhere            state NEW tcp dpt:ssh 
5    ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:http 
6    REJECT     all  --  anywhere             anywhere            reject-with icmp-host-prohibited 

Chain FORWARD (policy ACCEPT)
num  target     prot opt source               destination         
1    REJECT     all  --  anywhere             anywhere            reject-with icmp-host-prohibited 

Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination

それではブラウザから見てみましょう。

screenshot 2014-11-02 21.00.01

ちゃんと表示されてました!

おまけ

Amazon Linuxってログイン時にロゴっぽいテキストアートが表示されますよね。これやってみましょうw

作成は簡単です。アスキーアート作成Webサイトで簡単に作れます。

$ vi /etc/motd
  _____ _                _____ _____ __  __ ______ _______ _    _  ____  _____  
 / ____| |        /\    / ____/ ____|  \/  |  ____|__   __| |  | |/ __ \|  __ \ 
| |    | |       /  \  | (___| (___ | \  / | |__     | |  | |__| | |  | | |  | |
| |    | |      / /\ \  \___ \\___ \| |\/| |  __|    | |  |  __  | |  | | |  | |
| |____| |____ / ____ \ ____) |___) | |  | | |____   | |  | |  | | |__| | |__| |
 \_____|______/_/    \_\_____/_____/|_|  |_|______|  |_|  |_|  |_|\____/|_____/
 _____ __    _____ _____ _____ _____ _____ _____ _____ _____ ____  
|     |  |  |  _  |   __|   __|     |   __|_   _|  |  |     |    \ 
|   --|  |__|     |__   |__   | | | |   __| | | |     |  |  |  |  |
|_____|_____|__|__|_____|_____|_|_|_|_____| |_| |__|__|_____|____/

まとめ

今回は、CentOS6(HVM)にcloud-init等を設定して、Amazon Linuxと同じような環境を作ってみました。cloud-initはEC2インスタンス起動時に様々なパラメータを渡したり、ソフトウェアをインストールしたりできてとても便利です。当社では、リポジトリとしてS3にセットアッププログラムを配備して起動する際にブートストラップアクションを実行することが多いです。こうすることで、各リージョンにBaseとなるAMIをひとつ作り、アプリケーションに応じて指定するUserDataを切り替えてインスタンスの振る舞いを変えることができます。リージョン毎に毎度AMIを置く必要が無いのでマイルリージョン前提の大規模インフラ構築では効果を発揮します。Amazon LinuxやCentOS7は、全リージョンの置いてありますし、cloud-initが入っていますのでBaseのAMI自体用意する必要がありません。こ、これが、イミュータブルなのかっ!?(1回言ってみたかっただけです) 他にも、rootでログイン出来ないようにしたり、iptablesで80番ポート開けたりと、何気にハマる部分を中心にご紹介しました。良い道具は使い方を知ってなんぼですねー。まだまだ修行が足りません〜。それではまた!

参考資料

CentOS 6 (x86_64) - with Updates HVM

How do I set up cloud-init on custom AMIs in AWS? (CentOS)

CloudInit - Docs » Datasources View page source Datasources

Cloud-Init 0.7.4 EC2 Config

CLOUD-INIT: THE EARLY-INITIALIZATION TOOL YOU DIDN’T EVEN KNOW YOU NEEDED

ASCII Text Signature Generator / Figlet Frontend