うえきのブログ

妙高市に住んでいるサーバエンジニアのブログです

AWS hands-on の内容をコマンドラインでやってみる aws-api-tools

Phase-0 AWSコマンドラインツールの準備をする

普段使っているパソコンに aws-api-tools の実行環境を作成しても良いのですが、ec2で提供されているAmazon Linuxなら最初からコマンドがインストールされていて簡単です。

コマンド操作用ec2インスタンスを立ち上げる

AWS Management Consoleからec2インスタンスを起動しましょう。t1.micro タイプで問題ありません。
(以降、このインスタンスを作業用インスタンスと呼ぶことにします)

秘密鍵とX.509証明書をダウンロードする

ツールを使用してAPIにアクセスするためには秘密鍵とX.509証明書が必要になります。

AWSコンソールを開いて、画面右上の自分の名前をクリックして出てくるプルダウンメニューから "Security Credentials" をクリックします。
アクセス証明書のところにある "X.509証明書" で新しい証明書を作成します。小さいウインドウが開くので、"Private Key"と"X.509 Certifiate"をダウンロードします。

ダウンロードした秘密鍵と証明書を作業用インスタンスにコピーしてください。ここではec2-userのホーム下の aws ディレクトリに保存します。

まず作業用インスタンスsshでログインしホームディレクトリ下に aws ディレクトリを作成しておきます。

$ mkdir aws

次にローカルPCにダウンロードした秘密鍵と証明書を作業用インスタンスにコピーします。

$ scp -i uekikazuki.pem ~/Downloads/cert-XXXXXXXXXX.pem ec2-user@ec2-54-248-176-167.ap-northeast-1.compute.amazonaws.com:~ec2-user/aws
$ scp -i uekikazuki.pem Downloads/pk-XXXXXXXXXX.pem ec2-user@ec2-54-248-176-167.ap-northeast-1.compute.amazonaws.com:~ec2-user/aws

コマンドを実行する際にはコピーした秘密鍵と証明書のパスをコマンドラインオプションで指定するのですが、毎回パスを指定するのは手間なので、環境変数に設定しましょう。
あわせてEC2とRDSで使用するアベイラビリティゾーン(AZ)もTokyo(ap-northeast-1)に設定しておきます。(ここで指定するURLをエンドポイントを呼びます)

$ export EC2_PRIVATE_KEY=~/aws/pk-XXXXXXXXXX.pem
$ export EC2_CERT=~/aws/cert-XXXXXXXXXX.pem
$ export EC2_URL=https://ec2.ap-northeast-1.amazonaws.com
$ export RDS_URL=https://rds.ap-northeast-1.amazonaws.com

Phase-1 EC2インスタンスを立ち上げる

sshとhttpで繋がるようにSecurity Groupを作成する

次にセキュリティグループを作成します。セキュリティグループとはいわゆるファイアウォールのことです。
まず cms-app というセキュリティグループを作成し、次にその作成したセキュリティグループに通信を許可したいポート(tcp/22とtcp/80)を追加していきます。

$ ec2-create-group cms-app -d "SG for cms app (port 80 and 22)"
GROUP   sg-e1bacee0     cms-app SG for cms app (port 80 and 22)
$ ec2-authorize cms-app -P tcp -p 22 
GROUP                   cms-app 
PERMISSION              cms-app ALLOWS  tcp     22      22      FROM    CIDR    0.0.0.0/0       ingress
$ ec2-authorize cms-app -P tcp -p 80 
GROUP                   cms-app 
PERMISSION              cms-app ALLOWS  tcp     80      80      FROM    CIDR    0.0.0.0/0       ingress

AMIからEC2インスタンスを作成する

ハンズオンで使用したAMI(Amazon Machine Images: EC2インスタンス作成時のひな形となるもの)を指定してインスタンスを作成します。今回使うAMIのIDは ami-d170f5d0 です。作成する際、セキュリティグループは先ほど作成した cms-app を使用し、インスタンスタイプは一番小さな t1.micro を使用します。

$ ec2-run-instances \
  --group cms-app \
  --instance-type t1.micro \
  --instance-count 1 \
  --key <key-pair-name> \
  ami-d170f5d0
RESERVATION     r-79d4587a      376158489050    cms-app
INSTANCE        i-7d496c7e      ami-d170f5d0                    pending         0               t1.micro        2013-02-05T12:49:04+0000        ap-northeast-1a
        aki-44992845                    monitoring-disabled                                     ebs                                     paravirtual     xen   sg-e1bacee0      default false

