ec2-ssh に Public DNS 情報のキャッシュ機能を追加してみました

morikawaAWS, EC2, IAM, ssh, ツール

インフラグループの Morikawa です。今回は AWS EC2 のインスタンスに SSH ログインする際にちょっと便利なツールのご紹介です。

ちなみに AWS は初心者でして、最近時間を見つけてはちょっとずつ勉強してるところです。…で、使い始めて思ってしまったわけです。

  • EC2 (起動のたびにグローバルIP変わる) に SSH ログインするの毎度面倒くさいな、と…。 (もっと他に学ぶところはあるはずなんですが ^^;)

Web 上を探してみますと同じような不満を持ってる方はやっぱりいらっしゃいまして、以下のサイトで migrs さんが、EC2 上のインスタンスの名称を指定して SSH ログインできる ec2-ssh というツールを紹介して下さってます。ツールは GitHub Gist で公開されてます。

これはログインのたびに ec2-api-tools を介してインスタンスの名称と Public DNS の対応を自動取得してくれるツールです。単独で動くシェルスクリプトですのでセットアップも簡単で非常に便利です。ただ ログインのたびに API での Public DNS 情報の取得に数秒必要 のがどうも気になってました。

そんなわけで (ここが本題)、migrs さんの ec2-ssh を Fork して Public DNS 情報のキャッシュ機能を追加した ec2-ssh を作ってみました (こちらも Gist にて公開 してます)。今のところ CentOS 6.4 と Mac OS X 10.8.4 で動作確認してます。

既にオリジナルの ec2-ssh を利用されてる方や、ec2-api-tools を普段から利用している方は単にダウンロードして実行してもらえればサクッと使えると思います。今回の記事では、私のような AWS 初心者向けに関連ツールのセットアップも含めてまとめてみました。

目次

AWS IAM ユーザの作成とアクセスキーの発行

まず、AWS IAM (Identity and Access Management) で ec2-api-tools 用のユーザおよびアクセスキーを発行します。IAM ユーザを作成せずとも AWS アカウントのルートアカウントのアクセスキーは作成可能ですが、今回の ec2-ssh では基本的に参照にしか ec2-api-tools を使いませんので、AWS サービスに対して読取のみ許可されたユーザとアクセスキーを用意します。

なお、ec2-ssh は読取以上の権限があれば良いので、操作権限などが必要になれば後述の IAM 管理画面で適宜権限付与などして下さい。

IAM ユーザ作成とアクセスキー発行

AWS IAM の管理画面 にアクセスし、左ペインの [Users] をクリックします。

ユーザ管理画面に移動するので、[Create New Users] でユーザ作成を開始します。

ReadOnly ユーザを作ります。[Generate an access key for each User] にはチェックを入れ、[Create] をクリックします。

ユーザの作成と鍵が発行された旨が表示されます。ここで [Show User Security Credentials] をクリックします。

アクセスキーIDとシークレットアクセスキーが表示されます。

この2つのキーを手元に保存します。ここでは $HOME/.aws-access.key に保存することにします。

$ vi $HOME/.aws-access.key
# AWS IAM "ReadOnly" User Access Key
export AWS_ACCESS_KEY="xxxxxxxxxxxxxxxxxxxx"
export AWS_SECRET_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

なお、上記ファイルは bash で読み込む前提なので、他のシェルをお使いの場合はそのフォーマットに書き換えて下さい。

キーの保存が終わったら上記ウィンドウは閉じて下さい。うっかりキーを保管する前に閉じてしまった場合、そのシークレットアクセスキーは二度と入手できません。作成したキーは IAM 管理画面上から削除し、新たにキーを再発行して下さい。

IAM ユーザのポリシー設定

再びユーザ管理画面において、先ほど作成した ReadOnly ユーザを選択し、右ペインの [Permissions] タブを選択して、[Attach User Policy] をクリックします。

