【Elastic Stack & AWS】COVID-19可視化サイトを作ってみよう

# やりたいこと
#### COVID-19の可視化をElastic Stackを使ってAWS上に行い、公開する
ということをやっていこうと思います。
Elastic社の公式YouTubeチャンネルより[このような動画](https://youtu.be/iRiomHE2wY0?list=PL1n6JjsAcJxU5HtvIj3axpWJeeakuBy2q)が配信されていました。
そして私自身最近Elastic認定エンジニアを取得させていただいたことからせっかくなら自分でもこういったCOVID-19を可視化するようなページを作ってみようと思ったことがきっかけです。
そして本記事では
#### AWS基盤構築〜Elastic Stack構築の方法を公開しようと思います

# ゴール
こんな感じのページを作ろうと思います
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119747/41bbada5-838a-33f5-5b5e-2d89f00b1917.png) 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119747/a2f5038a-95f8-dd29-cde5-a0c71f79bf37.png)

基盤構成はこんな感じ
Logstashにより公開データを自動でデータを吸い上げてElasticsearchに保存し、Kibanaで可視化するといった形になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119747/4467dd3e-9050-a155-e817-472477475add.png)


# 使うもの
- Elastic Stack
    - Elasticsearch
    - Kibana
    - Logstash
- AWS
    - EC2
- docker

今回はまずページを作ることを第一にやっていこうと思いますのでELB、Cloudfrontを使わずにやっていきます。

# EC2の構築
基盤はEC2を使っていこうと思います。AWSの管理コンソールに入り、インスタンスを作成します。  
- Amazonマシンイメージ：　Amazon Linux 2 AMI
- インスタンスタイプ：　t2.large (今回の構成だとt2-large未満だと動かないです)
- インスタンスの詳細設定：　ここは自由に（外からつなげるネットワークを使ってください）
- ストレージ：　64GiBぐらいで（8は厳しい気がします）
- タグの追加：　適当に　Name: covid-19-test
- セキュリティグループ：　以下の2つは絶対入れてください（名前も適当につけてください）
    - タイプ：ssh, プロトコル：TCP, ポート：22, ソース：お好きに
    - タイプ：カスタムTCP, プロトコル：TCP, ポート：5601, ソース：0.0.0.0/0

最後に確認してよければ起動を押下 → 鍵はなくさず取っておきましょう！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119747/982037d1-f8d5-55aa-5f43-2c87559936e4.png)

こんな感じで立ち上がってきます
少し待って疎通確認をしてみます

sshでインスタンスに接続します。（接続の仕方がわからない方は上記写真にある「インスタンスの作成」の横にある「接続」を押下すると接続方法が書いてあります。）

# コンテナ環境の構築
ここではdockerをインストールし、「Elasticsearch」、「Kibana」、「Logstash」コンテナを作成しようと思います。
また、それぞれの製品に関してElastic社からコンテナイメージを提供されていますが、今回はCentOSコンテナを作成しその上でそれぞれの製品をインストールしていこうと思います。

## dockerのインストール
現在いるEC2インスタンス上にdockerをインストールしていきます
dockerをインストール後、ec2-userでもdockerコマンドを使用できるように設定します。

```
$ sudo yum install -y docker
$ sudo service docker start
$ sudo usermod -a -G docker ec2-user
$ sudo systemctl enable docker
$ exit
```

上記コマンドによりdockerをインストールできたらEC2インスタンスに再接続し、以下コマンドによりdockerが使用できるか確認してください。

```
$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
```
上記のように表っぽいものが帰ってくると設定は完了です。


## docker networkの構築
今回はそれぞれのコンテナ間での通信が必要となるため、docker networkを作成する必要があります。

```
$ docker network create elasticstack
```

以下のようにして確認ができます

```
$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
39612814bc52        bridge              bridge              local
b5c7f801ff0b        elasticstack        bridge              local
b6ca1bb92159        host                host                local
0dc929d2724d        none                null                local
```

## コンテナの作成
実際にコンテナを作成していきます
上記でも説明した通り、今回は３つのコンテナを作成していきます。
それぞれのコンテナの要件は以下となります

- elasticsearchコンテナ
    - name: elasticsearch
    - network: elasticstack
    - port: 9200:9200
    - イメージ: centos:centos7
