Ubuntu 18.04でElastic Stackを使用してマネージRedisデータベース統計を分析する方法

著者は、Write for DOnationsプログラムの一部として寄付を受け取るためにFree and Open Source Fundを選択しました。

前書き

データベース監視は、データベースのパフォーマンスを示すさまざまなメトリックを体系的に追跡する継続的なプロセスです。 パフォーマンスデータを観察することで、貴重な洞察を得て、考えられるボトルネックを特定し、データベースのパフォーマンスを向上させる追加の方法を見つけることができます。 そのようなシステムは、多くの場合、問題が発生したときに管理者に通知するアラートを実装しています。 収集された統計を使用して、データベースの構成とワークフローだけでなく、クライアントアプリケーションの構成とワークフローも改善できます。

管理対象データベースの監視にElastic Stack(ELKスタック)を使用する利点は、検索の優れたサポートと、新しいデータを非常に迅速に取り込む機能です。 データの更新には優れていませんが、このトレードオフは、過去のデータがほとんど変更されない監視およびログ記録の目的には受け入れられます。 Elasticsearchは、データをクエリする強力な手段を提供します。これをKibanaで使用すると、データベースがさまざまな期間でどのように処理されるかをよりよく理解できます。 これにより、データベースの負荷を実際のイベントと関連付けて、データベースの使用方法に関する洞察を得ることができます。

このチュートリアルでは、RedisINFOコマンドによって生成されたデータベースメトリックをLogstashを介してElasticsearchにインポートします。 これには、コマンドを定期的に実行し、その出力を解析し、すぐにインデックス作成のためにElasticsearchに送信するようにLogstashを構成する必要があります。 インポートされたデータは、後で分析し、Kibanaで視覚化できます。 チュートリアルの終わりまでに、後で分析するためにRedis統計を取り込む自動システムができます。

前提条件

  • 少なくとも4 GBのRAM、ルート権限、およびセカンダリの非ルートアカウントを持つUbuntu 18.04サーバー。 これは、this initial server setup guideに従って設定できます。 このチュートリアルでは、root以外のユーザーはsammyです。

  • サーバーにインストールされたJava 8。 インストール手順については、How To Install Java with apt on Ubuntu 18.04にアクセスしてください。

  • サーバーにインストールされたNginx。 これを行う方法のガイドについては、How To Install Nginx on Ubuntu 18.04を参照してください。

  • サーバーにインストールされているElasticsearchとKibana。 How To Install Elasticsearch, Logstash, and Kibana (Elastic Stack) on Ubuntu 18.04チュートリアルの最初の2つのステップを完了します。

  • DigitalOceanからプロビジョニングされた、接続情報が利用可能なRedis管理データベース。 サーバーのIPアドレスがホワイトリストに登録されていることを確認してください。 DigitalOceanマネージドデータベースの詳細については、product docsにアクセスしてください。

  • How To Connect to a Managed Database on Ubuntu 18.04チュートリアルに従って、サーバーにインストールされたRedli

[[step-1 -—- installing-and-configuring-logstash]] ==ステップ1—Logstashのインストールと構成

このセクションでは、Logstashをインストールし、Redisデータベースクラスターから統計をプルするように構成し、それらを解析して、インデックス作成のためにElasticsearchに送信します。

次のコマンドでLogstashをインストールすることから始めます。

sudo apt install logstash -y

Logstashをインストールしたら、ブート時にサービスが自動的に開始されるようにします。

sudo systemctl enable logstash

Logstashを構成して統計を取得する前に、データ自体がどのように見えるかを見てみましょう。 Redisデータベースに接続するには、管理対象データベースのコントロールパネルに移動し、Connection detailsパネルでドロップダウンからFlagsを選択します。

Managed Database Control Panel

データベースへの接続に使用するRedliクライアント用に事前構成されたコマンドが表示されます。 Copyをクリックし、サーバーで次のコマンドを実行して、redli_flags_commandをコピーしたばかりのコマンドに置き換えます。