設定するポリシーの選択画面が表示されるため [Select Policy Template] から [Read Only Access] の [Select] をクリックします。

最後に設定の詳細が表示されるため [Apply Policy] でポリシーを適用します。

以上で IAM 管理画面からの設定は終了です。

ec2-api-tools のセットアップ

パッケージのインストールと基本設定 (CentOS 6.4 編)

まず、ec2-api-tools の動作 (およびインストール作業) に必要なパッケージをインストールします。

# yum install java-1.6.0-openjdk unzip

以下ではホームディレクトリ直下の ec2-api-tools ディレクトリにインストールする前提でセットアップします。

$ cd ~
$ curl -LO http://s3.amazonaws.com/ec2-downloads/ec2-api-tools.zip
$ unzip ec2-api-tools.zip
$ rm ec2-api-tools.zip
$ mv ec2-api-tools-* ec2-api-tools

次に ec2-api-tools 用の環境変数を設定します。以下は bash での例になります。~/.bashrc に以下の記載を加えます。

export JAVA_HOME="/etc/alternatives/jre"
export EC2_HOME="$HOME/ec2-api-tools"
export AWS_KEY_FILE="$HOME/.aws-access.key"
[ -f "${AWS_KEY_FILE}" ] && source ${AWS_KEY_FILE}
export PATH="$PATH:$JAVA_HOME/bin:$EC2_HOME/bin"

設定を読み込んでリージョン一覧を取得してみます。正常にリージョン一覧が取得できていれば OK です。

$ source ~/.bashrc
$ ec2-describe-regions
 
REGION  eu-west-1       ec2.eu-west-1.amazonaws.com
REGION  sa-east-1       ec2.sa-east-1.amazonaws.com
REGION  us-east-1       ec2.us-east-1.amazonaws.com
REGION  ap-northeast-1  ec2.ap-northeast-1.amazonaws.com
REGION  us-west-2       ec2.us-west-2.amazonaws.com
REGION  us-west-1       ec2.us-west-1.amazonaws.com
REGION  ap-southeast-1  ec2.ap-southeast-1.amazonaws.com
REGION  ap-southeast-2  ec2.ap-southeast-2.amazonaws.com

パッケージのインストールと基本設定 (Mac OS X 10.8.4 編)

以下で紹介する方法は Homebrew がセットアップ済みであることが前提です。Homebrew のセットアップがまだであれば以下を参考にセットアップして下さい。(Homebrew は非常に便利ですので使ってない方は是非設定してみて下さい)

最終的に brew コマンドが利用できるようになり、以下の結果が返ってくれば OK です。

$ brew doctor
Your system is ready to brew.

まず、brew で ec2-api-tools パッケージをインストールします。

$ brew install ec2-api-tools

次に ec2-api-tools 用の環境変数を設定します。以下は bash での例になります。~/.bashrc に以下の記載を加えます。

export JAVA_HOME="/System/Library/Frameworks/JavaVM.framework/Home"
export EC2_HOME_BASE="/usr/local/Cellar/ec2-api-tools"
export EC2_HOME="$EC2_HOME_BASE/$(/bin/ls $EC2_HOME_BASE | /usr/bin/tail -1)/jars/"
export AWS_KEY_FILE="$HOME/.aws-access.key"
[ -f "${AWS_KEY_FILE}" ] && source ${AWS_KEY_FILE}

設定を読み込んでリージョン一覧を取得してみます。正常にリージョン一覧が取得できていれば OK です。

$ source ~/.bashrc
$ ec2-describe-regions
 
REGION  eu-west-1       ec2.eu-west-1.amazonaws.com
REGION  sa-east-1       ec2.sa-east-1.amazonaws.com
REGION  us-east-1       ec2.us-east-1.amazonaws.com
REGION  ap-northeast-1  ec2.ap-northeast-1.amazonaws.com
REGION  us-west-2       ec2.us-west-2.amazonaws.com
REGION  us-west-1       ec2.us-west-1.amazonaws.com
REGION  ap-southeast-1  ec2.ap-southeast-1.amazonaws.com
REGION  ap-southeast-2  ec2.ap-southeast-2.amazonaws.com

