AWS EFS でHLS配信

#はじめに

東京リージョンでもEFSが出たのでEFSでのライブ配信を試します。

遅延を少し抑えられるのとスケールアウトがやりやすいかと思いますがCloudFrontに直接繋げられるMedia Storeがあるのであまり利用するケースが無いかもしれません。
MediaLiveを利用すれば出力をs3やMedia Storeに直接書き込みが出来それをCloudFrontのオリジンにすることも出来ます。
(ただMedia Store消すのが面倒なんですよねー、後MediaLive経由だとDestinationが２つ必要になるので。。。)

MediaServicesが出る前にNFSやs3fsで共有領域をマウントして配信を検討していた時期があったので「あの時あればどうなっていたかな？」という疑問を解決するためにやってみます。

#環境

![ライブ構成案.png](https://qiita-image-store.s3.amazonaws.com/0/226670/72e8da1b-0ef3-4dab-51ee-d270bfad1e60.png)

構成はこんな感じになります。

##流れ

1.　Videoを撮影
2.　Encoderで取り込みtranscoderにrtmpで送出
3.　TranscoderでrtmpをHLSに変換してEFSに格納
4.　ViewerがELB経由でWebserverにマウントされたEFSのHLSコンテンツを閲覧

##Video、Encoder

こちらはなんでもいいですがトランスコーダーはnginxのrtmpモジュールを利用するのでrtmpで配信できるエンコーダーを利用します。
私はMacbook　Proの内部カメラと無料の[OBS](https://obsproject.com)エンコーダーでrtmpを投げます。

OBSの使い方の詳細が気になる方は[obsproject](https://obsproject.com)をご参考ください。

##Transcoder

トランスコーダーはnginx+rtmpモジュールを利用。

構築方法は以前の記事[HLSライブストリーミングサーバーの構築 (ABR対応)](https://qiita.com/khagi/items/b99f5a36846d9ab65daa) をご参考ください。

##Webserver

ウエブサーバーはなんでも良いのですが今回はnginx(https://nginx.org) で行います。

#EFS

##EFS作成

1. AWS　EFSの[トップページ](https://ap-northeast-1.console.aws.amazon.com/efs/home?region=ap-northeast-1#/firstrun) を開く

<img width="1775" alt="スクリーンショット 2018-08-03 16.12.42.png" src="https://qiita-image-store.s3.amazonaws.com/0/226670/15c3d1df-b797-8007-b954-14075aadaffc.png">

2. ”ファイルシステム作成”をクリックし、”ファイルシステムアクセスの設定”と”マウントポイント設定”を行う。今回はデフォルトで設定

<img width="1574" alt="スクリーンショット 2018-08-03 16.15.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/226670/cc2c5c4d-64e3-2263-260c-34ff0a93fea4.png">

3. ”次のステップをクリック”しNameタグの値を入力そのほかはデフォルト設定で”次のステップ”へ

<img width="1575" alt="スクリーンショット 2018-08-03 16.31.59.png" src="https://qiita-image-store.s3.amazonaws.com/0/226670/bfac9a42-665e-d51d-ce8d-75b1bd0e9666.png">

4. 設定した内容を確認し、”ファイルシステムの作成”を押下

5. EFSが作成されます。

<img width="3110" alt="スクリーンショット 2018-08-03 16.36.37-1.png" src="https://qiita-image-store.s3.amazonaws.com/0/226670/3929dc68-cc94-43ef-1275-b4ad7ca03909.png">

##EC2でマウント

### amazon-efs-utilsインストール

Amazon Linuxでマウントする場合、amazon-efs-utils パッケージが提供されています。こちらインストールするとstunnelパッケージもインストールされます。

amazon-efs-utils.noarch : This package provides utilities for simplifying the use of EFS file systems
stunnel.x86_64 : An SSL-encrypting socket wrapper

```
$　sudo yum install amazon-efs-utils
```

###マウント

```
$ sudo mkdir /efs_mnt
$ sudo mount -t efs fs-XXXXXXXX:/ efs_mount
```

###マウント確認

```
# mount
proc on /proc type proc (rw,relatime)
sysfs on /sys type sysfs (rw,relatime)
/dev/xvda1 on / type ext4 (rw,noatime,data=ordered)
devtmpfs on /dev type devtmpfs (rw,relatime,size=2010440k,nr_inodes=502610,mode=755)
devpts on /dev/pts type devpts (rw,relatime,gid=5,mode=620,ptmxmode=000)
tmpfs on /dev/shm type tmpfs (rw,relatime)
none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw,relatime)
fs-XXXXXXXX.efs.ap-northeast-1.amazonaws.com:/ on /efs_mnt type nfs4 (rw,relatime,vers=4.1,rsize=1048576,wsize=1048576,namlen=255,hard,noresvport,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=XXX.XXX.XXX.XXX,local_lock=none,addr=XXX.XXX.XXX.XXX)
```

###ライブ利用ディレクトリーの作成

```
$ mkdir　/efs_mnt/livetest
```

###EFSのアンマウント

(すごくどうでもいいことなのですがアンマウントのコマンドが"ユーマウント"、一文字足して"unmount"にした方がよかったんじゃないのとこのコマンド打つ度に思う)

```
$ sudo umount /efs_mnt
```

###ライブ利用領域のみマウント

EFS上にディレクトリーlivetestを作成してそこをマウントしました。

```
$ sudo mount -t efs fs-XXXXXXXX:/livetest /efs_mnt
$ mount
proc on /proc type proc (rw,relatime)
sysfs on /sys type sysfs (rw,relatime)
/dev/xvda1 on / type ext4 (rw,noatime,data=ordered)
devtmpfs on /dev type devtmpfs (rw,relatime,size=2010440k,nr_inodes=502610,mode=755)
devpts on /dev/pts type devpts (rw,relatime,gid=5,mode=620,ptmxmode=000)
tmpfs on /dev/shm type tmpfs (rw,relatime)
none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw,relatime)
fs-XXXXXXXX.efs.ap-northeast-1.amazonaws.com:/livetest on /efs_mnt type nfs4 (rw,relatime,vers=4.1,rsize=1048576,wsize=1048576,namlen=255,hard,noresvport,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=XXX.XXX.XXX.XXX,local_lock=none,addr=XXX.XXX.XXX.XXX)
```

#Transcoder

上記にも書きましたがトランスコーダーはnginx+rtmpモジュールを利用。

構築方法は以前の記事[HLSライブストリーミングサーバーの構築 (ABR対応)](https://qiita.com/khagi/items/b99f5a36846d9ab65daa) 同様に作成します。

違いとしてはnginx.conf内のhls_pathをEFSを指定します。

nginx.conf抜粋

```
hls_path /efs_mnt/;
```

## 配信

配信方法は[こちら](https://qiita.com/khagi/items/b99f5a36846d9ab65daa#%E3%81%A7%E3%81%A9%E3%81%86%E3%82%84%E3%81%A3%E3%81%A6rtmp%E3%82%92%E6%8A%95%E3%81%92%E3%82%8B%E3%81%AE)
今回はOBSを使って投げています。

###トランスコード確認

Transcoderで確認したけど問題なく書き込みが行われています。
削除も問題無いようです。

```
# ls /efs_mnt/
hagitest_high  hagitest_low  hagitest.m3u8  hagitest_mid
# ls /efs_mnt/hagitest_high/
19.ts  20.ts  21.ts  22.ts  23.ts  24.ts  25.ts  26.ts  27.ts  28.ts  29.ts  30.ts  31.ts  index.m3u8
```

# Webserver

ウェブサーバーはなんでも良いのですが今回はnginxで確認します。

##　EFSマウント

上記に記述した手順でEFSをウェブサーバーにもマウントをする。
トランスコーダーはlivetestをマウントしたのになぜウェブサーバーはEFS全体をマウントしたのか？　-　複数のトランスコーダーを繋げてEFS上でディレクトリーをトランスコーダー別で分ける予定だったからです。

```
# mkdir /efs_mnt
# mount -t efs fs-XXXXXXXX:/ /efs_mnt
# ls /efs_mnt/
livetest
```

##　Nginx設定

簡易な設定

```
http {

    server {
        listen 80;
        include       mime.types;
        default_type  application/octet-stream;
        server_name localhost;
        add_header Cache-Control no-cache;
        add_header 'Access-Control-Allow-Origin' '*';

        location / {
            types {
                 application/vnd.apple.mpegurl m3u8;
            }
            root /efs_mnt/livetest;
        }
}
```

##Safariで問題なく再生

<img width="1341" alt="スクリーンショット 2018-08-20 12.06.59.png" src="https://qiita-image-store.s3.amazonaws.com/0/226670/0a6585c4-af80-448b-97f1-88ec1903f3a1.png">


# 負荷分散

EFSを利用する利点としてトランスコーダーとウェブサーバーのデータを共有することと共にウェブサーバー同士でも共有できることかと思います。
ストリームデータを共有することによってスケールアウトも出来、負荷分散も可能となります。
そこで構成図に記述しました２台目のウェブサーバーを立ち上げELBに追加します。

##ELB作成、AMI 作成、インスタンス起動

今更感のところもあるので

ポチ、ポチ、ポチ

##EFSマウント、nginx.conf、nginx起動

上記を参照

##ELBに追加

ポチ

# 再生

ELBからの再生も問題ない

<img width="1339" alt="スクリーンショット 2018-08-20 12.53.02.png" src="https://qiita-image-store.s3.amazonaws.com/0/226670/fd5493dc-4b51-ca96-4cc7-8feb083e4906.png">

#最後に

EFSを長期的に利用した訳ではないので何ともいえませんが、利用方法によってはかなり便利だと思いました。
一つはスケールアウトが非常に簡単。EFSをウェブサーバーにマウントしてELBに追加するだけ。
もう一つはs3に転送するよりも圧倒的に簡単です。s3から配信するユースケースがあるとは思いますがライブ動画データをs3に置くまでが非常に面倒です。

今後ライブ配信環境に使えそうでいろいろ試したいと思います。