固定IPでないEC2のpublic DNSを追従してSSHする

# 概要
EC2では、固定IPを設定しない場合、停止・起動するとIPアドレスとpublic DNSが割り振り直されます。したがって、そのままでは毎回コンソールやコマンドラインからIPやDNSを調べて接続するという作業が必要になります。固定IPを設定するとかDNSを設定するとかすればいいのですが、もちろん財布との相談になります。お小遣いが少ないと、ドキドキして眠れないですよね。

ということでいい感じに自動で割り振られるpublic DNSを追従してSSHするやり方を考えてみました。


## 環境

* Windows10
* Debian stretch (Windows Subsystem for Linux)

```bash
kotaro@debian:~$ cat /etc/debian_version
9.4
```
* EC2
  * t2.nano 
  * AMI: ubuntu server 16.04


## 方法
今回は次の方法でやってみました。他のやり方は検討してません。

* ~/.ssh/config 適当な名前を決めてec2接続用の設定を書いておく
* 何らかの方法でEC2インスタンスのpublic DNSをとってくる
* sedなりperlなりでとってきたpublicDNSで ~/.ssh/configを置き換える
* 決めておいた名前に対してsshする

割と簡単ですね。
## やってみる
### ~/.ssh/configの設定

こんな感じで設定を書きます。

```config
kotaro@debian:~$ cat ~/.ssh/config
Host myserver
    HostName YOUR_PUBLIC_DNS
    User ubuntu
    IdentityFile ~/.ssh/myserver.pem
```

YOUR_PUBLIC_DNSのところにとってきたDNSを入れるイメージです。

試しに、今立ち上げたインスタンスのpublic DNSを入れてつないでみます。

```bash
kotaro@debian:~$ ssh myserver1
Welcome to Ubuntu 16.04.4 LTS (GNU/Linux 4.4.0-1062-aws x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  Get cloud support with Ubuntu Advantage Cloud Guest:
    http://www.ubuntu.com/business/services/cloud

0 個のパッケージがアップデート可能です。
0 個のアップデートはセキュリティアップデートです。


Last login: Sun Jul  8 17:08:15 2018 from 211.135.251.99
ubuntu@myserver1:~$
```

繋がりました。

### EC2インスタンスのPublic DNSをとってくる
awscliを使います。
#### awscliインストール
https://docs.aws.amazon.com/cli/latest/userguide/installing.html を参考に接続元のPCにインストールします。

```bash
kotaro@debian:~$ pip install awscli --upgrade --user
```
インストールにはpython2.6以上、または3.3以上と pip(pip3)が必要です。

ホームディレクトリの `~/.local/bin` にインストールされました。
これでは実行できないので、PATHを通します。

```bash
kotaro@debian:~$ echo "export PATH=\"~/.local/bin/:${PATH}\"" >> ~/.bashrc
```
WSLのPATHには`/mnt/c/Program Files (x86)`など、括弧やスペースが入っている場合が多いので、`\"`は結構大事です。

インストールの確認をします。

```bash
kotaro@debian:~$ aws --version
aws-cli/1.15.53 Python/2.7.13 Linux/4.4.0-17134-Microsoft botocore/1.10.52
```
OKです。

続いてセットアップをします。


#### awscliのセットアップ
https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html
を参考に権限の設定をしていきます。
#### IAMの作成
AWSコンソールからIAM Management Consoleを開いて、IAMユーザを作成します。
少なくとも、EC2インスタンスを参照できる権限が必要ですが、必要に応じて作成・起動・削除などの権限を設定しても良いでしょう。
ここで作成したIAMユーザを利用してawsのサービスに接続するため、Access Key, Secret Keyをメモしておきます。
##### aws configure
awscliの権限設定を行います。

```bash
kotaro@debian:~$ aws configure
AWS Access Key ID [None]: YOUR_ACCESS_KEY
AWS Secret Access Key [None]: YOUR_SECRET_KEY
Default region name [None]: ap-northeast-1
Default output format [None]: text
```
YOUR_ACCESS_KEY / YOUR_SECRET_KEYには上記で作成したIAMユーザのAccess Key, Secret Keyを設定します。Default Region nameは、東京リージョンであればap-northeast-1です。
動作確認

