AWS Marketplace AMIから起動したインスタンスのRootVolumeを他インスタンスにアタッチする方法

AWS MarketplaceのAMIから起動したインスタンスのRootVolumeはRootVolume(/dev/sda)以外でアタッチすることができない。
「Error attaching volume: ‘vol-xxxxxxxx’ with Marketplace codes may not be attached as a secondary device.」

オペレーションミスをしてサーバを閉じ込めてしまった場合の対処方法
(1)当該RootVolumeのスナップショットを取得する
(2)スナップショットをAWS MarketPlace 管理用アカウント(ID: 6795-9333-3241)に共有する
(3)AWSサポートに下記情報と制限を解除して欲しい旨を伝える
・スナップショットのID
・スナップショットが保存されているリージョン
・対象ボリューム/インスタンスのベースとなるAMIのID
・当該AMIのプロダクトバージョン

Red Hat Enterprise Linux (RHEL) 6 の場合
https://aws.amazon.com/marketplace/pp/B007ORSS8I?ref=cns_srchrow
Product Details
Version: 6.5
Available on AWS Marketplace Since: 03/26/2012

CentOS 6 の場合
https://aws.amazon.com/marketplace/pp/B00A6KUVBW/ref=cns_srchrow
Product Details
Version: 6 – 2014-09-29
Available on AWS Marketplace Since: 11/13/2012

(4)祈る
(5)AWSサポートから制限が解除されたスナップショットが共有される
(6)スナップショットからEBSを作成する
(7)作成したEBSを他インスタンスにアタッチする
(8)マウントし復旧作業する

Jenkins/GitLabでデプロイツールを作る

【お題】下記条件を満たしたデプロイツールを作成せよ

  1. インスタンスの増減に対応
  2. ロールバックが可能
  3. 既存のデプロイツール(rsync)と融合
  4. 複数システムで使用

「SVN+Capistrano」のデプロイツールは実績があるものの下記課題があるため作り直す。

  • バージョン管理でconflictすると面倒くさい
  • デプロイ実行履歴がログからしか分からない
  • デプロイしたコンテンツの差分がコマンドからしか分からない
  • 世間的にお手製のツールは信頼性が低い

バージョン管理でconflictすると面倒くさい問題
→コマンド実行するサーバを絞る

デプロイ実行履歴がログからしか分からない問題
→Jenkinsで見やすく

デプロイしたコンテンツの差分がコマンドからしか分からない問題
→GitLabで見やすく

世間的にお手製のツールは信頼性が低い問題
→オープンソースをベースに

[1] GitLab
(1) GitLabの構築
http://blog.tmkn.jp/gitlab-install/
(2) Projectの作成
(3) Repoの初期設定

[code]
mkdir (プロジェクト名)
cd (プロジェクト名)
git init
touch README.md
git add README.md
git commit -m "first commit"
git remote add origin git@127.0.0.1:cloudpack/sample-project.git
git push -u origin master
[/code]

作っている最中に気がついた。GitLab/JenkinsサーバがSPOFであることに。

「デプロイを実行したのに本番に反映されないんだけど」
見えた、未来が見えたぞ…!!

(*)「インスタンスの増減に対応」と「ロールバックが可能」は分ける方針に変更
http://blog.tmkn.jp/ec2-rsync/

[2] Jenkins
(1) Jenkinsの構築
http://blog.tmkn.jp/jenkins-install/
(2) 各スクリプトの準備
1. devからコンテンツを持ってくるスクリプト
同期対象から「.git」を除外する。

[code]
#!/bin/bash
#############
# Sync2Repo #
#############

SYNCHOST=(`aws ec2 describe-instances –filters Name=tag-value,Values=”(devのEC2 NameTag)” |jq ‘.Reservations[].Instances[]|{PrivateIpAddress}’ | grep “PrivateIpAddress” | awk ‘{print $NF}’ | sed -e “s/”//g”`)

SRCDIR=”(コンテツのあるディレクトリ)”
DSTDIR=”(リポジトリのディレクトリ)”

rsync -avc –delete –exclude=’.git’ -e ‘ssh -c arcfour256 -o StrictHostKeyChecking=no’ ${USER}@${SYNCHOST}:${SRCDIR} ${DSTDIR}
[/code]

2. 持ってきたコンテンツをGitLabにcommit/pushするスクリプト
commitする際に変更がないよ返り値が1になるようでJenkinsがFAILEDしてしまった。
スクリプトでまとめた。

[code]
#!/bin/bash
##############
# Commit2Git #
##############

git add -A
git commit -m “`date –iso-8601=seconds`”
git push
[/code]

(3) Jobの登録

[3] 既存のデプロイツール
下記2つを既存のデプロイツールに組み込む。
(1) 「インスタンスの増減に対応」したスクリプト(*)
http://blog.tmkn.jp/ec2-rsync/
(2) Jenkinsのプロジェクトを起動するcurl
http://blog.tmkn.jp/jenkins-kick/

rsyncするインスタンスをAWS EC2のNameタグを元に判断する

5分で作ったスクリプトのメモ
・管理サーバから実行することを想定
・(EC2インスタンスのNameタグ)は「prd-web」等を想定
・IAMrole使用
・jq使用
・並列実行風

[code]
#!/bin/bash
################
# Sync2DocRoot #
################

SYNCHOST=(`aws ec2 describe-instances –filters Name=tag-value,Values="(EC2インスタンスのNameタグ)*" | jq ‘.Reservations[].Instances[]|{PrivateIpAddress}’ | grep "PrivateIpAddress" | awk ‘{print $NF}’ | sed -e "s/"//g"`)