redli_flags_command info

このコマンドの出力は長いため、これをさまざまなセクションに分けて説明します。

Redisinfoコマンドの出力では、セクションはコメントを示す#でマークされています。 値はkey:valueの形式で入力されるため、比較的簡単に解析できます。

Output# Server
redis_version:5.0.4
redis_git_sha1:ab60b2b1
redis_git_dirty:1
redis_build_id:7909f4de3561dc50
redis_mode:standalone
os:Linux 5.2.14-200.fc30.x86_64 x86_64
arch_bits:64
multiplexing_api:epoll
atomicvar_api:atomic-builtin
gcc_version:9.1.1
process_id:72
run_id:ddb7b96c93bbd0c369c6d06ce1c02c78902e13cc
tcp_port:25060
uptime_in_seconds:1733
uptime_in_days:0
hz:10
configured_hz:10
lru_clock:8687593
executable:/usr/bin/redis-server
config_file:/etc/redis.conf

# Clients
connected_clients:3
client_recent_max_input_buffer:2
client_recent_max_output_buffer:0
blocked_clients:0

. . .

Serverセクションには、バージョンやベースとなるGitコミットなど、Redisビルドに関する技術情報が含まれています。 一方、Clientsセクションには、現在開いている接続の数が表示されます。

Output. . .
# Memory
used_memory:941560
used_memory_human:919.49K
used_memory_rss:4931584
used_memory_rss_human:4.70M
used_memory_peak:941560
used_memory_peak_human:919.49K
used_memory_peak_perc:100.00%
used_memory_overhead:912190
used_memory_startup:795880
used_memory_dataset:29370
used_memory_dataset_perc:20.16%
allocator_allocated:949568
allocator_active:1269760
allocator_resident:3592192
total_system_memory:1030356992
total_system_memory_human:982.62M
used_memory_lua:37888
used_memory_lua_human:37.00K
used_memory_scripts:0
used_memory_scripts_human:0B
number_of_cached_scripts:0
maxmemory:463470592
maxmemory_human:442.00M
maxmemory_policy:allkeys-lru
allocator_frag_ratio:1.34
allocator_frag_bytes:320192
allocator_rss_ratio:2.83
allocator_rss_bytes:2322432
rss_overhead_ratio:1.37
rss_overhead_bytes:1339392
mem_fragmentation_ratio:5.89
mem_fragmentation_bytes:4093872
mem_not_counted_for_evict:0
mem_replication_backlog:0
mem_clients_slaves:0
mem_clients_normal:116310
mem_aof_buffer:0
mem_allocator:jemalloc-5.1.0
active_defrag_running:0
lazyfree_pending_objects:0
. . .

ここで、Memoryは、Redisがそれ自体に割り当てたRAMの量と、使用できる可能性のあるメモリの最大量を確認します。 メモリが不足し始めると、コントロールパネルで指定した戦略を使用してキーが解放されます(この出力のmaxmemory_policyフィールドに表示されます)。

Output. . .
# Persistence
loading:0
rdb_changes_since_last_save:0
rdb_bgsave_in_progress:0
rdb_last_save_time:1568966978
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:0
rdb_current_bgsave_time_sec:-1
rdb_last_cow_size:217088
aof_enabled:0
aof_rewrite_in_progress:0
aof_rewrite_scheduled:0
aof_last_rewrite_time_sec:-1
aof_current_rewrite_time_sec:-1
aof_last_bgrewrite_status:ok
aof_last_write_status:ok
aof_last_cow_size:0

# Stats
total_connections_received:213
total_commands_processed:2340
instantaneous_ops_per_sec:1
total_net_input_bytes:39205
total_net_output_bytes:776988
instantaneous_input_kbps:0.02
instantaneous_output_kbps:2.01
rejected_connections:0
sync_full:0
sync_partial_ok:0
sync_partial_err:0
expired_keys:0
expired_stale_perc:0.00
expired_time_cap_reached_count:0
evicted_keys:0
keyspace_hits:0
keyspace_misses:0
pubsub_channels:0
pubsub_patterns:0
latest_fork_usec:353
migrate_cached_sockets:0
slave_expires_tracked_keys:0
active_defrag_hits:0
active_defrag_misses:0
active_defrag_key_hits:0
active_defrag_key_misses:0
. . .