```bash
kotaro@debian:~$ aws ec2 describe-regions --output table
----------------------------------------------------------
|                     DescribeRegions                    |
+--------------------------------------------------------+
||                        Regions                       ||
|+-----------------------------------+------------------+|
||             Endpoint              |   RegionName     ||
|+-----------------------------------+------------------+|
||  ec2.ap-south-1.amazonaws.com     |  ap-south-1      ||
||  ec2.eu-west-3.amazonaws.com      |  eu-west-3       ||
||  ec2.eu-west-2.amazonaws.com      |  eu-west-2       ||
||  ec2.eu-west-1.amazonaws.com      |  eu-west-1       ||
||  ec2.ap-northeast-2.amazonaws.com |  ap-northeast-2  ||
||  ec2.ap-northeast-1.amazonaws.com |  ap-northeast-1  ||
||  ec2.sa-east-1.amazonaws.com      |  sa-east-1       ||
||  ec2.ca-central-1.amazonaws.com   |  ca-central-1    ||
||  ec2.ap-southeast-1.amazonaws.com |  ap-southeast-1  ||
||  ec2.ap-southeast-2.amazonaws.com |  ap-southeast-2  ||
||  ec2.eu-central-1.amazonaws.com   |  eu-central-1    ||
||  ec2.us-east-1.amazonaws.com      |  us-east-1       ||
||  ec2.us-east-2.amazonaws.com      |  us-east-2       ||
||  ec2.us-west-1.amazonaws.com      |  us-west-1       ||
||  ec2.us-west-2.amazonaws.com      |  us-west-2       ||
|+-----------------------------------+------------------+|
```
通っているようです。

#### public DNSを取得する
`aws ec2` コマンドでできることは、https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html この辺に詳しいです。
調べてみると、public DNSを取得するには `aws ec2 describe-instances`が使えそうなことがわかりました。

PublicDNSを取得するには、

```bash
kotaro@debian:~$ aws ec2 describe-instances --filters "Name=tag:Name,Values=myserver1"  --query 'Reservations[0].Instances[0].PublicDnsName'
ec2-13-113-192-138.ap-northeast-1.compute.amazonaws.com
```
こんな感じ。
instance-idではなく、EC2のタグに設定したホスト名でデータを取得したかったので、`--filters`オプションを使ってタグ名で絞り込むようにしています。`--query`オプションは欲しいフィールドだけを指定できるのでとても便利です。

これで、起動済みのインスタンスのpublicDNSを取得できました。

### ssh configを書き換える
勉強がてらsedでやってみました

```bash
sed -i -e "N;s%\(Host myserver1.*HostName \).*$%\1ec2-13-113-192-138.ap-northeast-1.compute.amazonaws.com$%" ~/.ssh/config
```


事前に決めた名前(ここではmyserver1)で~/.ssh/configを探して、見つけた行の下にある最初のHostNameを置き換えます。

### sshしてみる
ここまでで、~/.ssh/configはいい感じに書き換えられているはずなので、試しにsshしてみます。

```bash

kotaro@debian:~$ ssh myserver1
The authenticity of host 'ec2-18-182-5-211.ap-northeast-1.compute.amazonaws.com (18.182.5.211)' can't be established.
ECDSA key fingerprint is SHA256:wJxkhBB3q7Wauzt9e5Va0zJ/LEDaQNS7HAlDvwpeLmg.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'ec2-18-182-5-211.ap-northeast-1.compute.amazonaws.com,18.182.5.211' (ECDSA) to the list of known hosts.
Welcome to Ubuntu 16.04.4 LTS (GNU/Linux 4.4.0-1062-aws x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  Get cloud support with Ubuntu Advantage Cloud Guest:
    http://www.ubuntu.com/business/services/cloud

5 個のパッケージがアップデート可能です。
0 個のアップデートはセキュリティアップデートです。


Last login: Sat Jul 21 07:55:32 2018 from 125.198.153.183
ubuntu@myserver1:~$
```

勝った！

## ツール化
目的は気軽にec2にsshすることなので、↑を1ファイルにまとめました。
起動してなかったらついでにインスタンスも起動するようにしています。
https://github.com/ichihara-3/easy2ssh


## 後日談
Vagrantでec2のプロビジョニングとか、`vagrant ssh`とかできるらしいことを知ったので、それを使ってみようかと思ってます。
github: https://github.com/mitchellh/vagrant-aws

詳しそうな記事: https://qiita.com/hmuronaka/items/b96aeb8179a4c74a4f9e