SRCDIR="(DocumentRootに配置するコンテンツのあるディレクトリ)"
DSTDIR="(WebサーバのDocumentRoot)"
#USER="root"

for ((i=0; i<${#SYNCHOST[*]}; i++))
do
rsync -avc –delete -e ‘ssh -c arcfour256 -o StrictHostKeyChecking=no’ ${SRCDIR} ${USER}@${SYNCHOST[$i]}:${DSTDIR} &
done
wait

exit 0
[/code]

NATの冗長化 〜High Availability NATパターンの別案〜

High Availability NATパターン
http://blog.suz-lab.com/2013/01/high-availability-natcentos6.html
が何故か安定しないので別案。

「pacemaker+corosync」は「ノード死活+iptables」から「ノード死活のみ」に変更し、iptablesはmonitで管理を行う。

crmコマンド再び
でcrmshを入れるとcorosyncとpacemakerも入るのでそのまま。

[code]
chkconfig pacemaker on
chkconfig corosync on
[/code]

NATインスタンスを作成する
の通り、NATインスタンスを作成する。(2台)

monitが入っていない場合はインストールする。
[code]
yum install monit
chkconfig monit on
[/code]

監視間隔は適宜変更する。
[code]
vim /etc/monit.conf
set daemon 5
[/code]

iptables用の設定を作成する。
[code]
vim /etc/monit.d/iptables.conf
check program iptables with path “/root/scripts/iptables-check.sh” with timeout 5 seconds
if status != 0 then restart
start program = “/etc/init.d/iptables start”
stop program = “/etc/init.d/iptables stop”
[/code]

iptables監視用のスクリプトを作成する。
[code]
mkdir /root/scripts/
vim /root/scripts/iptables-check.sh
#!/bin/bash
/etc/init.d/iptables status
exit ${?}

chmod +x /root/scripts/iptables-check.sh
[/code]

monitを起動する。
[code]
/etc/init.d/monit start
[/code]
この時点でサーバ起動時は常にiptablesが起動している環境ができあがる。
ここから下はルートテーブル変更の為の設定。

フェイルオーバー時のルートテーブル変更用スクリプトを作成する。
[code]
vim /etc/init.d/associate-nat
#!/bin/sh
#
# chkconfig: 2345 99 10
# description: Associate RouteTables

# Source Function Library
. /etc/init.d/functions

# System Variable
prog=${0##*/}
lock=/var/lock/subsys/$prog

# User Variavle
ROUTE_TABLE_ID=(ルートテーブルのID)
DESTINATION_CIDR=0.0.0.0/0

# Source Config
if [ -f /etc/sysconfig/$prog ] ; then
. /etc/sysconfig/$prog
fi

#
case “$1” in
start)
touch $lock
AZ=`curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone`
REGION=`echo $AZ | cut -c 1-$((${#AZ} – 1))`
INSTANCE_ID=`curl -s http://169.254.169.254/latest/meta-data/instance-id`
aws –region $REGION ec2 replace-route
–destination-cidr-block $DESTINATION_CIDR
–route-table-id $ROUTE_TABLE_ID
–instance-id $INSTANCE_ID
| logger -s -i -t $prog

exit ${PIPESTATUS[0]}
;;
stop)
rm -f $lock
exit 0
;;
status)
if [ -f $lock ] ; then
exit 0
else
exit 3
fi
;;
*)
echo “Usage: $0 {start|stop|status}”
exit 1
esac

chmod +x /etc/init.d/associate-nat
[/code]

corosyncの設定を各サーバへ行う。
[code]
vim /etc/corosync/corosync.conf
compatibility: whitetank

service {
name: pacemaker
ver: 0
use_mgmtd: yes
}

totem {
version: 2
secauth: off
threads: udpu
transport: udpu
interface {
ringnumber: 0
bindnetaddr: (自ノードのIPアドレス)
mcastport: 5405
ttl: 1
member {
memberaddr: (ノード1のIPアドレス)
}
member {
memberaddr: (ノード2のIPアドレス)
}
}
}

logging {
fileline: off
to_stderr: no
to_logfile: yes
to_syslog: yes
logfile: /var/log/cluster/corosync.log
debug: off
timestamp: on
logger_subsys {
subsys: AMF
debug: off
}
}

amf {
mode: disabled
}

/etc/init.d/corosync start
[/code]

リソースを追加する。(片側)
[code]
crm configure property no-quorum-policy=”ignore” stonith-enabled=”false”
crm configure rsc_defaults resource-stickiness=”INFINITY” migration-threshold=”1″
crm configure primitive associate-nat lsb:associate-nat
[/code]
associate-natを入れることで、フェイルオーバー時にルートテーブルを変更するスクリプトが実行される。

crm_monで確認する。
[code]
Last updated: Thu Feb 13 19:51:51 2014
Last change: Thu Feb 13 19:08:52 2014 via cibadmin on node02
Stack: classic openais (with plugin)
Current DC: node02 – partition with quorum
Version: 1.1.10-14.el6_5.2-368c726
2 Nodes configured, 2 expected votes
1 Resources configured

Online: [ node01 node02 ]

associate-nat (lsb:associate-nat): Started node01
[/code]

監視方法は下記の通り
・monitのプロセス監視
・NAT配下のインスタンスから外部(8.8.8.8)へfping