- kibanaコンテナ
    - name: kibana
    - network: elasticstack
    - port: 5601:5601
    - イメージ: centos:centos7
- logstashコンテナ
    - name: logstash
    - network: elasticstack
    - イメージ: centos:centos7

それぞれの設定を踏まえた上でコンテナを作成します。

```
$ docker run -it -d --network elasticstack -p 9200:9200 --name elasticsearch --privileged centos:centos7 /sbin/init
$ docker run -it -d --network elasticstack -p 5601:5601 --name kibana --privileged centos:centos7 /sbin/init
$ docker run -it -d --network elasticstack --name logstash --privileged centos:centos7 /sbin/init
```

たちがってることを以下のコマンドで確認できます。

```
$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                    NAMES
4aea44cb44ce        centos:centos7      "/sbin/init"        4 minutes ago       Up 4 minutes                                 logstash
479654a004cb        centos:centos7      "/sbin/init"        4 minutes ago       Up 4 minutes        0.0.0.0:5601->5601/tcp   kibana
977d952a52a8        centos:centos7      "/sbin/init"        4 minutes ago       Up 4 minutes        0.0.0.0:9200->9200/tcp   elasticsearch
```

## Elastic Stackの構築
それぞれのコンテナの設定をしていきます。
### Elasticsearchコンテナ
#### Elasticsearchの構築
以下のコマンドによりコンテナ内に入って作業を行います。

```
$ docker exec -it elasticsearch /bin/bash
```

javaのインストールとElasticsearchのrpmをインストールします。rpmのインストールではelasticsearchインストール用のrpmが必要ですのでそれを入手するためにもwgetもインストールします。
今回はJavaのバージョンは11系、Elasticsearchは7.6.2で行っていこうと思います。

```
# yum install -y java-11-openjdk
# yum install -y wget
# wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.6.2-x86_64.rpm
# rpm --install elasticsearch-7.6.2-x86_64.rpm
```

#### Elasticsearchの設定
今回の構成ではElasticsearchがシングルクラスタであることやコンテナ上で起動していることからElasticsearhにいくつかの設定をしてあげる必要があります。ここではその設定を行っていきます。
##### elasticsearch.ymlの設定
elasticsearch.ymlを開いてください。

```
# vi /etc/elasticsearch/elasticsearch.yml 
```

elasticsearch.ymlの一番最後の行に以下を追加してください。

```
cluster.name: my_cluster
node.name: elasticsearch
network.host: _site_
cluster.initial_master_nodes: ["elasticsearch"]
```
今回はシングルクラスタなのでcluster.name、node.name はあまり設定する必要がないですが、自分で設定する方が後々便利なので設定します。
network.host はリッスンするホストを指定します。今回はリンクローカルアドレスということで_site_を指定します。
cluster.initial_master_nodesはシングルクラスタ構成をとるには必ず必要な設定となりますので設定してください。簡単にいうとマスターノードを選定するために最低限必要なノードをここで指定します。

また、今回はjvm.optionsの設定も変更していきます。

```
# vi /etc/elasticsearch/jvm.options
```

-Xms1g, -Xmx1gとなっている箇所を以下に変更してください。

```
-Xms2g
-Xmx2g
```

設定を終えたらelasticsearchを起動してみます。

```
# systemctl restart elasticsearch.service
```

以下のコマンドを打つと起動できたことを確認できます。

```
# curl elasticsearch:9200
{
  "name" : "elasticsearch",
  "cluster_name" : "my_cluster",
  "cluster_uuid" : "l_xjt09CSu-43BUdBM4fkg",
  "version" : {
    "number" : "7.6.2",
    "build_flavor" : "default",
    "build_type" : "rpm",
    "build_hash" : "ef48eb35cf30adf4db14086e8aabd07ef6fb113f",
    "build_date" : "2020-03-26T06:34:37.794943Z",
    "build_snapshot" : false,
    "lucene_version" : "8.4.0",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}
```
※ 本来はxpack.securityなどを用いてセキュリティを強化する必要がありますが、ElasticsearchとKibanaを行ったり来たりするかsslを有効にする必要があったりして少し面倒なので今回はパスします。

### Kibanaコンテナ
#### Kibanaの構築
以下のコマンドによりコンテナ内に入って作業を行います。

