【ClickHouse連載】nginxアクセスログをLogStash- ClickHouseへデータ連携してみる

Hi, データエンジニアの大原です。

今回はタイトル通り、nginxアクセスログをLogStash- ClickHouseへデータ連携する方法をご紹介します。
ClickHouseはAlibaba Cloudの国際サイトで提供している ClickHouse を使用します。

f:id:sbc_ohara:20210714233458p:plain

ClickHouseとは

ClickHouseは非集計データを含む大量のデータを安定的かつ継続しながら集計といったリアルタイム分析を支える列指向の分散型データベースサービスです。 トラフィック分析、広告およびマーケティング分析、行動分析、リアルタイム監視などのビジネスシナリオで幅広く 使用されています。
ApsaraDB for ClickHouseの概要として、詳しいことはこの記事にてまとめています。

www.sbcloud.co.jp

clickhouse.tech

LogStashとは

Elastic社が管理するオープンソースのデータ収集ツールです。データを収集しつつ、ETLもできるため、Elasticsearchサービスと連携することが多いです。

www.elastic.co

本記事では、nginxアクセスログをLogStash - ClickHouseへデータ連携してみます。構成図で次の通りです。

f:id:sbc_ohara:20210823155034p:plain

利用環境:
ECS・・・CentOS 7.8 64-bit
Java・・・1.8.0_144
Nginx・・・v1.20.1
Logstash・・・v7.0.0
filebeats・・・v6.2.4
Clickhouse・・・v20.8.7.15
Logstash Plugin・・・logstash-output-clickhouse、logstash-filter-prune、logstash-filter-multiline

1. ClickHouseClientの準備

1-1.ClickHouseインスタンスを準備します

この手法は過去の記事でも記載していますが、再掲として記載します。

www.sbcloud.co.jp

1)まずはApsaraDB for ClickHouseインスタンスを作成します。
①VPCを作成

f:id:sbc_ohara:20210716155036p:plain

f:id:sbc_ohara:20210716155113p:plain

②ClickHouseインスタンスを作成
著者は以下のインスタンススペックでインスタンスを作成しています。

ClickHouse version:20.8.7.15
Edition:Single-replica Edition

f:id:sbc_ohara:20210716155212p:plain

f:id:sbc_ohara:20210716155220p:plain

f:id:sbc_ohara:20210716155231p:plain

2)ClickHouseの登録アカウントを作成 インスタンスをクリックし、左側にアカウント管理画面で、アカウントを作成します

f:id:sbc_ohara:20210716155256p:plain

3)ClickHouseクラスターにDMSで接続 ①ClickHouseのインスタンスをクリックし、トップメニューの「Log On to Database」をクリックします

f:id:sbc_ohara:20210716155315p:plain

② DBアカウントとパスワードを入力し、ClickHouseへログイン

f:id:sbc_ohara:20210716155334p:plain

③DMS画面でClickHouseのインスタンスが表示されます

f:id:sbc_ohara:20210716155401p:plain

2.ECSでNginxのインストール

2-1.ECS作成

1)Nginx導入のためのECSを作成します
①ECSコンソール画面でECS作成ボタンをクリックし、ECSを作成します
f:id:sbc_ohara:20210823135321p:plain

②ECS作成画面でSpec、課金方法を設定します
f:id:sbc_ohara:20210823135337p:plain

③CentOSを設定します
f:id:sbc_ohara:20210823135420p:plain

④VPCを選択します(ちなみに上記1 で作成したApsaraDB for Clickhouseと同じVPCを選定すると、Intranet経由で相互接続することができます) f:id:sbc_ohara:20210823135433p:plain

⑤ECSの登録パスワードを設定します
f:id:sbc_ohara:20210823135546p:plain

⑥ECS設定情報を確認します
f:id:sbc_ohara:20210823135603p:plain

⑦ECSを確認します
f:id:sbc_ohara:20210823135619p:plain

2-2 Nginxインストール

1)Nginxをインストールします
①ECSへログインします(この時、ECSで設定しているSecurity GroupのインバウンドPortとして、Port22と80を設定します) f:id:sbc_ohara:20210823135844p:plain

②下記コマンドでnginxをインストールします

# yum install nginx  -y

f:id:sbc_ohara:20210823135856p:plain

f:id:sbc_ohara:20210823135904p:plain

2)下記コマンドでNginxを起動します

# systemctl start nginx
# systemctl status nginx

f:id:sbc_ohara:20210823135921p:plain

3)テストとして、Nginxサーバーへアクセスします(数回)

f:id:sbc_ohara:20210823135935p:plain

4)nginx.configファイルにlog_formatを確認します

cat /etc/nginx/nginx.conf 
  log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

f:id:sbc_ohara:20210823140012p:plain

5)Nginx logを確認します

# tail -f /var/log/nginx/access.log

f:id:sbc_ohara:20210823140026p:plain

3.ECSでfilebeatをインストール

3-1.ECSでfilebeatをインストールします

# wget https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-6.2.4-linux-x86_64.tar.gz

1)filebeatをECSにダウンロードします