デフォルトリージョンの環境変数設定

次にデフォルトリージョンの環境変数を設定します。まず、ec2-describe-instances で EC2 の環境一覧を取得してみて下さい。

$ ec2-describe-instances

以下のように色々と情報が表示されれば OK ですが、何の出力もされない場合があります。

INSTANCE     i-d0dxxxxx  ami-173xxxxx  ip-xxx-xxx-xx-xx.ap-northeast-1.compute.internal ..
BLOCKDEVICE  /dev/sda1   vol-7f1xxxxx  2013-05-04T05:31:36.000Z     true
NIC          eni-fafxxx  subnet-4fxxx  vpc-4d8xxxx  704342xxxxx     in-use  ...

これは自分が使っているリージョンが、ec2-api-tools がデフォルトで参照する北米リージョン以外の場所にあるためです。自分のリージョンについては EC2 Management Console から確認できます。

リージョンごとの URL の一覧は上記の ec2-api-tools のセットアップ確認時に使用した ec2-describe-regions コマンドで確認できます。Tokyo がデフォルトリージョンであれば ap-northeast-1 となるため、~/.bashrc に以下の設定を追加します。

export EC2_URL=https://ec2.ap-northeast-1.amazonaws.com

再度確認し、インスタンスの一覧が取得できれば OK です。

$ source ~/.bashrc
$ ec2-describe-instances

INSTANCE     i-d0dxxxxx  ami-173xxxxx  ip-xxx-xxx-xx-xx.ap-northeast-1.compute.internal ..
BLOCKDEVICE  /dev/sda1   vol-7f1xxxxx  2013-05-04T05:31:36.000Z     true
NIC          eni-fafxxx  subnet-4fxxx  vpc-4d8xxxx  704342xxxxx     in-use  ...

ec2-ssh (キャッシュ機能追加版) のセットアップ

さて、ec2-api-tools の設定さえできてしまえばあとは簡単です。

まずは Gist に置いてあります ec2-ssh (キャッシュ機能追加版) のスクリプトをダウンロードします。オリジナル同様シェルスクリプト一個ですので、curl や wget などで手っ取り早く以下のようにダウンロードしてもらっても良いかと。

$ curl -LO https://gist.github.com/mo-ya/5788098/raw/80ce2cf079df1725db8ee69c16dcf6278210609b/ec2-ssh
$ chmod +x ec2-ssh

ec2-ssh は PATH が通ってるところに置いてください。

この ec2-ssh が参照する環境変数は以下の5つです。未設定でも使えますが、EC2_SSH_KEY_PATHEC2_SSH_DEFAULT_USER については設定しておいた方が便利と思います。

  • EC2_SSH_KEY_PATH:
    • EC2 アクセス時の秘密鍵のパス (ssh の -i オプションで指定するもの)
    • 未指定の場合は ssh コマンド同様、~/.ssh/ 以下の id_dsa, id_rsa がデフォルトとなります
  • EC2_SSH_DEFAULT_USER:
    • SSH アクセス時のユーザ
    • 未指定の場合は ssh コマンド同様、ec2-ssh 実行ユーザがデフォルトになります
  • EC2_SSH_HOST_CACHE:
    • Public DNS 情報をキャッシュするファイル
    • デフォルトだと ~/.ec2-ssh.hostcache となります
  • EC2_SSH_TIMEOUT:
    • SSH のタイムアウト値
    • リトライをすぐに行いたいので、デフォルトは短めの 2 秒にしてます
  • EC2_SSH_CACHE_DAY:
    • キャッシュの有効期限 (日で指定)
    • デフォルトは 1 日になります

