MongoDB AtlasをPrometheusでモニタリングしよう #MongoDBAtlas #Prometheus
この記事は1年以上前に投稿されました。情報が古い可能性がありますので、ご注意ください。
はじめに
MongoDB Atlasは、MongoDB社が提供するDBaaSです。Webから操作するだけで標準でレプリカセット(MongoDBにおける冗長性と高可用性を担保するためにレプリケーション+フェイルオーバーを提供する機能)構成のインスタンスを構築することが出来ます。
標準でもモニタリングやアラートの機能が提供されており、基本的な監視に必要な機能はおさえています。しかし、本番運用にあたって、既存の自前の監視システムに組み込みたい場合もあるでしょう。
近年、監視ツールはPrometheusが台頭しています。Prometheus本体は非常に軽量でシンプルですが、いろいろなexporter(従来の監視エージェントにあたるもの)を組み合わせることで多彩な監視ツールとしての能力を発揮します。また、近年よく聞くクラウドネイティブに特化した監視、オブザーバビリティ的な視点、Grafanaなどの連携するコンポーネントの多さからも利用者を増やしています。
MongoDB Atlasも標準でPrometheusとの連携が可能です。本記事ではAtlasとPrometheusの連携方法について解説していきます。
構成
本記事で構築する構成は以下の通りです。
MongoDB Atlasのクラスタは、登録されたIPアドレスからインターネット越しにアクセス可能とします。今回はVPC PeeringやPrivate Endpointは使用しません。
Prometheusの構築
ここでは詳細な構築手順は割愛します。以下の環境で構築しています。
OS:Debian GNU/Linux 11.0
バージョン:2.24.1+ds-1.b7(ディストリビューション提供パッケージ)
プラットフォーム:ESXi 7.0
Prometheusがインストールされているサーバからインターネットにアクセスできますが、外部IPアドレスは持っていません。今回はpull型(Prometheusがメトリクスを取得しに行く)なので、外部IPアドレスを持っていなくても問題ありません。
Prometheusの環境構築については、以下のドキュメントも参考にしてください。
https://prometheus.io/docs/prometheus/latest/installation/#installation
AtlasでPrometheus連携を有効化する
以下のドキュメントを見ながら進めます。MongoDBは公式ドキュメントがとても充実しているのがありがたいですね!
https://www.mongodb.com/docs/atlas/tutorial/prometheus-integration/
ところで、PrometheusはAtlas上のクラスタ構成やメトリクスをどのように把握するのでしょうか。それを解決するのが、Prometheusのサービスディスカバリです。サービスディスカバリを使用することで、Atlas上の構成変更を自動的にPrometheusに反映します。一度設定してしまえば、基本的に運用担当がPrometheusにAltas上のクラスター構成を登録・更新する必要がありません。
Atlasは2種類のサービスディスカバリに対応しています。HTTP SDとファイルベースのサービスディスカバリが使用できます。今回は後者を利用します。
御託はこれぐらいにして、早速有効化してみましょう。Prometheusとの連携は、project単位で行います。project名の横の三点から「Integrations」を選択します。
「Configure」を選ぶと有効化されます。
Prometheus Configrationが表示されました。
ここで表示されるユーザ名とパスワードは、後ほどDiscovery APIに問い合わせる際のクレデンシャルとして使用します。メモしておいてください。
忘れると作り直しになります。パスワードは任意の文字列でも、「Autogenerate Secure Password」で生成しても構いません。Service Discovery Methodは、特に問題がなければHTTP SDを選んだ方が良いでしょう。PrometheusからHTTPでのインターネット接続が可能で、バージョンがv2.28以降なら使用できます。
しかし、今回のように、ディストリビューションパッケージのPrometheusだと古くて対応しておらず、File Service Discoveryしか選べない場合があります。ひとまずここはこちらで設定を進めます。
画像内の①にも書いてある通り、PrometheusからのアクセスをAtlas側で許可してやる必要があります。この許可リストはAtlasのインスタンスへの接続許可リストと共通です。コメントにPrometheus用途であることを記載しておきましょう。棚卸のときにうっかり消されて使えなくなった!ということが防げます。
画像内の③が、実際にprometheus.ymlに設定する内容です。手元にコピーしておきます。
Prometheus側の設定
prometheus.ymlに先ほどコピーした内容を追記します。
file_sd_configs内で指定したファイル(atlas_target.json)が、MongoDBのDiscobery APIにアクセスして取得する、サービスディスカバリ用のターゲットファイルです。ここでは任意の名前と場所にしておいてください。
以下のドキュメントに従って、Atlas用のターゲットファイルを取得します。
https://www.mongodb.com/docs/atlas/reference/third-party-integration-settings-discovery/
いろいろな方法がありますが、ここでは一番簡単にcurlコマンドで取得してみましょう。
ユーザ名とパスワードは、Atlas上でPrometheusを有効化するときに取得したものをここで使用します。Project IDはProject Settingから確認できます。
curl --header 'Accept: application/json' --user prom_user_xxxxxxxxxx:<password> --request GET "https://cloud.mongodb.com/prometheus/v1.0/groups/<Project ID>/discovery"
JSON形式で構成が返ってこれば成功です。
Filebase Service Directoryの詳細については以下のドキュメントも参考にしてください。
https://prometheus.io/docs/guides/file-sd/
終わったらPrometheusをリロードします。
sudo systemctl reload prometheus
PrometheusのWebUIにアクセスしてTargetを見てみましょう。データを取得してStateがUpになっていればOKです。MongoDB Atlasはデフォルトで3台でレプリカセットを構成するため、Targetのエンドポイントは1クラスタあたり3つとなります。
先ほど設定したatlas_target.jsonは定期的に更新する仕組みを入れておきましょう。こうすることでAtlas側で発生した構成変更をPrometheusに自動的に反映してくれます。
今回はJSONを取得するスクリプトをpythonで書き、systemd timerで定期的に動作するようにします。
#!/usr/bin/env python3 import urllib.request import shutil import json import base64 url = 'https://cloud.mongodb.com/prometheus/v1.0/groups/<Project ID>/discovery' user = 'prom_user_xxxxxxxxxxxxxxxxxxxxxxxxxx' passwd = '<Password>' # base64にエンコードしheaderに付帯 base64_user_pass = base64.b64encode('{}:{}'.format(user,passwd).encode('utf-8')) headers = { "Accept": "application/json","Authorization": "Basic "+base64_user_pass.decode('utf-8')} req = urllib.request.Request(url, headers=headers) with urllib.request.urlopen(req) as res: #body = res.read().decode('utf-8') if res.status == 200: with open('/etc/prometheus/atlas_target.json',mode='bw') as f: shutil.copyfileobj(res,f) else: print("Error: ",res.status)
SystemdのUnitファイルを作ります。
youta@prometheus-sv /lib/systemd/system $cat atlas-json-update.service [Unit] Description=Prometheus JSON Update for MongoDB Atlas [Service] Type=oneshot ExecStart=/etc/prometheus/atlas_get.py [Install] WantedBy=multi-user.target
timerファイルも作ります。
youta@prometheus-sv /lib/systemd/system $cat atlas-json-update.timer [Unit] Description=JSON Update for MongoDB Atlas [Timer] # ブート後1分後にタイマーを開始 OnBootSec=1min # 10秒毎に実行 OnUnitActiveSec=10s Unit=atlas-json-update.service [Install] WantedBy=multi-user.target
systemdコマンドで対象Unitを有効化して、実際に動作しているか確認します。
youta@prometheus-sv ~ $sudo systemctl status atlas-json-update ● atlas-json-update.service - Prometheus JSON Update for MongoDB Atlas Loaded: loaded (/lib/systemd/system/atlas-json-update.service; enabled; vendor preset: enabled) Active: inactive (dead) since Wed 2023-09-27 15:12:29 JST; 9s ago TriggeredBy: ● atlas-json-update.timer Main PID: 696906 (code=exited, status=0/SUCCESS) CPU: 37ms 9月 27 15:12:28 prometheus-sv systemd[1]: Starting Prometheus JSON Update for MongoDB Atlas... 9月 27 15:12:29 prometheus-sv systemd[1]: atlas-json-update.service: Succeeded. 9月 27 15:12:29 prometheus-sv systemd[1]: Finished Prometheus JSON Update for MongoDB Atlas.
これで定期的にターゲットファイルが更新されるようになりました。
補足:ターゲットファイルの更新に影響はないのですが、以下のログが定期的に出るようになりました。
Sep 27 13:37:10 prometheus-sv prometheus[274242]: level=error ts=2023-09-27T04:37:10.044Z caller=file.go:344 component="discovery manager scrape" discovery=file msg="Error reading file" path=/etc/prometheus/atlas_target.json err="unexpected end of JSON input"
JSONファイルそのものは問題なさそうなので、おそらく以下のissueに該当したものと考えています。
https://github.com/prometheus/prometheus/issues/12383
クラスタの追加・削除を検知できるか試す
MongoDB Atlas上でクラスタを追加し、Prometheusに自動的に反映されるか確認してみましょう。増やす前のTargetsはこうなっていました。
Atlas上でcluster1を追加してみました。
Prometheus上のTargetsも追加されていました。
その後クラスタを削除したら、Targetからも消えていました。今の環境では試せていないので断言できないのですが、HTTP SDであればjsonの取得スクリプトとsystemd timerの設定なしでPrometheusが継続的にTargetを更新してくれるはずです。
Prometheusで利用可能なメトリクスは以下のドキュメントを参照してください。
まとめ
今回はMongoDB AtlasでPrometheusを使う方法について書きました。DBaaSのようなサービスではモニタリングが不要と捉える方もいるかもしれませんが、実際はオートスケールの発生や構成変更、それに伴う月額使用料の増額などといったように、取得したいメトリクスが従来から変わってきたように感じます。この記事が誰かの参考になれば幸いです。