f:id:sbc_ohara:20210823160645p:plain

2)filebeatを解凍します

# tar -zvxf filebeat-6.2.4-linux-x86_64.tar.gz

f:id:sbc_ohara:20210823160700p:plain

f:id:sbc_ohara:20210823160709p:plain

3)filebeatのフォルダ名を変更します

# mv filebeat-6.2.4-linux-x86_64 filebeat
# ll

f:id:sbc_ohara:20210823160725p:plain

3-2.filebeat設定

1)filebeat.ymlを設定します

# cd /usr/local/logstash/filebeat
# vim filebeat.yml

filebeat.prospectorとLogstashのoutputを設定します

filebeat.prospectors:
input_type: log
enabled: true
 paths:
    - /var/log/nginx/acc*.log
exclude_files: ['.gz$']

output.logstash:
hosts: ["localhost:5044"]

※LogstashはPort5044を使用するため、ECSのSecurityGroupでPort 5044を許可する必要があります
※outputはLogstashのみを設定します

f:id:sbc_ohara:20210823160915p:plain

f:id:sbc_ohara:20210823160924p:plain

f:id:sbc_ohara:20210823160933p:plain

4.ECSでLogstashをインストール

4-1.Java1.8をインストールします

1)jdk1.8を用意します
①jdk-8u144-linux-x64.tar.gzをダウンロードします
(下記リンクからでもjdkダウンロードができます)

www.oracle.com

f:id:sbc_ohara:20210823161031p:plain

②jdk-8u144-linux-x64.tar.gzをjavaフォルダへ解凍します

# mkdir /usr/local/java/
# tar -zxvf jdk-8u144-linux-x64.tar.gz -C /usr/local/java/
# cd /usr/local/java/
# ll

f:id:sbc_ohara:20210823161049p:plain

f:id:sbc_ohara:20210823161057p:plain

2)Java環境を設定します
①Java環境パスを設定します

# vim /etc/profile
    export JAVA_HOME=/usr/local/java/jdk1.8.0_144
    export PATH=${JAVA_HOME}/bin:$PATH
    export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
    export JRE_HOME=$JAVA_HOME/jre

f:id:sbc_ohara:20210823161113p:plain

②Java環境パスを有効化します

# source /etc/profile
# ln -s /usr/local/java/jdk1.8.0_144/bin/java /usr/bin/java

f:id:sbc_ohara:20210823161135p:plain

③Javaバージョンを確認します

java -version

f:id:sbc_ohara:20210823161149p:plain

4-2.ECSでLogstashインストール

1)ECSでLogstashをインストールします

# cd /usr/local
# mkdir logstash
# cd logstash
# wget https://artifacts.elastic.co/downloads/logstash/logstash-7.0.0.tar.gz
# ll

①logstashをECSにダウンロードします

f:id:sbc_ohara:20210823161212p:plain

②logstashを解凍します

# tar -xzvf logstash-7.0.0.tar.gz
# cd logstash-7.0.0
# ll

f:id:sbc_ohara:20210823161227p:plain

f:id:sbc_ohara:20210823161235p:plain

4-3.LogstashのClickHouseプラグインをインストール

1)ClickHouseプラグインをインストールします
①logstash-output-clickhouseプラグインをインストールします

# cd /usr/local/logstash/logstash-7.0.0
# ll
# ./bin/logstash-plugin install logstash-output-clickhouse

f:id:sbc_ohara:20210823161312p:plain

2)filterのプラグインをインストールします
②logstash-filter-pruneとlogstash-filter-multilineのプラグインをインストールします

# ./bin/logstash-plugin install logstash-filter-prune
# ./bin/logstash-plugin install logstash-filter-multiline

f:id:sbc_ohara:20210823161334p:plain

4-4.Logstashを設定

1)logstash-sample.confを開きます

# cd /usr/local/logstash/
# ll
# cd logstash-7.0.0/
# cd config/
# ll
# vim logstash-sample.conf

f:id:sbc_ohara:20210823161402p:plain

2)logstash-sample.confを編集します

input {
  beats {
    port => 5044
    host => "127.0.0.1"
    client_inactivity_timeout => 36000
  }
}

filter { 
  grok {
    match =>["message",'%{IPORHOST:remote_addr} - (%{USERNAME:remote_user}|-) \[%{HTTPDATE:nginx_timestamp}\] %{HOSTNAME:http_host} %{WORD:request_method} %{URIPATH:uri} %{BASE10NUM:http_status} %{BASE10NUM:body_bytes_sent} (%{BASE10NUM:upstream_status}|-) (?:%{HOSTPORT:upstream_addr}|-) (%{BASE16FLOAT:request_time}|-) (%{BASE16FLOAT:upstream_response_time}|-) (?<http_user_agent>[^"]*)']
    }
  date {
    locale => "en" 
    match =>["nginx_timestamp" , "dd/MMM/YYYY:HH:mm:ss Z"]
  }
  mutate {
    convert => [
       "request_time","float",
       "body_bytes_sent","integer",
       "upstream_response_time","float",
       "http_status","integer"
    ]
    remove_field => [
      "message", "@timestamp", "source", "@version", "beat", "offset", "tags", "prospector"
    ]
  }
}

