うえきのブログ

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

とあるJAWSUG懇親会で聞かせてもらった地方インフラエンジニアの働き方についての話

Q.クラウドやAWSの知名度は?

東京での知名度は高い。大阪でも知らない人はいたりする。


東京で勉強会開くとすぐに席が埋まる。クラウド熱はやっぱすごい。

Q.AWSはどんなお客さんが使ってる?

ソーシャルゲームとか。


東芝が開発した医療カルテをS3へ保存するとか
http://aws.amazon.com/jp/solutions/case-studies/toshiba-medicalsystems/


最近システム開発するときは「まずはAWSで構築する」ことを前提に考えるようになってきた。


お客さんから「AWSで」と指定されることも増えてる。


Q.個人情報とかセキュリティ的には問題ないの

S3は暗号化されて管理されているし。
医療カルテのケースでは東芝の独自暗号化されたものが保存されている。
(上記URLで紹介されているDICOMのこと)


Q.課金は?突然予定外の支払いとか怖くない?

ある程度支払い予測ができる規模なら問題ない。


リスク分を月々多めにもらっておいて月定額にするってビジネスはいいかも。でも顧客数ある程度多くないと(リスク分散として)厳しいと思う。


Q.クラウドっていうと他にもさくらやニフティなんかあるけどAWSとの違いは

EC2とか仮想マシンだけで比べたら変わらない。


AWSの強みはその周辺の多数のサービスが充実していること。SESとかメール配信にすごく便利。


Q.AWSになることでエンジニアには何が必要になる

基本的なサーバ管理の知識はいままでと変わらない。いろんなサービスをどう組み合わせるかって知識は必要。


Q.ハードが不要になりクラウドでサーバを持つってことは現地常駐開発がなくなるってこと? 地方のエンジニアの仕事は東京にとられちゃうの?

東京でも地方のインフラが管理できるので東京に仕事を持ってかれる可能性はあるだろう。


けど逆に地方で東京の仕事ができって考えることもできるよね。実際に地方にいながら東京の仕事やってるよ。


