AWSでJupyterHub (EC2)




# 概要
全体概要は，[AWSでJupyterHub (概要)](https://qiita.com/ryouka0122/items/af5004d17e0ac934e550) にあるので，参照してください．

ここでは，サーバとなるEC2の用意とEBSのマウント，UIの見方などを説明します．
セキュリティ周りの細かい制御（IAMやセキュリティグループなど）はあまり期待しないでもらえるとありがたいです．

# おしながき

* EC2インスタンスの作成
    * 作り方
    * UIの見方
* ターミナルからのアクセス
    * TeraTermを使った接続
* EBSの追加
    * アタッチ方法

細かく手順やUIを細かく書いていくので，長めの記事になっています．

# EC2ダッシュボード
AWSのUIって定期的にリニューアルされるんですよね．．．
記事書いている最中にも「UI変わった Σ(ﾟДﾟ)」ってなったし．

2019年12月段階のUIはこちら
![dashboard.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165030/0c11390c-c852-1886-48b7-ff1b36abef38.png)
上部には，ナビゲーションバーがあります．
【サービス】からAWSの全サービスの一覧が表示されます．
中央には各種アイコンが並んでますが，ワンクリックナビゲーションというそうで，好きなサービスを配置することが出来ます．
よく使う`EC2`，`Route53`，`CloudWatch`，`IAM`，`Lambda`などはここに置いておくと便利です．
画像の右側には【東京】と書いてあるのは「リージョン」といって，リージョンごとにサービスの利用有無や金額の差異などがあります．
`AWS WAF`や`IAM`などのサービスは，リージョンを気にしない「グローバル（全域みたいなもの）」もあります．
基本的に，リージョンは揃えておくのが無難．

左側に各種項目，メインにいろんな情報を区分けにされています．
主に，知っておけばいいと思うのは，以下の2つ

* リソース
    * ここには，実行中インスタンスや`キーペア`，`ELB`，`EBS`など`EC2`を利用するにあたり重要な項目とその数が一目で分かるようになってます．
* インスタンスを起動
    * このボタン1つでインスタンスを作成するウィザードに移り，数クリックで`EC2インスタンス`が出来ちゃいます．

# EC2インスタンスの起動
さっそく`EC2インスタンス`を作っていきます．
先ほどのダッシュボードにある，いかにも「押して！」って主張している【インスタンスを起動】を押してあげましょう．

## OSの選択
そうすると，以下のような画面が出てきます．
![サーバOS.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165030/3aabf183-f8ca-e5e4-1652-c3721d5368be.png)
一覧にずらーっとサーバのOSが並んでいます．このうち，【無料利用枠の対象】となっているのが，文字通り無料で使えるOSになります．
特にこだわりもないので，今回は赤枠で囲んであるLinuxサーバにします．

## インスタンスタイプの選択
次に，サーバのスペックを決めていきます．
スペックを表すのが「インスタンスタイプ」です．
CPUやメモリ，ネットワークパフォーマンス（通信性能かな？）などが細かく分かれています．
無料枠は CPU1個，メモリ1Gの`t2.micro`のみになってます．タイプによって金額が変わりますので，利用目的や利用期間を想定して決めていきます．
`t2.micro`のインスタンス1台を1か月（大体31日分）稼働した分の金額が無料枠になります．なので，2台にすると，1台分の金額が請求されるようになります．ご利用は計画的に☆
私は，CPU2個，メモリ2Gのt3a.small を使っていたりします．（月額5,000円程度）
このインスタンスタイプは，サーバを停止させることで変更が可能なので，「まずお試しで，あとで本格的に」ということが出来ます．
右下にある「確認と作成」ボタンを押すと最後の確認画面まで飛びます．（間にある細かい設定はすべてデフォルト設定となります）
![サーバスペック.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165030/c15462fa-86d4-b007-3255-1a103a03e63d.png)

### T系インスタンスについて
インスタンスタイプには，A系・T系・M系などいろいろありますが，T系は基本的にベースラインとなるパフォーマンスを提供してくれます．
A系・M系にはない機能として，時間経過で溜まるCPUクレジットという数値があります．これは瞬発的にパフォーマンスが高騰する場合，このCPUクレジットを消費して，ベースラインを超えてパフォーマンスを発揮させることが出来ます．使い切ったら，CPUは通常のパフォーマンスで動きます．パフォーマンスを残しておける「タンス貯金」みたいな存在？です．

## インスタンスの詳細の設定
前の【インスタンスタイプの選択】で「次のステップ：インスタンスの詳細の設定」ボタンを押すと，文字通り，インスタンスについての細かな設定ができるようになっています．
ですが今回は特に変更・設定しないので，そのまま【次のステップ：ストレージの追加】に進みます．

## ストレージの追加
ここで，サーバの容量を変更することが出来ます．
画面は，これまでの設定してきた時の値になります．
ルートのストレージしかない状態で，サイズが8GiBになってます．ここで追加できますし，あとで個別に追加することもできます．
また，容量も後から増やすこともできます．（逆に減らすことはできないようです）
今回は，個別に`EBS`を追加するのでこのままにして，「次のステップ：タグの追加」に進みます．
![ストレージの追加.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165030/ddc050e9-38ba-ff2b-fabe-c9a528e42900.png)

## タグの追加
今回はタグは利用しないので，そっとしておいて「次のステップ：セキュリティグループの設定」に進みます．

## セキュリティグループの設定
セキュリティグループとは，アクセスするプロトコル（ポート番号）をグループという単位で管理するものです．
ファイヤーウォールのルールセットというとわかる人もいるかもしれません．
画像は，ここに遷移してきたものを撮影したものです．
![セキュリティグループ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165030/79bf97f3-8d93-1ad4-7ddf-0e8df216a5a8.png)

`SSH`は，ターミナルで接続するためのものなので，消さないようにします．（消してしまっても後で付ければいいですが）
ここに使うポートを追加していけば，HTTPやFTPなどが使えるようになります．
当然，「後々使うから解放しておこう」というより「必要になったから追加しよう」のほうがセキュリティ面が良いです．
ここはひとまず【セキュリティグループ名】と【説明】の欄だけ，自分が分かりやすいものにして，他はそっとしておきます．
ちなみに【セキュリティグループ名】は，先頭を `sg-` にすると，最後の最後に「sg-ってしないで！」って言ってきます．入力時にチェックしておいてよ．．．
このままだと，「どこからでもアクセスされちゃうから気持ち悪い！」という場合は，【ソース】欄のプルダウンを【カスタム】から【マイIP】に変更します．そうするとAWSに接続してるIPアドレスが自動的に設定してくれます．

そして，【確認と作成】に進みます．

## インスタンス作成の確認
最後に，今まで設定してきた項目をチェックできる画面になります．
問題なければ，右下の【起動】ボタンを押します！

## キーペアの設定
SSHで接続する際に利用する`キーペア`を登録します．
以前に作ったキーペアを使い回す場合は，既存のキーペアを指定すればよいですが，今回は新規で作っておきます．
画像では，「kp-sample-jupyterhub」というキーペア名にしてます．
新規追加する場合は，`キーペアをダウンロードいない`と先に進めないようになっています．
既存のキーペアを指定する場合は，「安全な場所に保管されてるよね？」って聞いてくるので，`チェックボタンにチェックする`と先に進めるようになっています．

![キーペア.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165030/3ad58ad7-03e8-afc6-c90e-fd501189ade4.png)

青枠で書かれている通り，再作成・再ダウンロードができませんので大切に保管しておきます．
【キーペアのダウンロード】を押すと，pemファイルがダウンロードされます．画像では `kp-sample-jupyterhub.pem`というファイル名になります．
ダウンロードすると【インスタンスの作成】ボタンが活性化するので，押すと晴れてEC2インスタンスが作成されます．

# インスタンスの確認
## インスタンス一覧
左側にある【インスタンス＞インスタンス】を選択すると以下の画像のような一覧が表示されます．
![インスタンス.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165030/964fddd0-640a-7f44-6de9-9c591a79abc8.png)
画像出たインスタンスが3つある状態になります．
今までの流れで作ったインスタンスは一番下のものです．
この一覧でよく見る項目を下表にまとめました．

|項目名|概要|
|:---|:---|
|Name|名前はまだ付けてないので空欄のままになっています．最初は気にならないのですが，数が増えていくと各インスタンスがどんな役割を持っているかわからなくなるので，Nameは積極的に使っていくといいでしょう．|
|インスタンスID|インスタンスごとに割り当てられるユニーク値です．この値を追いかければ必ずインスタンスを間違えることが無いようになってます．|
|インスタンスタイプ|現在利用しているインスタンスタイプになります．もし，インスタンスタイプを変更したい場合は，【アクション】からインスタンスを停止させた後にインスタンスタイプを変更できます．|
|アベイラビリティゾーン|EC2サービスの中でもゾーンというもので区切っていて，インスタンス作成時に必ずどこかに割り当てられます．|
|インスタンスの状態|画像では，`running`となっている部分です．停止中や削除中，起動中などの状態を確認できます．|
|パブリックDNS(IPv4)|次のIPv4パブリックIPに基づいて自動的に生成してくれる項目です．この値はドメイン名になっていて，IPアドレスの代わりに使用することが出来ます．|
|IPv4パブリックIP|ここの項目は，リンクが付いていない時と付いている時があります．<br>リンクが付いていない時は完全に動的なIPアドレスになっていることになります．この状態だと，インスタンスタイプを変更させたり，必要時のみ起動させるような使い方をしていたりしていると，その都度，割り当てられるため，コロコロ変わります．（OSのリブート`sudo reboot`では変わりません）<br>リンクが付いている時は`Elastic IP`を割り当てているときになります．`Elastic IP`は，IPアドレスを固定化させたいときに利用する機能になります．使われていない`Elastic IP`に対して課金させるちょっと変わった料金体系になっているようです．|

## インスタンスの詳細
一覧からインスタンスを選ぶと以下のような詳細情報が表示されます．
華扇の部分はインスタンスIDになっていて同じものが表示さているのが分かります．

![詳細ペイン.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165030/229af917-3459-8ce8-fcf8-0b1b0754d09b.png)

この部分で，よく見る項目を下表にまとめました．

|項目名|概要|
|:---|:---|
|セキュリティグループ|このインスタンスのセキュリティグループになります．リンク先でセキュリティグループの詳細を確認することが出来ます．サーバのアクセスポートなどはこのセキュリティグループが管理しているようになります．|
|キーペア名|インスタンス作成時に指定したキーペア名が表示されています．|
|パブリックDNS(IPv4)|一覧にあるものと同じです．`インスタンスにアクセスするためのドメイン`と言ったらこの項目になります．Route53でエイリアス設定すれば，好きなドメインでアクセスできるようになります．|
|IPv4パブリックIP|一覧にあるものと同じです．リンクの有無も連動してます．|
|ブロックデバイス|EBSを利用してアタッチされたものがここに列挙されます．(後で追加するので紹介しました)|


# ターミナルからのアクセス
EC2インスタンスが出来上がったら，さっそくアクセスしてみましょう．
私は，普段からTeraTermを使っているので，今回はTeraTermでアクセスしてみます．
以下のスクリプトをTTLファイルとして保存して，実行してみます．
usernameとpasswdは，`ec2-user`のままで構いません．最初のユーザはこれになっているので，これ以外だと接続できないようになってます．
あとで，専用のユーザを作るようにしてください．（`ec2-user`は`root`と同じなので，そのままでは危険です）

```
;;;;;;;;;;;;;;; connect information ;;;;;;;;;;;;;;;
; user name
username = 'ec2-user'
; password
passwd = 'ec2-user'

; secret key
keyfile = '"kp-sample-jupyterhub.pem"'

;host
hostname = '★ここにパブリックDNS(IPv4)の値を入れる★'

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; setup
msg = hostname
strconcat msg ':22 /ssh2 /auth=publickey /user='
strconcat msg username
strconcat msg ' /passwd='
strconcat msg passwd
strconcat msg ' /keyfile='
strconcat msg keyfile
 
; connect
connect msg
```

接続できると以下のように出てきます．
`Run "sudo yum update" to apply all updates.` と表示されているので，`sudo yum update` と入力してアップデートしてあげましょう．
![ターミナル.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165030/e6e00f4d-766f-1278-db60-6e4ed5aface8.png)

後で，EBSをアタッチして容量を増やしますが，いったんどんな状態か確認しておきます．
`df -h` とコマンドを入力すると，以下のように現在の容量が確認できます． `/dev/xbda1`のマウント先がルートになっていてインスタンス生成時にしていていた容量と同じになっています．
![サーバ容量確認.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165030/4b189209-7830-d895-b27d-4326f18db282.png)

## サーバ時刻を日本時間に変更
また，サーバ時刻はUTCになっているので，ファイルの更新時刻やタイムスタンプの利用の時，日本時間じゃないとピンとこないので，サーバを日本時間にさせておきます．
私は，こちらの記事を参考に設定しています．
https://qiita.com/drapon/items/2fc5b21a9cdc31ddb152

# サーバの容量を増やす
インスタンスにEBSを追加してサーバの容量を増やしておきます．
追加するEBSは，JupyterHubで作成されたnotebookデータを格納しておく場所（ワークスペース）として利用します．
手順は，
* EBS追加
* インスタンスにアタッチ
* マウント
の３つになります．

## EBSの追加
EC2の左側にある【ELASTIC BLOCK STORAGE＞ボリューム】を選択すると下図のような一覧が出てきます．
【アタッチ済み情報】を見て，どのインスタンスにつながっているか確認できます．
ここでも，ボリュームごとに【Name】という項目があるので，名前を付けておきましょう．
私の環境では，EC2インスタンスが3つ，追加EBSが1つあったので，計4つのEBSが存在しています．
先ほどターミナルで確認したように，EC2インスタンスにはルートとなるボリュームが必ず1つは必要になります．インスタンスを削除すると連動してここのルートボリュームは消えるようになっています（インスタンス作成時に連動機能をOFFにすることもできます）
![EBS一覧.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165030/d6213b73-50df-c294-f7f8-9c802a3faeb4.png)

【ボリュームの作成】ボタンを押すと作成画面に遷移します．
下図のように赤下線の2か所のみ設定していきます．
サイズは，文字通りボリュームの容量を指す項目です．後々容量が足りなくなったら追加する方向では問題ないので初めは小さくしてもいいと思います．（単位がGiBになっているので注意）
アベイラビリティーゾーンは，アタッチ先インスタンスがあるアベイラビリティーゾーンと同じにします．別のゾーンを選んでしまうと，アタッチできなくなるので注意が必要です．
今回は，30GiBにして作成します．（容量はお好みで）
![ボリューム作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165030/d29d933e-5595-de1e-61c4-103f7a349825.png)

【ボリュームの作成】ボタンをぽちっと押して，一覧に戻ると下図のように【状態】が`creating(作成中)`になっているので，待ちましょう．
待っている間に，【サイズ】【アベイラビリティーゾーン】【アタッチ済み情報】を確認して，`アタッチ先インスタンスと同じアベイラビリティーゾーン`になっていて，サイズが合っているか確認しておきます．
しばらくすると，`creating`から`available`に変わります．この状態では，「使えるけど使われていない」という状態でアタッチ可能ということになります．

今追加したボリュームを右クリックして，【ボリュームのアタッチ】を選択して，インスタンスに追加していきます．
![ボリュームのアタッチ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165030/6299aaf0-e497-c719-c5db-dba62ddaaa5f.png)

【ボリュームのアタッチ】を選択すると以下のようなダイアログが表示されるので，【インスタンス】のテキストボックスを選択すると，プルダウンでアタッチ可能インスタンスが出てくるので，追加したいインスタンスを選びます．もし，一覧になければ，アベイラビリティーゾーンが同じになってない可能性が高いので，見直しましょう．違っていてもEBSの中身は空っぽのはずなので，削除⇒作成してアベイラビリティーゾーンを合わせに行きます．
【デバイス】の項目は今回特に気にしないので，そのまま放置しておいて【アタッチ】ボタンを押します．
【アタッチ】ボタンを押したら，ボリュームのアタッチ済み情報にインスタンスIDが追加されます．
![インスタンスの指定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165030/50daa6e9-093b-7050-4f8b-e7d6b386e9c3.png)


## 追加したEBSをマウントする
細かい手順はこちらが参考になります．
https://qiita.com/yuppi/items/ceed29f19e2b38fd0a79

今回は，先ほどのボリュームを `/mnt/jupyterhub` というディレクトリにマウントさせようと思います．

まず，以下のコマンドでボリュームを初期化します．
ここから先は，`root`で操作していくので `sudo su -` でユーザーを切り替えておきます．
`/dev/sdf` には，先ほどの`ボリュームのアタッチ`で放置しておいたデバイスを指定します．

```
mkfs -t ext4 /dev/sdf
```

なんかログがずらーっと出力して実行が終了します．
マウントさせるディレクトリを作成します．

```
mkdir /mnt/jupyterhub
```

作成したディレクトリにフォーマット済みのボリュームをマウントさせます．

```
mount /dev/sdf /mnt/jupyterhub
```

`df -h`コマンドを実行すると下図の赤下線のように，`/mnt/jupyterhub`に30Gのサイズでマウントされていることが分かります．
![マウント確認.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165030/df83a189-ccee-7d8d-296f-5ab4a1a6b6c7.png)


# まとめ
今回は，EC2インスタンスの追加，ターミナルでの接続，EBSをインスタンスにアタッチの3つを行いました．
私の知識不足のため，セキュリティ関係には一切手を出しませんでした．
勉強したら，個別に記事書いていきたいと思います．