rnsshとec2sshでEC2への快適ssh接続

EC2でインスタンスが多く稼働していて、sshするときに名前を覚えたり、追加削除したときにssh configを修正したりと、面倒な部分があると思います。その手間をできるだけ減らすことができます。

## ツール

### [rnssh](https://github.com/reiki4040/rnssh)

私の作ったツールで、EC2からインスタンス情報を持ってきて、pecoと同じように選択して、sshログインできるツールです。goでできてます。動作はMacOSのみ。
ssh configは、場合によっては自分でいじらないといけないので、その部分を次のec2sshを使ってカバーします。

### [ec2ssh](https://github.com/mirakui/ec2ssh)

Cookpadのmirakuiさん作のツールで、EC2の情報を持ってきて、それをもとに`~/.ssh/config`に接続設定を出力してくれます。

## インストールと準備

### AWSアクセスキー

rnssh,ec2ssh共にAWSのアクセスキーが必要になるので、発行して設定します。`~/.aws/credentials`もしくは、環境変数にアクセスキーを設定します。

``` ~/.aws/credentials
[default]
aws_access_key_id=your_key_id
aws_secret_access_key=your_secret
```

または

``` ~/.bashrcなど
export AWS_ACCESS_KEY_ID=your_key_id
export AWS_SECRET_ACCESS_KEY=your_secret
```

### rnssh

homebrew対応してます。

```
brew tap reiki4040/rnssh
brew install rnssh
```

もしくは、リリースからアーカイブをダウンロードして、PATHを通してください。
https://github.com/reiki4040/rnssh/releases
書いている時点では0.3.3

加えて、`~/.bashrc`などに、デフォルトのリージョンを指定します。

``` ~/.bashrcなど
export AWS_REGION=ap-northeast-1
```

実行時に`-r`でも指定可能です

### ec2ssh

```
gem install ec2ssh
  # 環境によってはsudo
```

書いている時点では3.0.3


## ユースケース

### 全インスタンスPublicIPを持っているケース

```
[Mac] --[ssh]--> [PublicIPを持つインスタンス]
```

#### ssh config

ec2sshの設定`~/.ec2ssh`のDSL部分を以下にする。(PublicIPでの接続設定)

``` ~/.ec2ssh
host_line <<END
Host <%= ip_address %>
  HostName <%= ip_address %>
  User your_user
  IdentityFile /path/to/your_ssh_key
END
```

設定後、`ec2ssh update`

```
ec2ssh init
  # 初回のみinit
ec2ssh update
```

#### rnssh

```
rnssh [filter_query]
```

デフォルトはPublicIPを使って接続します。稼働しているインスタンスのInstanceId, NameTag, PublicIPが表示されます。

```
which do you choose the instance? > 
i-XXXXXXXX    production.web.1    54.X.Y.A
i-XXXXXXXX    production.web.2    54.X.Y.B
i-XXXXXXXX    production.web.3    54.X.Y.C
```

あとは選択するとそのサーバにsshログインできます。
filter_queryを指定すると、稼働中のインスタンスからさらにその文字列で絞り込めます。

ユーザや鍵を変えたい場合は、以下のように指定することで可能です。

```
rnssh -i /path/to/ssh_key user@filter_query
```

### VPNで接続しているケース(PrivateIPで繋がる)

```
[Mac] --[VPN]--> [PrivateIPだけを持つインスタンス]
```

例：10.10.10.xのネットワークにはPrivateIPで接続可能な環境の場合

#### ssh config

`~/.ssh/config`にワイルドカードでまとめて設定する

``` ~/.ssh/config
Host 10.10.10.*
  HostName 10.10.10.*
  User your_user
  IdentityFile /path/to/your_ssh_key
```

もしくはec2sshの設定`~/.ec2ssh`のDSL部分を以下のように`private_ip_address`にする。(PrivateIPでの接続設定)

``` ~/.ec2ssh
host_line <<END
Host <%= private_ip_address %>
  HostName <%= private_ip_address %>
  User your_user
  IdentityFile /path/to/your_ssh_key
END
```

設定後、`ec2ssh update`

```
ec2ssh init
  # 初回のみinit
ec2ssh update
```

#### rnssh

`-p`オプションをつけて、PrivateIPモードで動かします。

```
rnssh -p filter_query
```

毎回`-p`を付けるのは面倒なので、デフォルト動作を環境変数を使って変更します。
`~/.bashrc`などで、

``` ~/.bashrcなど
export RNSSH_HOST_TYPE=private
```

もしくは、`alias rnssh="rnssh -p"`でも構いません

## 踏み台サーバを経由する場合

VPNがない場合は、踏み台サーバを用意することで、PrivateIPのみのサーバにもsshできます。

```
[Mac] -> [PublicIPを持っているインスタンス] -> [VPC内のPrivateIPしかないインスタンス]
```

### ssh config

```
# 踏み台へのPublicIPでの接続設定
Host 54.X.Y.Z
  HostName 54.X.Y.Z
  User your_fumidai_user
  IdentityFile /path/to/your_fumidai_ssh_key

# VPC内、10.10.10.*に対して、踏み台経由でsshする設定
Host 10.10.10.*
  HostName 10.10.10.*
  User your_user
  IdentityFile /path/to/your_ssh_key
  ProxyCommand ssh your_fumidai_user@54.X.Y.Z -W %h:%p
```

### rnssh

VPNの場合と同様に、-pを使って接続できます。(ssh configの設定でトンネルされます)
※この場合は10.10.10.*のインスタンスを選択した場合接続できます。

```
rnssh -p
```

## インスタンスに変更があった場合

インスタンスの追加や削除があった場合、rnssh/ec2sshどちらも更新作業が必要です。rnsshは`-f`オプションで、EC2の情報を再度取りに行きます。通常はそのあとローカルにキャッシュしたファイルから情報を取ります。

```
# ec2ssh使っている場合は先に`~/.ssh/config`を更新
ec2ssh update

# rnssh
rnssh -f
```

これだけで済みます。手で`~/.ssh/config`いじる必要なし、ec2のインスタンスのIP調べる必要もないです。

## 雑感

昨今はansible/chefなどのプロビジョニングツールがあり、直接sshして作業することは減ったかなと思いますが、なんだかんだまだsshしていじることは多いです。また、サーバを作り直したりすることも多いと思いますが、rnsshとec2sshを使うことで、サーバの増減に対しての手間を減らすことができます。

もともとシェルで作っていましたが、使ってみたら思いの外便利だったので、go化までやって配布を楽にしてみました。

### 注意点

- rnsshは、sshログインのみで、コマンドの実行は対応していません。(例:`ssh user@host ls -al`)
- 選択部分は少し古いpecoを改造して呼び出しているので、若干挙動が怪しい気がします。フィルタリングによって、選択肢の文字が消える不具合があります。
**->2015/11/09 追記 選択肢が消えるバグを修正したものを0.3.4としてリリースしました。**
- Windowsは未対応です。Linuxはコンパイルすれば動きそう。
- インスタンスを作ったり止めたりしたら必ず`rnssh -f`で再読み込み。