作成したインスタンスにわかりやすく"Name"タグをつけておきます。NameタグをつけるとEC2 Management ConsoleのName列に表示されてインスタンスが区別しやすくなります。
タグをつける際には付与先のEC2インスタンスを指定します。EC2インスタンスは作成時に表示された i-xxxxxxxx がIDなので、これを指定します。

$ ec2-create-tags i-7d496c7e --tag Name=az-a-cms1
TAG     instance        i-7d496c7e      Name    az-a-cms1

EIPを割り当て、EC2インスタンスに関連づける

Elastic IP(固定グローバルIPアドレス)を取得して、作成したEC2インスタンスに関連づけます。
まず ec2-allocate-address を実行してEIPを取得します。

$ ec2-allocate-address
ADDRESS 54.249.238.6            standard

表示されたEIPをEC2インスタンスに関連づけます。先ほどと同様EC2インスタンスは作成時に表示された i-xxxxxxxx がIDなので、これを指定します。

$ ec2-associate-address 54.249.238.6 --instance i-7d496c7e
ADDRESS 54.249.238.6    i-7d496c7e

(a-blog cmsのセットアップ)

ここまでの作業でEIP(グローバルIPアドレス)を使ってEC2インスタンス上で動いているa-blog cmsというアプリケーションが表示できるはずです。早速ブラウザから表示してみましょう。

http://54.249.238.6/

初期設定が済んでいないので http://54.249.239.207/setup/install.php というURLに移動してインストールウィザードが表示されます。画面の指示に従って初期設定をしてください。(基本的にデフォルトのままボタンをクリックしていけば良いだけです)

データベースサーバ名
localhost
データベースが存在しなかった場合に、指定された名前でデータベースを作成する
チェックする
データベース名
ablogcms
データベースユーザー名
root
データベースパスワード
XXXXXXXX

Phase-2 RDSインスタンスを立ち上げる

MySQL DB用Security Groupを作成する

RDS用のセキュリティグループ(ファイアウォール)を作成します。
EC2の時と同様まず cms-db というセキュリティグループを作成し、次にその作成したセキュリティグループに通信を許可したいポート(tcp/3306)を追加していきます。
ここで特徴的なのはアクセス元としてEC2で作成したセキュリティグループ cms-app を指定できることです。これによってRDSにEC2インスタンスからのみアクセスを許可することができます。

$ rds-create-db-security-group cms-db -d "db SG for cms (port 3306)"
SECGROUP  cms-db  db SG for cms (port 3306)

なお --ec2-security-group-owner-id に指定するAWS Account Numberは ec2-describe-group で調べることができます。

$ ec2-describe-group cms-app
GROUP   sg-bba3d4ba     376158489050    cms-app SG for cms app (port 80 and 22) 
PERMISSION      376158489050    cms-app ALLOWS  tcp     22      22      FROM    CIDR    0.0.0.0/0       ingress
PERMISSION      376158489050    cms-app ALLOWS  tcp     80      80      FROM    CIDR    0.0.0.0/0       ingress
$ rds-authorize-db-security-group-ingress cms-db \
  --ec2-security-group-name  cms-app \
  --ec2-security-group-owner-id 376158489050
SECGROUP  cms-db  db SG for cms (port 3306)
      EC2-SECGROUP  cms-app  sg-e1bacee0  376158489050  authorizing

MySQL DB用Parameter Groupを作成する

MySQLのデータベース設定ファイル(my.conf)にあたるパラメーターグループを作成します。パラメータグループを作成することで同じDB設定のRDSを複数作成することができるようになります。

なおパラメータグループ名(cms-db-mysql55)は、DBの種類(mysql)とバージョン(5.5)が分かるよう命名するのがコツだそうです。

$ rds-create-db-parameter-group cms-db-mysql55 \
  --db-parameter-group-family mysql5.5 \
  -d "db PG for cms(mysql-5.5)"
DBPARAMETERGROUP  cms-db-mysql55  mysql5.5  db PG for cms(mysql-5.5)

DBインスタンスを作成する

作成したセキュリティグループとパラメータグループを指定し、RDSインスタンス "cmsdb" を作成します。
なお以下で指定している "cmsdb" は「RDSのインスタンス名」のことで、--db-nameで指定している "mydb" はMySQLのデータベース名のことです。後ほどEC2上にあるMySQLデータをRDSにインポートしますが、その際に指定するのはMySQLデータベース名である "mydb" の方なのでご注意ください。