まだ EC2 使い始めの私は以下のような設定にしてます。ec2-key.pem は EC2 インスタンスを Launch した際に紐付けたログイン用の秘密鍵です。Amazon Linux AMI で Launch したばかりのインスタンスに用意されているユーザ ec2-user を明示的に指定しなくてもログインできるようになってます。ここらへんは使う方それぞれで設定して頂ければ。

export EC2_SSH_DEFAULT_USER=ec2-user
export EC2_SSH_KEY_PATH=~/.ssh/ec2-key.pem

使い方

ec2-ssh のキャッシュ機能

キャッシュ機能付きの ec2-ssh も migrs さんのオリジナル ec2-ssh と同様 EC2 の Name タグに設定された名称 でアクセスします。EC2 Management Console の [Instances] が以下のような状態だったとします。

Demo01 にアクセスしたい場合は以下で OK です。大文字小文字は区別するのでご注意下さい。

$ ec2-ssh Demo01

初回は当然キャッシュがないので ec2-api-tools を使って Public DNS 情報を取得しに行きます。

[Load EC2 Information from Local Cache] ...
  Cache file is not found.
[Get EC2 Information from AWS] ... (wait a minutes)
[Connecting EC2] ...
Last login: ...
[ec2-user@ip-xx-xx-xx-xxx ~]$

さて、では一度ログアウトして再度ログインしてみます。今度は先ほどよりさっくりログインできるはずです。

$ ec2-ssh Demo01
 
[Load EC2 Information from Local Cache] ...
  Cache HIT: Demo01 => ec2-xx-xx-xx-xxx.ap-northeast-1.compute.amazonaws.com
[Connecting EC2] ...
Last login: ...
[ec2-user@ip-xx-xx-xx-xxx ~]$

キャッシュを読み込むため ec2-api-tools による問い合わせを行わないので、その分待ち時間が短くて済みます。

一方で、EC2 は一度停止してしばらくしてから起動するとグローバルIPが変わります (Elastic IP を使わない限り) 。その場合は (1) アクセス試行 (失敗する)、(2) ec2-api-tools から情報を再取得、(3) キャッシュの更新、を行うようにしてます。タイムアウトはデフォルトだと 2秒 になってます。短すぎる場合は EC2_SSH_TIMEOUT に適当なタイムアウト値 (秒) を設定して下さい。実際にタイムアウトして再試行する場合は以下のようなメッセージが出ます。

$ ec2-ssh Demo01
 
[Load EC2 Information from Local Cache] ...
  Cache HIT: Demo01 => ec2-xx-xx-xx-xxx.ap-northeast-1.compute.amazonaws.com
[Connecting EC2] ...
ssh: connect to host ec2-xx-xx-xx-xxx.ap-northeast-1.compute.amazonaws.com port 22: Operation timed out
WARNING: Cache Info may be obsoleted. Cache is ignored.
[Get EC2 Information from AWS] ... (wait a minutes)
[Connecting EC2] ...
Last login: ...
[ec2-user@ip-xx-xx-xx-xxx ~]$

はじめは上記仕様でまあ完成かなと思ってましたが、これって人様のサーバに SSH ログインかけてることもあるわけで、あまりお作法良くないよな…、とちょっと考えなおしまして、キャッシュの有効期限 を設けるようにしました。デフォルトは 1 日 になってます。短い場合は EC2_SSH_CACHE_DAY に日数を設定することで延ばすことができます。キャッシュが期限切れの場合は以下のようなメッセージが出て、ec2-api-tools で Public DNS 情報を取得しに行きます。

$ ec2-ssh Demo01
 
[Load EC2 Information from Local Cache] ...
  Cache OLD: older than 1 day [20130706104937]: Demo01 => ec2-xx-xx-xx-xxx.ap-northeast-1.compute.amazonaws.com
