Elasticsearch・Kibanaの環境をDockerで構築してみた

NTTテクノクロスの長谷川と申します。普段はウェアラブルデバイスなどを用いた自社製品の開発・維持管理業務に従事しています。
今回は、ElasticsearchとKibanaについて学習したことと、学習時の環境構築についてご紹介したいと思います。
私がElasticsearch・Kibanaの学習を始めた際、自由に利用できる環境がなかったため、Dockerで環境を構築しました。この経験が初学者の方々の参考になればと思い、この記事を執筆しました。
Elasticsearchに初めて触れる方にとって、学習の足掛かりとして役立つ記事となれば幸いです。

## Elasticsearch とは
Elasticsearchは、オープンソースの検索エンジンです。大規模なデータセットに対して高速で効率的な検索を行うことに優れています。
Elasticsearchの特徴として、ノードの追加によりシステム拡張できること、インデックス作成によるリアルタイム検索機能、テキストや数値、日付や地理情報など多様なデータタイプに対応したクエリ機能などが挙げられます。ユーザーは必要な情報を迅速かつ正確に取得することができます。
Elasticsearchは、ログ分析、データ可視化、フルテキスト検索など、さまざまな用途に利用されています。
特に、複数の情報源から収集したデータを活用することで、オブザーバビリティによるシステム全体の統合監視や、SIEM（Security Information and Event Management）による潜在的な脅威や異常の迅速な検出に優れています。

## Kibana とは
Kibanaは、Elasticsearchと連携して動作するデータ可視化ツールです。Elasticsearchに格納されたデータを視覚的に分析することができます。
主な機能としては、グラフやチャートの作成機能、ダッシュボードの作成、データ探索機能などが挙げられます。
さらに、Kibanaはシステム監視やSIEM向けの便利な機能を備えています。例えば、異常検知機能では、数多くのデータの中から通常とは異なるパターンを特定することができます。また、トレンド分析機能では、過去のデータから将来の予測を立てることができます。

## DockerでKibanaを動かせるようにする

それでは、ここからはElasticsearchとKibanaの環境をDockerを使って構築する手順を説明します。

### 環境情報
OS: Windows 10 + WSL2
WSLディストリビューション: Ubuntu 20.04.6 LTS

### 環境準備
①Dockerのインストール
Dockerのインストール方法については、公式のガイドを参照してください。以下のリンクから手順を確認できます。
https://docs.docker.com/engine/install/

②Dockerネットワークの作成
Elasticsearchのコンテナ間通信のために、カスタムネットワークを作成します。以下のコマンドを実行してください。
``` bash
$ docker network create test-nw --subnet=172.30.0.0/16 --gateway=172.30.0.254
```

③compose.ymlファイルの作成
次に、以下の内容でcompose.ymlファイルを作成します。このファイルには、Elasticsearch3台とKibanaの設定が含まれています。
Elasticsearchは複数ノードで構成することができ、今回はそのような構成を模しています。
バージョンは、ベンダ資格試験対策の対応バージョンである8.8としています。
``` yaml
services:
    elasticsearch1:
        image: docker.elastic.co/elasticsearch/elasticsearch:8.8.2
        hostname: doc-elastic101
        container_name: es01
        environment:
            - cluster.name=es-docker-cluster
            - network.host=0.0.0.0
            - node.name=es01
            - discovery.seed_hosts=es02,es03
            - cluster.initial_master_nodes=es01,es02,es03
            - bootstrap.memory_lock=true
            - "ES_JAVA_OPTS=-Xms128m -Xmx128m"
            - xpack.security.enabled=false
            - node.roles=master,data
        ulimits:
            memlock:
                soft: -1
                hard: -1
        mem_limit: 1g
        ports:
            - "9200:9200/tcp"
        networks:
            test-nw:
                ipv4_address: 172.30.10.1
        volumes:
            - elasticsearch1-data:/usr/share/elasticsearch/data
        extra_hosts:
            - "doc-elastic102:172.30.10.2"
            - "doc-elastic103:172.30.10.3"
            - "doc-kibana101:172.30.20.1"

    elasticsearch2:
        image: docker.elastic.co/elasticsearch/elasticsearch:8.8.2
        hostname: doc-elastic102
        container_name: es02
        environment:
            - cluster.name=es-docker-cluster
            - network.host=0.0.0.0
            - node.name=es02
            - discovery.seed_hosts=es01,es03
            - cluster.initial_master_nodes=es01,es02,es03
            - bootstrap.memory_lock=true
            - "ES_JAVA_OPTS=-Xms128m -Xmx128m"
            - xpack.security.enabled=false
            - node.roles=master,data
        ulimits:
            memlock:
                soft: -1
                hard: -1
        mem_limit: 1g
        networks:
            test-nw:
                ipv4_address: 172.30.10.2
        volumes:
            - elasticsearch2-data:/usr/share/elasticsearch/data
        extra_hosts:
            - "doc-elastic101:172.30.10.1"
            - "doc-elastic103:172.30.10.3"
            - "doc-kibana101:172.30.20.1"

    elasticsearch3:
        image: docker.elastic.co/elasticsearch/elasticsearch:8.8.2
        hostname: doc-elastic103
        container_name: es03
        environment:
            - cluster.name=es-docker-cluster
            - network.host=0.0.0.0
            - node.name=es03
            - discovery.seed_hosts=es01,es02
            - cluster.initial_master_nodes=es01,es02,es03
            - bootstrap.memory_lock=true
            - "ES_JAVA_OPTS=-Xms128m -Xmx128m"
            - xpack.security.enabled=false
            - node.roles=master,data
        ulimits:
            memlock:
                soft: -1
                hard: -1
        mem_limit: 1g
        networks:
            test-nw:
                ipv4_address: 172.30.10.3
        volumes:
            - elasticsearch3-data:/usr/share/elasticsearch/data
        extra_hosts:
            - "doc-elastic101:172.30.10.1"
            - "doc-elastic102:172.30.10.2"
            - "doc-kibana101:172.30.20.1"

    kibana:
        image: docker.elastic.co/kibana/kibana:8.8.2
        hostname: doc-kibana101
        container_name: kibana1
        environment:
            SERVER_NAME: "kibana"
            ELASTICSEARCH_HOSTS: "http://doc-elastic101:9200"
            ELASTICSEARCH_REQUESTTIMEOUT: "60000"
        ports:
            - "5601:5601/tcp"
        mem_limit: 1g
        networks:
            test-nw:
                ipv4_address: 172.30.20.1
        extra_hosts:
            - "doc-elastic101:172.30.10.1"
            - "doc-elastic102:172.30.10.2"
            - "doc-elastic103:172.30.10.3"
        depends_on:
            - elasticsearch1
            - elasticsearch2
            - elasticsearch3

volumes:
    elasticsearch1-data:
        driver: local
    elasticsearch2-data:
        driver: local
    elasticsearch3-data:
        driver: local

networks:
    test-nw:
        external: true
```