```
$ docker exec -it kibana /bin/bash
```

javaのインストールとkibnaのrpmをインストールします。rpmのインストールではkibanaインストール用のrpmが必要ですのでそれを入手するためにもwgetもインストールします。
今回はJavaのバージョンは11系、kibanaは7.6.2で行っていこうと思います。

```
# yum install -y java-11-openjdk
# yum install -y wget
# wget https://artifacts.elastic.co/downloads/kibana/kibana-7.6.2-x86_64.rpm
# rpm --install kibana-7.6.2-x86_64.rpm
```

#### Kibanaの設定
コンテナ上で起動していることのでKibanaにいくつかの設定をしてあげる必要があります。ここではその設定を行っていきます。
##### kibana.ymlの設定
kibana.ymlを開いてください。

```
# vi /etc/kibana/kibana.yml 
```

kibana.ymlの該当箇所を探して以下の設定に変更してください。

```
server.host: 0.0.0.0
elasticsearch.hosts: ["http://elasticsearch:9200"]
```

設定を終えたらelasticsearchを起動してみます。

```
# systemctl restart kibana.service
```

ここまでくるとkibanaを起動できるようになっています
以下のURLにアクセスして疎通確認をしてみましょう

```
http://{パブリックDNS}:5601
```

kibanaに接続後左側にあるサイドバーの「Dev Tools」に移動してください。
そうするとコンソール画面が出てくるのでそこで以下の入力を行った後、再生ボタンを押下してみてください

```
GET /
```
以下のような画面が出てくればKibana → Elasticsearchの接続も完了です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119747/648f9fcf-faa4-973b-e59d-1e1016c670c6.png)


##### インデックステンプレートの設定
[こちら](https://github.com/siscale/covid-19-elk)にインデックスのテンプレート、ダッシュボードのテンプレートなどが公開されているのでダウンロードしてきましょう
ダウンロードしてくると
https://github.com/siscale/covid-19-elk/blob/master/index-template-mapping.json
こちらのテンプレートをKibanaで登録していきます。
index-template-mapping.jsonファイルをコピーし、先ほどの「Dev Tools」画面でクエリを投げます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119747/7951a274-c5f1-30a7-020a-18309e59a350.png)

これでインデックステンプレートが作成できました。

##### ダッシュボードの設定
次に、ダッシュボードのテンプレートを取り込みます。
左側のバーにある「Managemnet」を押下後、Kibanaの項目にある「Saved Objects」を押下してください。
以下のような画面になると思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119747/5cce75e2-6b03-00c1-923b-5484aa1e2cc3.png)

右上のimportを押下後、以下のファイルをインポートしてください。
ドラッグ&ドロップでインポートできます。
https://github.com/siscale/covid-19-elk/blob/master/kibana-7.6.1-covid-19-dashboard.ndjson
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119747/b8f0b85c-d967-ca49-c787-9d4384b5fa4d.png)
インポート後、「Saved Objects」をもう一度確認すると、以下のようにテンプレートが複数入っていることがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119747/47fae45b-f26b-4795-1289-c4d919d838ed.png)
まだデータが入っていないのでどれを見てみてもエラーにしかなりませんが、これで可視化の準備はできました。