コマンドを実行してから実際に作成され使えるようになるまでに5分程度かかります。しばらくお待ちください。

$ rds-create-db-instance cmsdb \
  --db-security-groups cms-db \
  --db-instance-class db.t1.micro \
  --engine mysql \
  --db-parameter-group-name cms-db-mysql55 \
  --db-name mydb \
  --master-username awsuser \
  --master-user-password mypassword \
  --allocated-storage 5 \
  --backup-retention-period 0
DBINSTANCE  cmsdb  db.t1.micro  mysql  5  awsuser  creating  1  ****  n  5.5.27  general-public-license
      SECGROUP  cms-db  active
      PARAMGRP  cms-db-mysql55  in-sync
      OPTIONGROUP  default:mysql-5-5  in-sync

RDSインスタンスの状態は rds-describe-db-instances コマンドで確認することができます。"creating" が "available" になれば作成完了です。

$ rds-describe-db-instances cmsdb
DBINSTANCE  cmsdb  2013-02-15T13:51:23.868Z  db.t1.micro  mysql  5  awsuser  available  cmsdb.c9cxowny4ezp.ap-northeast-1.rds.amazonaws.com  3306  ap-northeast-1c  0  n  5.5.27  general-public-license
      SECGROUP  cms-db  active
      PARAMGRP  cms-db-mysql55  in-sync
      OPTIONGROUP  default:mysql-5-5  in-sync

(EC2上のDBデータをRDSに移行する)

EC2インスタンスにログインしてMySQLデータベースをバックアップ&RDSにリストアします。作業内容自体は一般的なMySQLの操作と変わりません。
データインポート時に指定するユーザ名とパスワードはRDSインスタンス作成時に指定した--master-username / --master-user-password のことです。また接続先ホスト名は rds-describe-db-instances コマンドで表示される「エンドポイント」と呼ばれるホスト名を指定します。インポート先のデータベースはRDSインスタンス作成時に --db-name で指定したデータベース名になります。

$ mysqldump -uroot -pXXXXXXXX ablogcms > backup.sql
$ mysql -uawsuser -pmypassword -h cmsdb.c9cxowny4ezp.ap-northeast-1.rds.amazonaws.com mydb < backup.sql 

インポートが完了したらEC2上のablogの設定ファイルを修正して、接続先データベースを変更します。
また以降の作業で混乱しないようにEC2上のMySQLプロセスは止めてしまいましょう。

$ sudo service mysqld stop
Stopping mysqld:                                           [  OK  ]
$ sudo chkconfig mysqld off
$ sudo chkconfig --list mysqld
mysqld         	0:off	1:off	2:off	3:off	4:off	5:off	6:off

スケールアウトできるようAMIを作成する

ablogが動いているEC2インスタンスからカスタムAMIを作成します。AMIを作成しておいて、EC2インスタンス作成時にこのAMIを指定することで同じ設定のサーバをいくつでも作成することができるようになります。

$ ec2-create-image --name cms-app-image -d "ablog custom AMI image" i-a35e75a0
IMAGE   ami-dd9116dc

$ ec2-describe-images 
IMAGE   ami-dd9116dc    376158489050/cms-app-image      376158489050    available       private         x86_64  machine aki-44992845                    ebs      paravirtual     xen
BLOCKDEVICEMAPPING      EBS     /dev/sda1               snap-9ba164b8   8       true    standard

Phase-3 異なるAZにEC2インスタンスを立ち上げELBで負荷分散する

カスタムAMIからEC2インスタンスを起動する

先程作ったカスタムAMIを指定してEC2インスタンスを新たに起動します。さらにここでは1つ目とは異なるアベイラビリティゾーンで起動しています。
(1つ目のEC2インスタンスがap-northeast-1bで作成されていたので、ここではap-northeast-1aを指定しています)

$ ec2-describe-availability-zones 
AVAILABILITYZONE        ap-northeast-1a available       ap-northeast-1  
AVAILABILITYZONE        ap-northeast-1b available       ap-northeast-1  
AVAILABILITYZONE        ap-northeast-1c available       ap-northeast-1  
$ ec2-run-instances \
  --group cms-app \
  --instance-type t1.micro \
  --instance-count 1 \
  --key <key-pair-name> \
  --availability-zone ap-northeast-1a \
  ami-dd9116dc

ロードバランサーを作成する