神戸の会社(※デジタルキューブ https://www.digitalcube.jp/)の社員は地方に点在して仕事してる。
(たぶんこのこと→ http://bloggingfrom.tv/wp/2012/05/13/7504


Q.エンジニアとして技術向上の意識を高く持つためには?

東京方面にアンテナをはって、自分のいる位置を意識すること。
AWSが流行ってるから使わなきゃいけないわけじゃなく、そういう事を知りつつ自分の立ち位置を知ることが大事だと思う。


刺激を受けることが大事。
刺激を受けることが大事。
刺激を受けることが大事。(大事なことなのでry


Q.刺激どうやって受けよう?

勉強会に参加したり。セミナーに参加したり。



QPstudyはいいよ。適度にゆるくて。
https://sites.google.com/site/qpstudy/


今度あるJAWS Daysにでてみるのがいいと思う。LT枠30くらいあって、まだ空きあるよ。


結論:地方のエンジニアのみんな!JAWS Days 行こうぜ!!

http://jaws-ug.jp/jawsdays2013/
http://jaws-ug.jp/jawsdays2013/

AWS EC2でaws-sdk-rubyとvim使う時に最低限設定しておくもの・・・をchefで設定してみた

Cookbookとかレシピを作成する

$ sudo gem install chef
$ knife config
(すべて初期値のままで良いのでエンターキーを押していく)
(~/.chef/knife に設定が書き出されるのでパスを追記する)
$ cat >> ~/.chef/knife.rb

file_cache_path "/tmp"
cookbook_path "/home/ec2-user/chef-solo/cookbooks"

$ knife cookbook create ec2_config
** Creating cookbook ec2_config
** Creating README for cookbook: ec2_config
** Creating CHANGELOG for cookbook: ec2_config
** Creating metadata for cookbook: ec2_config

ひとまず、いまの設定ファイルをままテンプレートとして置いておきます。設定ファイルの拡張子は ".erb" になります。

$ cp -pi ~/.screenrc cookbooks/ec2_config/templates/default/screenrc.erb
$ cp -pi ~/.vimrc cookbooks/ec2_config/templates/default/vimrc.erb

レシピはまずは簡単に2種類だけ設定してみます。

  • yum を使っていくつかのパッケージをインストールする
  • 上でコピーしたファイルをec2-userのホームディレクトリに展開する

レシピを書くにあたって AWS OpsWorks のgithubリポジトリにある opsworks_bundler を参考に(ほぼ丸パクリ)させてもらいました。
https://github.com/aws/opsworks-cookbooks

$ vi cookbooks/ec2_config/recipes/default.rb
#
# Cookbook Name:: ec2# Recipe:: default
#
# Copyright 2013, Kazuki Ueki
#
# All rights reserved
#

ec2_user  = 'ec2-user'
ec2_group = 'ec2-user'
if node[:bundler][:manage_package]
  gem_package "Installing Bundler #{node[:bundler][:version]}" do
    gem_binary node[:dependencies][:gem_binary]
    retries 2
    package_name "bundler"
    action :install
    version node[:bundler][:version]
  end
end

%w[libxml2-devel libxslt-devel libffi-devel git rubygems ruby-devel].each do |pkg_name|
  package pkg_name
end

template "/home/#{ec2_user}/.screenrc" do
  source 'screenrc.erb'
  user ec2_user
  group ec2_group
  mode 0644
end

template "/home/#{ec2_user}/.vimrc" do
  source 'vimrc.erb'
  user ec2_user
  group ec2_group
  mode 0644
end

うまく動くかテストしてみましょう。

$ sudo chef-solo -j ~/.chef/chef.json -c ~/.chef/knife.rb

特にエラーなく動いたらgithubにpushして別のEC2インスタンスでクリーンな状態で動かしてみます。

$ cd ~/chef-solo/cookbooks
$ git init .
$ git add .
$ git commit -m "Initial commit"
$ git remote add origin https://github.com/uekikazuki/ec2_config.git
$ git push -u origin master

別のEC2インスタンスに適用してみる

chefを入れるにもrubygemsやmakeパッケージが必要という鶏と卵な関係なので、そこは仕方なく手作業でインストールします。

$ sudo yum -y install git rubygems make gcc ruby-devel
$ sudo gem install chef --no-ri --no-rdoc

githubから作っておいたCookbookを取り寄せます。pull後のディレクトリは ~/.chef/cookbooks/ec2_config になります。

$ mkdir -p ~/.chef
$ cd .chef
$ git clone https://github.com/uekikazuki/ec2_config.git cookbooks

chef-solo を実行するためにファイルを2つ作成します。"chef-solo.rb" はgitで取ってきたCookbookのパスなどが書かれたコンフィグファイル、"ec2_config.json" はとってきたCookbookの中からどのレシピを実行するか(run_list)を指示したファイルです。

2つのファイルをchef-soloコマンドのオプションとして指定し実行します。

$ cat >> ~/.chef/chef-solo.rb

file_cache_path "/tmp"
cookbook_path "/home/ec2-user/.chef/cookbooks"

$ cat >> ~/.chef/ec2_config.json

{
  "run_list":["recipe[ec2_config]"]
} 

さあ!設定開始です!!パッケージをインストールするのでsudoで実行します。

$ sudo chef-solo -j ~/.chef/ec2_config.json -c ~/.chef/chef-solo.rb

画面に表示されるログにエラーがなければ成功です!
ホームディレクトリにドットファイルが作成されているか確認してみましょう。

$ ls -1a ~/.*rc
/home/ec2-user/.bashrc
/home/ec2-user/.screenrc
/home/ec2-user/.vimrc


成功しました!あとはchefを開発しているopscodeのドキュメント(特にPackagesのドキュメント)を読みながらレシピの書き方を覚えていきましょう。

2013-03-04 23:31 追記

  • chef のインストールには ruby-devel も必要なので yum の対象に追加
  • chef インストール時は --no-ri --no-rdoc でドキュメントはインストールしないように変更

AWS EC2でaws-sdk-rubyとvim使う時に最低限設定しておくもの

毎回毎回設定するたびに忘れるので。それこそchef使って自動化したいよね・・・

開発に必要なパッケージをインストールする。

$ sudo yum -y update
$ sudo yum -y groupinstall "Development tools"
$ sudo yum -y install libxml2-devel libxslt-devel libffi-devel
$ sudo yum -y install git rubygems ruby-devel
$ sudo gem install bundler

gitの設定をする。

$ git config --global user.name "Kazuki Ueki"
$ git config --global user.email ueki.kazuki@XXXXX.com

vimの設定をする。タブ幅=2と、コメント行で改行した時も次の行がコメントにならないようにだけしておきます。

$ cat ~/.vimrc
set softtabstop=2
set tabstop=2
autocmd FileType * setlocal formatoptions-=ro

追記(2013-02-26 23:00)

しばらく操作しないとsshが切られてしまうので時刻表示用にscreenも必要。

$ cat .screenrc 
escape ^t^t
shell /bin/bash
defencoding UTF-8
defhstatus "^E:^Et"
defscrollback 8195
term screen-256color-bce
zombie ^[
hardstatus alwayslastline "%{= rw} %H %{= wk}%-Lw%{= bw}%n%f* %t%{= wk}%+Lw %{= wk}%=%{= gk} %y/%m/%d %c "

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

EC2へのログインアカウントの制約にみる今後のサーバ運用の自動化の流れについて

最初に結論

  • AWS EC2インスタンスでは複数アカウントによるログインが行いにくくなっている
  • 人による作業は環境に差異が発生しやすくなるから
  • Capistrano,Chef,CloudFormation,OpsWorksなどを使って自動化しましょう

はじめに

いつもは普段使っているパソコンでEC2のインスタンスsshでログインしていろいろと作業をしていたのですが、ある日事情により人のパソコンを借りて作業の続きをすることがありました。ところがいざログインしようとした時、認証につかう秘密鍵ファイル(*.pem)が手元にないためログインできないことに気付きました。pemファイルの再ダウンロードはできないので別の秘密鍵を作成してインスタンスを作り直す必要がありました。

ちょっと出先で作業したい、といった場合の備えどうしておけばいいのでしょうか?

これまでのUnixサーバ運用的な考えでは

どこでも作業ができるようにするためには以下いずれかの対策が思いつきます。

  1. 秘密鍵のファイルをDropboxなどに置いて共有しておく
  2. EC2インスタンスで独自のアカウント管理を行い秘密鍵がなくてもログインできるようにしておく

1つ目の案は簡単で1人でやるには十分なのです。が、企業での利用など複数のサーバ管理者がいる場合にはすべての人で秘密鍵を共有するのでしょうか? セキュリティの問題からちょっと考えにくいですね。ならば2でいうアカウント管理を独自に管理していこう、となればいいのでしょうが、EC2インスタンスが10台とか100台規模になってきた場合に管理が大変になります。

これまでUnixを管理してきた人ならNISを利用したアカウントの一元管理を思いつくでしょう。ところがAWSではNISサービスを提供していないようです。なぜでしょう? EC2で独自NISサーバを構築すればいいのでしょうか?

AWSの機能不足と考えることもできますが、すでに多くのユーザに利用されているサービスです、ここは需要がないからととらえるのが妥当でしょう。つまりEC2に複数アカウントがなくても困らない運用する、これまでのUnix管理の常識にとらわれない、AWSの富豪的サーバ利用にあったやり方に考え方を変えてみる必要がある、と捉えてみることにしましょう。

補足

ちなみに当初IAM(Identity and Account Management)を使ってユーザ・グループを作成すればEC2サーバへのログインが管理できるのではないかと思い調べたのですが、IAMのFAQに書いてある通りできないそうです。

AWS Identity and Access Management FAQs
Q: ユーザーは、AWS ユーザー名およびパスワードを使用して、EC2 インスタンスSSH で接続できますか?


いいえ。IAM で作成されたユーザーのセキュリティ証明書は、EC2 のお客様のインスタンスには反映されません。お客様の EC2 インスタンスの認証は、お客様の責任下にあります。

AWSによるこれからサーバ運用

そもそもなぜログインが必要かというとサーバ上での作業が必要だからです。パッケージのインストールや設定ファイルの変更、アプリケーションのデプロイなどがこれにあたりますが、いままでこれらは人手による作業でした。

サービスが大きくなり負荷をさばくために、EC2インスタンスを増やしてスケールアウトさせる方式を採用したとしましょう。このとき重要なのは「各サーバが同じ設定であること」です。あるサーバで動くアプリが環境の違いのため別のサーバで動かず、苦労をしたという経験を、開発者なら何度かあるのではないでしょうか? サーバごとに微妙に設定が違ってしまうのは、人手で作業をしているため、サーバごとに設定漏れが発生してしまうためです。

それならばいっそsshによるログインを制限してはどうでしょう?というのがAWSでのアプローチだと思われます。人手でサーバ設定する機会を減らすことで、スケールアウト時に発生しうる問題を排除するわけです。

手作業による設定やデプロイをする代わりに、最近ではCapistranoやChefといったソフトを使い、これらの作業を自動化する流れが主流になりつつあります。EC2インスタンスを作成した後は、事前に決めた設定に従って自動的にサーバ環境を構築することで、サーバ間の差異がなくなるわけです。


AWSではCloudFormationというAWSの各種サービスと設定を組み合わせたテンプレートを作成できるインフラ構築サービスや、OpsWorksというアプリケーションデプロイのテンプレートサービスも提供しています。AWSを利用することを前提とした今後の運用方法は以下のような流れになるのでしょう。

  1. 試験的なソフト導入や設定修正は個々人ごとにEC2インスタンスを作成してそこで行う
  2. 設定が決まったらChefのレシピに反映する
  3. スケールアウト時にはChefを実行することでサーバに設定を適用する


以上、これからはサーバ運用についても人手から自動化へ考えを変えていく必要があるね、というお話でした。

補足

環境構築の自動化はなにもAWSを利用するときしかメリットがないわけではなありません。アプリケーション開発時には本番環境とは別に、開発環境や本番導入前の検証環境をもっている場合があると思います。もしかしたら仮想化技術を使って個人ごとに開発環境をもっているかもしれません。これら複数の環境を本番環境と一緒にする際にも環境構築の自動化ツールは有用だと思われます。

AMI (Amazon Machine Images) のVectorみたいなサービスについて

Amazon Web Service で提供されている仮想マシンサービスであるEC2(Elastic Compute Cloud)では、Amazon Machine Imagesという仮想マシンイメージの配布を行っています。

EC2で構築した環境をディスクイメージとして保存してAMIとして公開することが誰でもできて、その環境を使いたい人は公開されたAMIを選んで仮想マシンを作成し動かすことができる、というものです。

環境構築が難しいシステムをインストール・設定済みのものをAMIとして公開してくれている方が増えてきています。


AWSコンソールという管理画面からAMIを検索することができますが、現在のところお世辞にも使いやすい画面ではないし、検索に一致したAMIがどういう用途でなにが設定されたイメージなのかも分かりにくいです。(一応 Descriptionという説明欄はあるけど、すべてのAMIで記入されているわけではないし、一行コメントなので詳細まではわかりません)

現在は自分が設定した環境をAMIとして公開し、Twitterなどで「作ってみたから使ってみてね」とAMI IDを広めている状況のようです。


いずれはVector窓の杜のようにオススメAMIとか人気AMIとかがカテゴリ別にまとまってたりランキング形式で紹介されたりして、活発にAMIのやりとりがされるようになるのかなぁ、とそんなことを考えました。


そうなるとシステム構築を生業している企業は仕事がなくなっちゃうかもしれませんね・・・

2013-03-02 17:18 追記

Amazon Market PlaceのページではOS別や用途別の検索ができることを知りました。各EC2インスタンスごとの利用料金もみることができます(アプリ使用量+EC2使用量でもBIツールが月3000円から試せるとか(安い!)。現在英語ページだけですが日本(Tokyoリージョン)でも独自AMIが活発にやりとりされるようになるのが楽しみですね。

コマンドでの作業をオススメする理由

仕事柄、作業手順書をたくさん書くのですが、コマンドで作業できるものはなるべくコマンドで作業するようにして(もらって)います。GUIの手順書の方が見栄え的にも、知らない人からみた取っ付きやすさ的にも優れているとは思うのですが、コマンドでの作業をオススメするのには理由があります。

手順の再現がしやすい

手順書をみて作業するのが自分自身なら問題はないのですが、その作業に詳しくない人が作業する場合があります。業務移管の場合もあれば、深夜休日にトラブルが発生して電話越しに「とにかくこのコマンドを貼付けて実行してもらえればOK」というケースも結構あったりする(アプリの停止とか、データ取得とか)のでGUIだけでなくコマンドでもできる方法を手順として残しておくようにしています。

それと、作った手順書は一度書き終わった後に環境をまっさらにしてもう一度やり直し、手順に間違いや漏れがないか確認するようにしてるのですが、そんな時マウス操作よりもコマンドの方が確認がやりやすいってのも理由の一つです。

作業ログが残しやすい

作業するときには必ず作業ログを記録するようにしています。TeraTermならtelnetやsshでの作業を簡単に保存できます。最近のバージョンだと行単位で時刻を記録してくれる機能もあります。便利ですね。

他人が行った作業だけでなく自分が作業する場合にも「手順書通りにやったはずなのにうまくいかない」というケースがよくあります。大抵は作業を一つ飛ばしてしまっていたり、入力ミスしてしまったことが原因だったりするのですが、やってる本人は「手順書通りにやった」つもりなわけです。うまくいかなかった原因を調べる時には、まずその手順を疑うことになりますが、その時作業ログが残っていることは重要です。いつ、なにを実行したのか、どれ位時間がかかって、どんな結果が返ってきたのかがすべて記録されていますので原因を特定できる確率がずっと高くなります。

それと「手順書が間違っている」ことも(あってはいけないことなのですが)よくあります。職場で作った手順書だけでなく、製品マニュアルやベンダー作成の手順書でも間違っているケースが経験上多々あります。作業者による「手順書の読み間違え」もあります(root作業を一般ユーザで行っていたとか、その逆とか)。いずれにしても作業ログが残っていれば原因調査は比較的楽になりますのでログは残すように(残しやすいように)しておきましょう。

マウスでの作業でも作業記録が残せればいいんですけど、そういったソフトは聞いたことがありません。なにか良いソフトはないですかね。

手順書を残す手間がかからない

マウス操作を行う手順だと画面キャプチャが必要になる場合が多く、手順書作成に時間がかかってしまいます。キャプチャ画像を貼付けるだけでなくクリックしてもらいたいところを赤丸で囲んだりと色々加工も必要です。手順書作成に時間がかかると手順書を残すこと自体が億劫になってしまい、ついついすっぽかしてしまいがちになります。

コマンドベースで作業ログ、少なくとも実行したコマンドさえ残しておけば、数日後あるいは数ヶ月後に以前に行った作業を再度行うことができます。自分はその日に行った作業を日付付きのフォルダにテキストで保存しているのですが、過去にやったちょっとした作業をもう一度やらなきゃいけない、という時に何度も助かったことがあります。

まとめ

GUIでの操作は初めて操作する際には敷居が低くて良いのですが、繰り返し作業する場合には不向きな場合があります。最近はWebベースのコントロールパネルをブラウザで操作するアプリが増えてきたので、どうしても手順書がマウス操作主体になってしまうのですが、そのアプリの仕組みや用語、作業に慣れてきたら同じことがコマンドでもできないか調べるようにしましょう。


そして作業ログは必ず残すように!


2013-02-16 09:22 追記

作業をコマンドで実行できるようにしておけば、将来的に自動化しやすいってのも理由の一つですね。