### Logstashコンテナ
今回はJohns Hopkins Universityにより公開されている[こちらのデータ](https://github.com/CSSEGISandData/COVID-19/tree/master/csse_covid_19_data/csse_covid_19_daily_reports)を用いて可視化を行います。
また、[こちら](https://github.com/siscale/covid-19-elk)にテンプレートが公開されているのでそれもうまく使用しながらLogstashの構築を行っていきます。

#### Logstashの構築
以下のコマンドによりコンテナ内に入って作業を行います。

```
$ docker exec -it logstash /bin/bash
```

Javaのバージョンは11系です。

```
# yum install -y java-11-openjdk
```
/etc/yum.repos.d/配下に以下の設定を反映したlogstash.repoファイルを作成します。([参考](https://www.elastic.co/guide/en/logstash/current/installing-logstash.html))

```
[logstash-7.x]
name=Elastic repository for 7.x packages
baseurl=https://artifacts.elastic.co/packages/7.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=1
autorefresh=1
type=rpm-md
```

インストールを実施します。

```
# yum install -y logstash
```

#### Logstashの設定
##### confファイルの編集
gitのインストールを行い、テンプレートをcloneします

```
# yum install -y git
# git clone https://github.com/siscale/covid-19-elk.git
```

今回の環境に合わせてlogstash-github-covid-19-daily-reports-template.conf を編集します。
現在以下のようになっていると思います。

```
# vi /covid-19-elk/logstash-github-covid-19-daily-reports-template.conf
...
output {
  #Send the data to Elasticsearch
  elasticsearch { 
    #Add your Elasticsearch hosts 
    hosts => ["<ES_HOST>"]
    #Add the index name
    index => "covid-19-live-update"
    #Add Elasticsearch credentials 
    user => "<ES_USER>"
    password => "<ES_PASSWORD>" 
```

上記の hosts を変更し、user, passwordをコメントアウトします。

```
# vi /covid-19-elk/logstash-github-covid-19-daily-reports-template.conf
...
output {
  #Send the data to Elasticsearch
  elasticsearch { 
    #Add your Elasticsearch hosts 
    hosts => ["http://elasticsearch:9200"]
    #Add the index name
    index => "covid-19-live-update"
    #Add Elasticsearch credentials 
    # user => "<ES_USER>"
    # password => "<ES_PASSWORD>" 
```

編集したconfファイルを/etc/logstash/conf.dディレクトリにコピーします。

```
# cp /covid-19-elk/logstash-github-covid-19-daily-reports-template.conf /etc/logstash/conf.d/
```
##### jvm.optionsの編集
elasticsearchと同様、jvm.optionsの設定も変更していきます。

```
# vi /etc/logstash/jvm.options
```

-Xms1g, -Xmx1gとなっている箇所を以下に変更してください。

```
-Xms2g
-Xmx2g
```

##### 起動
confファイルを指定し、logstashを起動します。

```
/usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/logstash-github-covid-19-daily-reports-template.conf 
```

こちらのconfファイルは毎時００分に[こちらのデータ](https://github.com/CSSEGISandData/COVID-19/tree/master/csse_covid_19_data/csse_covid_19_daily_reports)を監視し更新がないかを確認した後、更新があればelasticsearchにドキュメントを登録するという設定になっています。
そのため、一度こちらを走らせてしまえば、以降何もしなくてもデータが更新され続けるということになります。
以下のような行が出力されればとりあえずうまくいっています。

```
 ruby - Succesfuly updated cache at /etc/logstash/covid-19-hashes.json
```

## ダッシュボードの確認
左側のバーにある「Managemnet」を押下後、Kibanaの項目にある「Saved Objects」を押下してください。
その中に「COVID 19」とあると思うのでそちらを押下してください。
そうすると、以下のような画面になると思います。まずIndex patternを定義しろ！と言われてしまうので従いましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119747/019a6c3a-9a80-9383-c16e-58f074ce4921.png)

「index pattern」に「covid-19-live-update*」と入力し、「Next Step」を押下、次の画面の「Time Filter field name」で「@timestamp」を選択してください。
その後、「Create index pattern」を押下してindex patternを作成してください。
index patternが作成できたと思うので先ほどの「Save Objects」に戻り、「COVID 19」を押下すると以下のようなダッシュボードの閲覧ができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119747/412e5e2e-13f8-4763-28c1-1f90a4853cdf.png)
もし、上記のような画面にならない方はもしかしたら右上の日にち設定が、最近の15分などになっているかもしれないので調整してみてください。
また、左上にある「Share」というところを押下すると「埋め込みコード」を発行してくれたり、「pdf」、「png」ファイルを出力してくれたりするので是非触ってみてください。

## まとめ
[こちらのデータ](https://github.com/CSSEGISandData/COVID-19/tree/master/csse_covid_19_data/csse_covid_19_daily_reports)を使ってCOVID-19の様子を可視化してみました。
Kibanaでの構築やElasticsearchの基本などまだまだあげていく予定ですのでよろしくお願いします。

## 参考
[はじめてのElasticsearch](https://www.udemy.com/course/elasticsearch/?referralCode=77A587BF990789F85505)

[はじめてのKibana](https://www.udemy.com/course/kibana-jap/?referralCode=51CCA3E0F0553B561DBC)