ELB "cms-lb" を作成します。ロードバランシングされるEC2インスタンスがあるリージョンとアベイラビリティゾーンを明示的に指定する必要があります。

$ elb-create-lb cms-lb \
  --listener "lb-port=80,instance-port=80,protocol=http" \
  --availability-zones ap-northeast-1a,ap-northeast-1b \
  --region ap-northeast-1
DNS_NAME  cms-lb-XXXXXXXXX.ap-northeast-1.elb.amazonaws.com

ロードバランサーインスタンスを関連づける

ここでもリージョンは明示的に指定する必要があります。

$ elb-register-instances-with-lb cms-lb --region ap-northeast-1 --instances  i-a35e75a0,  i-af2209ac  
INSTANCE_ID  i-af2209ac
INSTANCE_ID  i-a35e75a0

$ elb-describe-instance-health cms-lb --region=ap-northeast-1
INSTANCE_ID  i-a35e75a0  InService  N/A  N/A
INSTANCE_ID  i-af2209ac  InService  N/A  N/A

ロードバランサが作成できたら、ロードバランサ経由でEC2インスタンスにアクセスしてみます。
http://cms-lb-XXXXXXXXX.ap-northeast-1.elb.amazonaws.com/

試しに片方のapacheを停止させてみましょう。ヘルスチェックで一方がOutOfServiceになっていても、ablogは表示されていればOK。

(一方のablogが動いているEC2インスタンスにsshでログインする)
$ sudo service httpd stop
Stopping httpd:                                            [  OK  ]

(次に作業用インスタンスからヘルスチェックを行う → どちらかがOutOfServiceになっているはず)
$ elb-describe-instance-health cms-lb --region=ap-northeast-1
INSTANCE_ID  i-a35e75a0  OutOfService  Instance has failed at least the UnhealthyThreshold number of health checks consecutively.  Instance
INSTANCE_ID  i-af2209ac  InService     N/A                                                                                         N/A

後始末

ELBやRDSはそのままにしておくと時間で課金されるので実験が終わったら削除しておくのを忘れないでください。

ELBの削除

$ elb-delete-lb cms-lb --region ap-northeast-1
    
    Warning: Deleting a LoadBalancer can lead to service disruption to any
    customers connected to the LoadBalancer. Are you sure you want to delete
    this LoadBalancer? [Ny]y
OK-Deleting LoadBalancer

EC2とEIPの削除

$ ec2-disassociate-address 54.249.238.6
ADDRESS 54.249.238.6
$ ec2-release-address 54.249.238.6
ADDRESS 54.249.238.6
$ ec2-terminate-instances i-a35e75a0
INSTANCE        i-a35e75a0      running shutting-down
$ ec2-terminate-instances i-af2209ac
INSTANCE        i-af2209ac      running shutting-down

AMI、スナップショットの削除

AMIを作成する際には自動でスナップショットも作成されているので、AMIだけでなくスナップショットも削除します。

AMIを削除します。

$ ec2-deregister ami-dd9116dc
IMAGE   ami-dd9116dc

スナップショットを削除します。

$ ec2-describe-snapshots 
SNAPSHOT        snap-9ba164b8   vol-be05909c    completed       2013-02-15T14:32:10+0000        100%    376158489050    8       Created by CreateImage(i-a35e75a0) for ami-dd9116dc from vol-be05909c
$ ec2-delete-snapshot  snap-9ba164b8  
SNAPSHOT        snap-9ba164b8

RDSの削除

DBインスタンスの削除処理には時間がかかるので、rds-delete-db-instance後すぐにはパラメータグループを削除できません。
DBセキュリティグループ(cms-db)でEC2セキュリティグループ(cms-app)を参照しているので、先にcms-dbを削除してからcms-appを削除してください。

$ rds-delete-db-instance cmsdb -f --skip-final-snapshot
DBINSTANCE  cmsdb  2013-02-05T13:33:24.196Z  db.t1.micro  mysql  5  awsuser  deleting  cmsdb.c9cxowny4ezp.ap-northeast-1.rds.amazonaws.com  3306  ap-northeast-1a  1  n  5.5.27  general-public-license
      SECGROUP  cms-db  active
      PARAMGRP  cms-db-mysql55  in-sync

(RDSインスタンスが削除されるまでしばらく時間がかかります)

$ rds-delete-db-parameter-group cms-db-mysql55 -f
$ rds-delete-db-security-group cms-db -f
$ ec2-delete-group cms-app
RETURN  true