④コンテナの起動
次に、以下のコマンドを実行してコンテナを起動します。

``` bash
$ docker compose up --build -d
```
⑤Kibanaにアクセス
コンテナが正常に起動したら、ブラウザでhttp://localhost:5601/ にアクセスします。画面が表示されれば成功です。



### 注意点
起動時にdockerのログより、以下のようなエラーが表示されることがあります。
このエラーは仮想メモリ領域の値が不足しており、Elasticsearchが必要とするメモリ領域を確保できず、正常に起動できないことを示しています。
```
max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
```

このエラーが発生した場合は、以下のコマンドを実行して設定を変更してください。
``` bash
$ sudo sysctl -w vm.max_map_count=262144
```
以上で、ElasticsearchとKibanaの環境構築が完了です。必要に応じて、設定を調整しながら利用してください。

## Kibanaの操作
ここでは、Kibanaの基本的な操作を行う手順を説明します。
コンテナの起動後、http://localhost:5601/ にアクセスすると、Kibanaの画面を開くことができます。
![1_top.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3946181/ef3ff3c5-4e6f-8611-c4ff-a5414d318373.png)


Kibanaには、一部有償版でないと使えない機能があります。有償版の機能を試してみたい場合は、以下の手順でライセンス設定を行います。
* Kibanaの左側メニューから「Stack Management」を選択し、「License Management」をクリックします。いずれもメニューの一番下にあります。
![2_menu.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3946181/cade0709-0fee-17b1-b574-59e5e85eed2c.png)
![3_trial.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3946181/ecb0cc12-8ca0-22d0-16fc-f9cb730e719e.png)


* 「Start a 30-day trial」と試用版のライセンスを取得するボタンが表示されるので、指示に従って設定を行います。これにより、有償版の機能を一定期間試すことができます。


Kibanaでは、サンプルデータを利用して、データの可視化や分析を簡単に行うことができます。
Kibanaの機能を学習するには、こちらが便利です。以下の手順でサンプルデータを導入します。
* 左側メニューから「Home」を選択します。次に、「Try sample data」をクリックします。
![4_sample.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3946181/1363bf74-ad68-fc41-bad7-35279ef79d91.png)


* サンプルデータセットの中から、興味のあるデータを選択し、「Add Data」ボタンをクリックします。これにより、選択したデータがElasticsearchにインデックスされ、Kibanaで可視化できるようになります。
![5_sample.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3946181/0cecf6a9-7872-1daa-e928-33917eeac7d8.png)


* サンプルデータがインポートされたら、Kibanaの「Dashboard」「Visualize」などの機能を使って、データの可視化を行います。以下の画面は、サンプルデータとして「Sample eCommerce orders」を選択し、ダッシュボードを開いたときの画面です。
![6_sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3946181/1d32901e-1cbb-bdc2-13a0-f60c63e61641.png)


## 終わりに
いかがでしたでしょうか。この記事を機に、Elasticsearchを知るきっかけとなれば幸いです。
もし、導入・活用にご興味がありましたら、以下のHPもぜひご覧ください。
https://www.ntt-tx.co.jp/products/elastic/
最後までご覧いただき、ありがとうございました。