Persistenceセクションでは、Redisが保存したキーを最後にディスクに保存した時刻と、成功したかどうかを確認できます。 Statsセクションには、クライアント接続とクラスター内接続に関連する数値、要求されたキーが検出された(または検出されなかった)回数などが表示されます。

Output. . .
# Replication
role:master
connected_slaves:0
master_replid:9c1d345a46d29d08537981c4fc44e312a21a160b
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:46137344
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
. . .

[.note]#Note: Redisプロジェクトでは、ドキュメントやさまざまなコマンドで「マスター」および「スレーブ」という用語を使用しています。 DigitalOceanは通常、「プライマリ」と「レプリカ」という代替用語を好みます。
このガイドでは、可能な限りデフォルトで「プライマリ」と「レプリカ」という用語を使用しますが、「マスター」という用語が使用される場合もあることに注意してください。やむを得ず「奴隷」が出てきます。

Replicationの下のroleを見ると、プライマリノードとレプリカノードのどちらに接続しているかがわかります。 セクションの残りの部分では、現在接続されているレプリカの数と、プライマリに関してレプリカに不足しているデータの量を提供します。 接続しているインスタンスがレプリカである場合、追加のフィールドがあります。

Output. . .
# CPU
used_cpu_sys:1.972003
used_cpu_user:1.765318
used_cpu_sys_children:0.000000
used_cpu_user_children:0.001707

# Cluster
cluster_enabled:0

# Keyspace

CPUの下に、システム(used_cpu_sys)とユーザー(used_cpu_user)のCPURedisが現在消費している量が表示されます。 Clusterセクションには、Redisクラスターが実行されていることを示す1つの一意のフィールドcluster_enabledのみが含まれます。

Logstashは、Redisデータベースでinfoコマンドを定期的に実行し(今行った方法と同様)、結果を解析してElasticsearchに送信するように指示されます。 これで、後でKibanaからそれらにアクセスできるようになります。

ElasticsearchのRedis統計にインデックスを付けるための構成を、Logstashが構成ファイルを保存する/etc/logstash/conf.dディレクトリの下のredis.confという名前のファイルに保存します。 サービスとして開始されると、バックグラウンドで自動的に実行されます。

お気に入りのエディター(nanoなど)を使用してredis.confを作成します。

sudo nano /etc/logstash/conf.d/redis.conf

次の行を追加します。

/etc/logstash/conf.d/redis.conf

input {
    exec {
        command => "redis_flags_command info"
        interval => 10
        type => "redis_info"
    }
}

filter {
    kv {
        value_split => ":"
        field_split => "\r\n"
        remove_field => [ "command", "message" ]
    }

    ruby {
        code =>
        "
        event.to_hash.keys.each { |k|
            if event.get(k).to_i.to_s == event.get(k) # is integer?
                event.set(k, event.get(k).to_i) # convert to integer
            end
            if event.get(k).to_f.to_s == event.get(k) # is float?
                event.set(k, event.get(k).to_f) # convert to float
            end
        }
        puts 'Ruby filter finished'
        "
    }
}

output {
    elasticsearch {
        hosts => "http://localhost:9200"
        index => "%{type}"
    }
}

redis_flags_commandを、手順の前半で使用したコントロールパネルに表示されているコマンドに置き換えることを忘れないでください。