output {
  clickhouse {
    http_hosts =>["http://172.16.0.74:8123"]
    headers => ["Authorization", "Basic c2J0ZXN0OlRlc3QxMjM0"]
    table => "nginx_logstash_local"
    request_tolerance => 1
    flush_size => 32
    pool_max => 128
  }
  stdout {
    codec => json
  }
}

上記設定内容として、、
input・・・デフォルトのBeats
Filter・・・matchはNginxログと一致していること
output:・・・output先として次の設定通り

http_hosts:ClickHouseのVPCエンドポイントのIPを設定する(今回はECSとClickHouseが同じVPC内であるため、Intranetで接続)
headers:c2J0ZXN0OlRlc3QxMjM0の形式は admin:password のBase64コードとなります
table:ターゲットテーブルです。ターゲットテーブルのパラメータがNginxログとmatchと一致していること

f:id:sbc_ohara:20210823161755p:plain

f:id:sbc_ohara:20210823161804p:plain

f:id:sbc_ohara:20210823161811p:plain

5.LogstashでデータをClickHouseに格納

5-1.ClickHouseでターゲットテーブルを作成します

1)ローカルテーブルを作成します
①DMSでClickHouseをログインし、デフォルトDBで下記のテーブルを作成します

CREATE TABLE default.nginx_logstash_local
(
    remote_addr String,
    remote_user String,
    nginx_timestamp String,
    http_host String,
    request_method String,
    uri String,
    http_status UInt32,
    body_bytes_sent UInt32,
    upstream_status UInt32,
    upstream_addr String,
    request_time Float32,
    upstream_response_time Float32,
    http_user_agent String
)
ENGINE = MergeTree() ORDER BY remote_addr SETTINGS index_granularity = 8192

f:id:sbc_ohara:20210823161836p:plain

2)分散テーブルを作成します

CREATE TABLE nginx_logstash_distributed ON CLUSTER default as nginx_logstash_local ENGINE = Distributed(default, default, nginx_logstash_local, rand());

f:id:sbc_ohara:20210823161855p:plain

5-2.Logstashとfilebeatを実行し、NginxのアクセスログをClickhouseへ格納

1)nginxがすでに起動されていることを確認します

# systemctl status nginx

f:id:sbc_ohara:20210823161923p:plain

2)logstashを起動します
①下記コマンドでlogstashを起動します

# cd /usr/local/logstash/logstash-7.0.0
# ll
# nohup ./bin/logstash -f ./config/logstash-sample.conf &

f:id:sbc_ohara:20210823161935p:plain

②logstashを確認します

# ps aux|grep logstash

f:id:sbc_ohara:20210823161952p:plain

3)下記コマンドでfilebeatを起動します

①下記コマンドでfilebeatを起動します

# cd /usr/local/logstash/filebeat
# ll
# nohup ./filebeat -e -c filebeat.yml &

f:id:sbc_ohara:20210823162006p:plain

②filebeatを確認します

# ps aux|grep filebeat

f:id:sbc_ohara:20210823162022p:plain

4)テストとして、nginx web page を10回アクセスします

f:id:sbc_ohara:20210823162052p:plain

5)nginxアクセスログを確認します

# cd /var/log/nginx
# ll
# tail -f -n 10 ./access.log

f:id:sbc_ohara:20210823163505p:plain

6)logstashログを確認します

# cd /usr/local/logstash/logstash-7.0.0
# ll
# cat nohup.out

f:id:sbc_ohara:20210823162123p:plain

f:id:sbc_ohara:20210823162131p:plain

6)filebeatログを確認します

# cd /usr/local/logstash/filebeat
# ll
# cat nohup.out

f:id:sbc_ohara:20210823162144p:plain

f:id:sbc_ohara:20210823162152p:plain

5-3.ClickhouseでNginxのアクセスログデータを確認します

1)nginx_logstash_localを確認します
①データを確認します

select * from nginx_logstash_local;

f:id:sbc_ohara:20210823162205p:plain

f:id:sbc_ohara:20210823162213p:plain

②データ件数を確認します

select count(*) from nginx_logstash_local;

f:id:sbc_ohara:20210823162228p:plain

2)nginx_logstash_distributedを確認します
①データを確認します

select * from nginx_logstash_distributed

f:id:sbc_ohara:20210823162244p:plain

f:id:sbc_ohara:20210823162253p:plain

②データ件数を確認します

select count(*) from nginx_logstash_distributed

f:id:sbc_ohara:20210823162303p:plain


最後に

ここまで、nginxアクセスログを Logstash(filebeat)- ApsaraDB for ClickHouseへ連携する方法を紹介しました。
ApsaraDB for ClickHouseはLogstash(filebeat)とスムーズに連携できるので、例えば、WebサーバーのデータをLogstash(filebeat)で収集し、 ApsaraDB for ClickHouseへリアルタイムデータ連携しながら、ClickHouseでリアルタイム可視化、といったソリューションを構築することもできます。

Special Thanks, Nancy