[Get EC2 Information from AWS] ... (wait a minutes)
[Connecting EC2] ...
Last login: ...
[ec2-user@ip-xx-xx-xx-xxx ~]$

とりあえず使い方については以上になります。

キャッシュの消し方

キャッシュは EC2_SSH_HOST_CACHE に設定されたファイル (デフォルトは ~/.ec2-ssh.hostcache) に以下のようなフォーマットで保存されています。

$ cat ~/.ec2-ssh.hostcache
 
Demo03#2  ec2-xx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com  201307xxxxxxxx
Demo03#1  ec2-xx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com  201307xxxxxxxx
Demo03#3  ec2-xx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com  201307xxxxxxxx
Demo02#1  ec2-xx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com  201307xxxxxxxx
Demo01#1  ec2-xx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com  201307xxxxxxxx
Demo02#2  ec2-xx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com  201307xxxxxxxx

ファイルごと消せばキャッシュが全部クリアされますし、行単位で消せばそのホスト情報のキャッシュだけクリアできます。

オリジナルの ec2-ssh の使い方 (参考情報)

以降の話は migrs さんのオリジナル ec2-ssh の仕様そのままなので Amazon EC2 で SSH するなら ec2-ssh が便利 – m.igrs.jp に書いてありますが、一応補足します。

「同じ名前の複数のインスタンスにはどう区別してログインするのか?」については #<順番> を付与します。具体的には以下のような感じです。順序は EC2 Management Console の [Instances] にデフォルトで表示される順番になります。

$ ec2-ssh Demo03#1
 
$ ec2-ssh Demo03#2
 
$ ec2-ssh Demo03#3

ec2-ssh に渡したオプションがそのまま ssh コマンドに引き継がれるようになってますので、以下のような使い方ができます。

$ ec2-ssh hogehoge@Demo02
 
$ ec2-ssh -L 8080:127.0.0.1:80 Demo03#3
 
$ ec2-ssh Demo01 vmstat 1
$ ec2-ssh Demo02 -t top

 

ヘルプ追加しておきました

今回作った ec2-ssh キャッシュ機能追加版ではヘルプを表示できるようにしておきました。ec2-ssh を引数なしで実行すると ヘルプメッセージキャッシュ情報 を表示できますので参考にして下さい。

$ ec2-ssh
 
# [ec2-ssh] Usages
 
  Basic Usage
    $ ec2-ssh web1
    $ ec2-ssh jonny@web1
 
  Access Same Name Instances (#1, #2 ...)
    $ ec2-ssh web#3
 
  Port Fowarding
    $ ec2-ssh -L 8080:127.0.0.1:80 web1
 
  Command direct execution
    $ ec2-ssh web1 ls -la
    $ ec2-ssh web1 tail -f /var/log/nginx/access.log
    $ ec2-ssh web1 vmstat 1
    $ ec2-ssh web1 -t top
    $ ec2-ssh web1 -t sudo service nginx restart
 
# [ec2-ssh] Cache Lists (in "~/.ec2-ssh.hostcache")
Demo03#2  ec2-xx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com  201307xxxxxxxx
Demo03#1  ec2-xx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com  201307xxxxxxxx
Demo03#3  ec2-xx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com  201307xxxxxxxx
Demo02#1  ec2-xx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com  201307xxxxxxxx
Demo01#1  ec2-xx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com  201307xxxxxxxx
Demo02#2  ec2-xx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com  201307xxxxxxxx

おわりに

以上、AWS の勉強からいつの間にか脇道に逸れて、人様のスクリプトに機能追加してしまいました、というお話でした。たぶんもっとバリバリ使ってる人たちはこんなもの使わずになんかしらノウハウあるんだろうなぁとは思うんですが…。賢い方法がありましたら教えてもらえますと幸いです。

さて、それではまた勉強を再開しようと思います。^^;

参考サイト

morikawaAWS, EC2, IAM, ssh, ツール

Posted by morikawa