収集されたデータに対して実行されるフィルターのセットであるinputと、フィルター処理されたデータをElasticsearchに送信する出力を定義します。 入力はexecコマンドで構成され、設定された時間interval(秒単位で表される)の後にサーバー上で定期的にcommandを実行します。 また、Elasticsearchでインデックスを作成するときにドキュメントタイプを定義するtypeパラメータも指定します。 execブロックは、command文字列とmessage文字列の2つのフィールドを含むオブジェクトを渡します。 commandフィールドには実行されたコマンドが含まれ、messageにはその出力が含まれます。

入力から収集されたデータに対して順次実行される2つのフィルターがあります。 kvフィルターは、Key-Valueフィルターの略で、Logstashに組み込まれています。 これは、keyvalue_separatorvalueの一般的な形式でデータを解析するために使用され、値およびフィールド区切り文字と見なされるものを指定するためのパラメーターを提供します。 フィールドセパレータは、一般形式でフォーマットされたデータを互いに分離する文字列に関係します。 Redis INFOコマンドの出力の場合、フィールド区切り文字(field_split)は改行であり、値区切り文字(value_split)は:です。 定義されたフォームに従わない行は、コメントを含めて破棄されます。

kvフィルタを設定するには、:を `value_split`パラメータに渡し、 (改行を示す)をfield_splitパラメータに渡します。 また、commandフィールドとmessageフィールドを配列の要素としてremove_fieldに渡すことにより、現在のデータオブジェクトから削除するように命令します。これらのフィールドには、現在は役に立たないデータが含まれているためです。

kvフィルターは、設計により文字列(テキスト)タイプとして解析された値を表します。 これは、実際に数字であっても、Kibanaが文字列型を簡単に処理できないために問題を引き起こします。 これを解決するには、可能な場合は、カスタムRubyコードを使用して、数字のみの文字列を数字に変換します。 2番目のフィルターはrubyブロックであり、実行するコードを含む文字列を受け入れるcodeパラメーターを提供します。

eventは、Logstashがコードに提供する変数であり、フィルターパイプラインの現在のデータが含まれています。 前に述べたように、フィルターは次々に実行されます。つまり、Rubyフィルターはkvフィルターから解析されたデータを受け取ります。 Rubyコード自体は、eventをハッシュに変換してキーをトラバースし、キーに関連付けられた値が整数または浮動小数点数(10進数の数値)として表現できるかどうかを確認します。 可能な場合、文字列値は解析された数値に置き換えられます。 ループが終了すると、進行状況を報告するメッセージ(Ruby filter finished)が出力されます。

出力は、インデックス付けのために処理されたデータをElasticsearchに送信します。 結果のドキュメントはredis_infoインデックスに保存され、入力で定義され、パラメータとして出力ブロックに渡されます。

ファイルを保存して閉じます。

aptを使用してLogstashをインストールし、Redisに統計を定期的に要求して処理し、Elasticsearchインスタンスに送信するように構成しました。

[[step-2 -—- testing-the-logstash-configuration]] ==ステップ2—Logstash構成のテスト

Logstashを実行して構成をテストし、データが適切にプルされることを確認します。

Logstashは、ファイルパスを-fパラメータに渡すことにより、特定の構成の実行をサポートします。 次のコマンドを実行して、最後の手順の新しい構成をテストします。

sudo /usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/redis.conf

出力の表示には時間がかかる場合がありますが、すぐに次のようなものが表示されます。

