Azure AppServiceの診断ログをKibanaで可視化する

# はじめに

Azureが提供する各サービスは、ログをETL（Extract、Transform、Load）したり、アーカイブできる診断ログ機能があります。この記事では診断ログ機能でアーカイブしたログをKibanaで可視化し、ログを活用するための構築手順等を示します。
以下のようなイメージでシステムを構築してログデータを可視化します。

<img width="709" alt="スクリーンショット 2020-02-15 21.58.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133866/5d6b40f8-4dab-06d9-2045-75ed85cde737.png">

## 1. Elasticsearch/Kibanaを構築する

Elasticsearch/Kibanaをdockerを用いてubuntu16.04上に構築します。

### 1.1. dockerをインストールする

[docker公式ドキュメント](https://docs.docker.com/install/linux/docker-ce/ubuntu/)を参考に以下のコマンドでインストールします。

```console
$ sudo apt-get update
$ sudo apt-get -y install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
$ sudo apt-key fingerprint 0EBFCD88
$ sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"
$ sudo apt-get update
$ sudo apt-get install -y docker-ce docker-ce-cli containerd.io
```

### 1.2. docker-composeをインストールする

[docker公式ドキュメント](https://docs.docker.com/compose/install/)を参考に以下のコマンドでインストールします。

```console
$ sudo curl -L "https://github.com/docker/compose/releases/download/1.25.3/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose
$ docker-compose --version
```

### 1.3. docker-composeで構築する

```console
# vi docker-compose.yml
```

docker-compose.ymlは以下の内容で作成します。

```yaml
version: '2'
services:
  elasticsearch:
    image: ${ELASTICSEARCH_IMAGE}
    expose:
      - 9200
    ports:
      - "9200:9200"
    volumes:
      - ./elastic_data/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml
      - ./elastic_data/data:/usr/share/elasticsearch/data
    environment:
      - http.host=0.0.0.0
      - transport.host=127.0.0.1
      - ELASTIC_PASSWORD=${PASSWORD}

  kibana:
    image: ${KIBANA_IMAGE}
    links:
      - "elasticsearch"
    ports:
      - "5601:5601"
    volumes:
      - ./elastic_data/config/kibana.yml:/usr/share/kibana/config/kibana.yml
      - ./elastic_data/security:/security
```

docker-compose.ymlで読み込む環境変数を定義したconfigを作成します。

```console
# vi config
```

configは以下の内容で作成します。

```text
export USER=elastic
export PASSWORD=changeme
export ELASTIC_HOST="127.0.0.1"
export ELASTIC_PORT="9200"
export ELASTIC_ENDPOINT="http://${ELASTIC_HOST}:${ELASTIC_PORT}"
export ELASTICSEARCH_IMAGE=docker.elastic.co/elasticsearch/elasticsearch:7.6.0
export KIBANA_IMAGE=docker.elastic.co/kibana/kibana:7.6.0
```

elasticsearchを動作させるために以下のコマンドを実行します。

```console
# mkdir -p elastic_data/{config,data,security}
# chmod -R 755 elastic_data/{config,security}
# chmod -R 777 elastic_data/data
```

```console
# vi elastic_data/config/elasticsearch.yml
# vi elastic_data/config/kibana.yml
```

それぞれ以下の内容となります。

* elasticsearch.yml

```yaml
cluster.name: "docker-cluster"
network.host: 0.0.0.0
discovery.zen.minimum_master_nodes: 1
```

* kibana.yml

```yaml
server.name: kibana
server.host: "0"
elasticsearch.hosts: http://elasticsearch:9200
elasticsearch.username: elastic
elasticsearch.password: changeme
```

docker-composeコマンドを以下の様に実行して構築します。

```console
# source config
# docker-compose up -d
```

## 2. Logstashをインストールする

[公式ドキュメント](https://www.elastic.co/guide/en/logstash/7.6/installing-logstash.html#_apt)を参考に以下のコマンドにインストールします。

### 2.1. openjdkをインストールする

```console
$ sudo su -
# apt-get install -y openjdk-11-jdk
# INSTALLED_JAVA_HOME="$(find /usr/lib/jvm/ -name "java" |grep 'openjdk' | grep -v 'jre'|xargs -i dirname "{}"|xargs -i dirname "{}")"
# export JAVA_HOME=${INSTALLED_JAVA_HOME}
```

### 2.2. logstashをインストールする

```console
# LS_VERSION="7.6.0"
# LS_DOWNLOAD_URL="https://artifacts.elastic.co/downloads/logstash/logstash-${LS_VERSION}.tar.gz"
# LS_BASENAME=`basename "${LS_DOWNLOAD_URL}"`
# wget "${LS_DOWNLOAD_URL}" -P /tmp
# tar -zxvf "/tmp/${LS_BASENAME}"
```

## 3. Azureにリソースを構築する

AzureにログインしCloudShellを起動します。

![スクリーンショット 2020-02-15 22.50.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133866/4c84a6ae-5505-fea0-1ac2-a41e35df6a9a.png)

### 3.1. ResourceGroupを作成する

```console
$ az group create --name testStrAccELK
```

### 3.2. StorageAccountを構築する

StorageAccount名は一意の名前にする必要がありますので必要に応じて変更してください。

```console
$ az storage account create --resource-group testStrAccELK --name straccappelk2020021501
```

### 3.3. AppService(WebApps)を構築する

```console
$ az appservice plan create --resource-group testStrAccELK --name myAppServicePlan --location japaneast --sku B1
$ az webapp create --name testmyapp2020021501 --plan myAppServicePlan --resource-group testStrAccELK
```

## 4. WebAppsのログ診断を設定しログをStorageAccountに転送する

AzureポータルよりAppServiceログの設定を行います。
blobへログを送る設定はCLIでは[公式Githubを見る](https://github.com/Azure/azure-cli/issues/10043)に実装されていないようなので、ポータル(AppService > AppServiceログ)から設定します。

![スクリーンショット 2020-02-15 23.47.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133866/4d826946-ecbd-ed04-a82c-0d1d71edfc51.png)

## 5. LogstashからStorageAccountのログをElasticsearchに入れ込む

LogstashからStorageAccountのログを取り込むには、StorageAccountのアクセスキー、StorageAccount名、Blobコンテナ名が必要になります。
また、[Microsoftが開発しているlogstash plugin](https://github.com/Azure/azure-diagnostics-tools/tree/master/Logstash/logstash-input-azureblob)のインストールも必要となります。

### 5.1. logstash-input-azureblobプラグインのインストール

ここではubuntuで以下のコマンドを実行しインストールします。

```console
# cd logstash-7.6.0/bin/
# ./logstash-plugin install logstash-input-azureblob
```

### 5.2. StorageAccountのアクセスキーを特定する

Azureポータルから起動したCloudShellに以下のコマンドを実行して特定できます。

```console
$ az storage account keys list --account-name straccappelk2020021501 --resource-group testStrAccELK
```

### 5.3. Logstashのconfigを作成する

ubuntuのマシンで以下のコマンドを実行します。

```console
# vi azure_blog_webapp_diagnostic.config
```

以下の内容とします。

```console
input {
    azureblob
    {
        registry_create_policy => "start_over"
        storage_account_name => "straccappelk2020021501"
        storage_access_key => "<STOREGE_ACCESS_KEY>"
        container => "webapps-webserv-diagnostics"
        path_filters => "**/*.log"
    }
}

filter {
    if [message] =~ "^#" {
        drop {}
    }
    grok {
        match => { "message" => "%{TIMESTAMP_ISO8601:log_timestamp} %{WORD:application_name} %{WORD:http_method} %{URIPATH:uri_path} X-ARR-LOG-ID=%{UUID:x_arr_log_id} %{POSINT:port} %{USERNAME:cs_username} %{IP:ip_address} %{GREEDYDATA:user_agent} %{DATA:cs_cookie} %{DATA:referer} %{IPORHOST:host} %{NUMBER:sc_status} %{NUMBER:sc_substatus} %{NUMBER:sc_win32_status} %{NUMBER:sc_bytes} %{NUMBER:cs_bytes} %{NUMBER:time_taken}" }
    }
}
output {
  elasticsearch {
    hosts => ["http://127.0.0.1:9200"]
    index => "blob-web-%{+YYYY.MM}"
  }
  stdout { }
}
```

### 5.4. Logstashを実行する

```console
# ./logstash -f azure_blog_webapp_diagnostic.config

以下のようなログが出力されればStorageAccountからWebAppsのログが収集できています。

{
          "user_agent" => "curl/7.54.0",
            "cs_bytes" => "840",
             "message" => "2020-02-15 14:55:28 TESTMYAPP2020021501 GET / X-ARR-LOG-ID=138eb994-a586-4401-a5ce-a9bbb4d50a09 443 - 180.6.175.132 curl/7.54.0 - - testmyapp2020021501.azurewebsites.net 200 0 0 3896 840 15\r",
            "sc_bytes" => "3896",
            "uri_path" => "/",
          "time_taken" => "15",
     "sc_win32_status" => "0",
        "x_arr_log_id" => "138eb994-a586-4401-a5ce-a9bbb4d50a09",
          "ip_address" => "180.6.175.132",
    "application_name" => "TESTMYAPP2020021501",
       "log_timestamp" => "2020-02-15 14:55:28",
         "http_method" => "GET",
        "sc_substatus" => "0",
          "@timestamp" => 2020-02-15T15:04:16.278Z,
             "referer" => "-",
                "tags" => [
        [0] "_jsonparsefailure"
    ],
         "cs_username" => "-",
                "host" => "testmyapp2020021501.azurewebsites.net",
            "@version" => "1",
           "cs_cookie" => "-",
           "sc_status" => "200",
                "port" => "443"
}
```

## 6. Kibanaで可視化する

構築したkibanaにブラウザ上からアクセスします。
アクセス後、以下の画像のように操作してWebAppsのログがKibana上で見えることを確認します。

![スクリーンショット 2020-02-16 0.11.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133866/14b8e901-51d0-0296-5314-7c3eccba9eda.png)

Index patternを押下します。

![スクリーンショット 2020-02-16 0.11.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133866/467c4073-284e-e313-3c52-651acb71ee0a.png)

Create Index patternを押下しインデックスを作成します。

![スクリーンショット 2020-02-16 0.11.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133866/aed1816b-e259-000c-87e0-33a903d33507.png)

Index patternを画像のように入力してNext Stepsを押下します。

![スクリーンショット 2020-02-16 0.11.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133866/8c6ad934-27f0-26b5-02ec-1ff5019d3a22.png)

TimeFilterには`@Timestamp`を選択し、Create index patternsを押下したらインデックス作成完了です。

![スクリーンショット 2020-02-16 0.12.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133866/8f4938bb-8de7-410c-9ff6-1466196d797d.png)

完了画面からDiscoverへ遷移します。

![スクリーンショット 2020-02-16 0.12.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133866/d1ca3c5f-b01e-d551-3851-132c1c8aca67.png)

DiscoverからいくつかWebAppsのログが見えたら成功です！

![スクリーンショット 2020-02-16 0.12.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133866/e8c57614-be98-0164-415c-337160633944.png)

以上