OutputWARNING: Could not find logstash.yml which is typically located in $LS_HOME/config or /etc/logstash. You can specify the path using --path.settings. Continuing using the defaults
Could not find log4j2 configuration at path /usr/share/logstash/config/log4j2.properties. Using default config which logs errors to the console
[WARN ] 2019-09-20 11:59:53.440 [LogStash::Runner] multilocal - Ignoring the 'pipelines.yml' file because modules or command line options are specified
[INFO ] 2019-09-20 11:59:53.459 [LogStash::Runner] runner - Starting Logstash {"logstash.version"=>"6.8.3"}
[INFO ] 2019-09-20 12:00:02.543 [Converge PipelineAction::Create
] pipeline - Starting pipeline {:pipeline_id=>"main", "pipeline.workers"=>2, "pipeline.batch.size"=>125, "pipeline.batch.delay"=>50} [INFO ] 2019-09-20 12:00:03.331 [[main]-pipeline-manager] elasticsearch - Elasticsearch pool URLs updated {:changes=>{:removed=>[], :added=>[http://localhost:9200/]}} [WARN ] 2019-09-20 12:00:03.727 [[main]-pipeline-manager] elasticsearch - Restored connection to ES instance {:url=>"http://localhost:9200/"} [INFO ] 2019-09-20 12:00:04.015 [[main]-pipeline-manager] elasticsearch - ES Output version determined {:es_version=>6} [WARN ] 2019-09-20 12:00:04.020 [[main]-pipeline-manager] elasticsearch - Detected a 6.x and above cluster: the `type` event field won't be used to determine the document _type {:es_version=>6} [INFO ] 2019-09-20 12:00:04.071 [[main]-pipeline-manager] elasticsearch - New Elasticsearch output {:class=>"LogStash::Outputs::ElasticSearch", :hosts=>["http://localhost:9200"]} [INFO ] 2019-09-20 12:00:04.100 [Ruby-0-Thread-5: :1] elasticsearch - Using default mapping template [INFO ] 2019-09-20 12:00:04.146 [Ruby-0-Thread-5: :1] elasticsearch - Attempting to install template {:manage_template=>{"template"=>"logstash-*", "version"=>60001, "settings"=>{"index.refresh_interval"=>"5s"}, "mappings"=>{"_default_"=>{"dynamic_templates"=>[{"message_field"=>{"path_match"=>"message", "match_mapping_type"=>"string", "mapping"=>{"type"=>"text", "norms"=>false}}}, {"string_fields"=>{"match"=>"*", "match_mapping_type"=>"string", "mapping"=>{"type"=>"text", "norms"=>false, "fields"=>{"keyword"=>{"type"=>"keyword", "ignore_above"=>256}}}}}], "properties"=>{"@timestamp"=>{"type"=>"date"}, "@version"=>{"type"=>"keyword"}, "geoip"=>{"dynamic"=>true, "properties"=>{"ip"=>{"type"=>"ip"}, "location"=>{"type"=>"geo_point"}, "latitude"=>{"type"=>"half_float"}, "longitude"=>{"type"=>"half_float"}}}}}}}} [INFO ] 2019-09-20 12:00:04.295 [[main]-pipeline-manager] exec - Registering Exec Input {:type=>"redis_info", :command=>"...", :interval=>10, :schedule=>nil} [INFO ] 2019-09-20 12:00:04.315 [Converge PipelineAction::Create
] pipeline - Pipeline started successfully {:pipeline_id=>"main", :thread=>"#"} [INFO ] 2019-09-20 12:00:04.483 [Ruby-0-Thread-1: /usr/share/logstash/lib/bootstrap/environment.rb:6] agent - Pipelines running {:count=>1, :running_pipelines=>[:main], :non_running_pipelines=>[]} [INFO ] 2019-09-20 12:00:05.318 [Api Webserver] agent - Successfully started Logstash API endpoint {:port=>9600} Ruby filter finished Ruby filter finished Ruby filter finished ...

Ruby filter finishedメッセージが定期的に(前のステップで10秒に設定されて)出力されているのがわかります。これは、統計がElasticsearchに送信されていることを意味します。

キーボードのCTRL + Cをクリックすると、Logstashを終了できます。 前述のように、Logstashは、サービスとして開始されると、バックグラウンドで/etc/logstash/conf.dの下にあるすべての構成ファイルを自動的に実行します。 次のコマンドを実行して起動します。

sudo systemctl start logstash

Logstashを実行して、Redisクラスターに接続してデータを収集できるかどうかを確認しました。 次に、Kibanaの統計データのいくつかを調べます。

[[step-3 -—- exploring-imported-data-in-kibana]] ==ステップ3—Kibanaでインポートされたデータを探索する

このセクションでは、Kibanaでのデータベースのパフォーマンスを説明する統計データを調べて視覚化します。

Webブラウザーで、前提条件の一部としてKibanaを公開したドメインに移動します。 デフォルトのウェルカムページが表示されます。

Kibana - Welcome Page

LogstashがElasticsearchに送信するデータを調べる前に、まずredis_infoインデックスをKibanaに追加する必要があります。 これを行うには、左側の垂直サイドバーからManagementをクリックしてから、Kibanaセクションの下のIndex Patternsをクリックします。

Kibana - Index Pattern Creation

新しいIndex Patternを作成するためのフォームが表示されます。 Kibanaのインデックスパターンは、複数のElasticsearchインデックスからデータを一度にプルする方法を提供し、1つのインデックスのみを探索するために使用できます。

Index patternテキストフィールドの下に、redis_infoインデックスが一覧表示されます。 テキストフィールドに入力して、Next stepボタンをクリックします。

その後、タイムスタンプフィールドを選択するように求められるため、後で時間範囲で検索を絞り込むことができます。 Logstashは、@timestampと呼ばれるものを自動的に追加します。 ドロップダウンからそれを選択し、Create index patternをクリックして、Kibanaへのインデックスの追加を終了します。

Kibana - Index Pattern Timestamp Selection

既存のビジュアライゼーションを作成して表示するには、左側の垂直メニューのVisualizeアイテムをクリックします。 次のページが表示されます。

Kibana - Visualizations

新しいビジュアライゼーションを作成するには、Create a visualizationボタンをクリックし、ポップアップするタイプのリストからLineを選択します。 次に、作成したばかりのredis_info*インデックスパターンをデータソースとして選択します。 空の視覚化が表示されます。

Kibana - Empty Visualization

左側のパネルには、Kibanaが視覚化の描画に使用するパラメーターを編集するためのフォームがあり、画面の中央部分に表示されます。 画面の右上には、日付範囲ピッカーがあります。 @timestampフィールドがビジュアライゼーションで使用されている場合、Kibanaは範囲ピッカーで指定された時間間隔に属するデータのみを表示します。

指定した時間間隔でのRedisの平均メモリ使用量を視覚化します。 左側のパネルのMetricsの下にあるY-Axisをクリックして展開し、AggregationとしてAverageを選択し、Fieldとしてused_memoryを選択します。 s。 これにより、プロットのY軸に平均値が入力されます。

次に、Bucketsの下のX-Axisをクリックします。 Aggregationには、Date Histogramを選択します。 @timestampFieldとして自動的に選択されます。 次に、パネル上部の青い再生ボタンをクリックして、視覚化を表示します。 データベースが真新しくて使用されていない場合、非常に長い行は表示されません。 ただし、すべての場合において、平均メモリ使用量の正確な描写が表示されます。 結果の視覚化は、ほとんど使用されないか、まったく使用されない場合があります。

Kibana - Redis Memory Usage Visualization

このステップでは、Kibanaを使用して、管理対象のRedisデータベースのメモリ使用量を視覚化しました。 Visual Builderなど、Kibanaが提供する他のプロットタイプを使用して、同時に複数のフィールドを描写するより複雑なグラフを作成することもできます。 これにより、データベースがどのように使用されているかをより深く理解できるようになり、クライアントアプリケーションとデータベース自体の最適化に役立ちます。

結論

これで、Elastic Stackがサーバーにインストールされ、管理されたRedisデータベースから定期的に統計データをプルするように設定されました。 Kibanaまたはその他の適切なソフトウェアを使用してデータを分析および視覚化できます。これにより、データベースのパフォーマンスに関する貴重な洞察と現実の相関を収集できます。

Redisマネージデータベースでできることの詳細については、product docsにアクセスしてください。 別の視覚化タイプを使用してデータベース統計を表示する場合は、Kibana docsで詳細な手順を確認してください。

Related