はじめに
ハイパフォーマンスで多彩な機能として人気のデータベース用プロキシ ProxySQL ですが、ネイティブなクラスタ機能を有していることをご存じでしょうか。
v1.4.2 で実験的に実装され、その後 Bug 修正もありつつ、v2.1.0, 2.4.0 で多数の機能改善があり、現在は安定した機能となっています。
今回はこの ProxySQL Cluster について紹介したいと思います。
ProxySQL Cluster の概要
クラスタ、というキーワードが付くと多くの場合は一般的な HA クラスタ(高可用性構成)を思い浮かべてしまうかもしれません。
ProxySQL Cluster はそのような機能ではなく、おおまかに説明すると「クラスタメンバー間で設定の自動同期ができるようになる」というのが機能の主旨です。
ProxySQL 自体は分散型プロキシですので、ProxySQL Cluster は負荷分散クラスタリングの位置付けと言えます。
クラスタ機能を有効にすると、同期可能な設定情報が変更されるたび、チェックサムを生成するようになります。
このチェックサムとその生成・変更日時をクラスタメンバーが互いに監視しあい、他のピアで発生した変更分を(比較して適宜)自ノードに反映する、というものです。
上記については、「現時点のバージョン(執筆時点の最新は v2.4.5) では、」 という但し書きを補足しておきたいと思います。
というのも公式ドキュメント中には、以下の開発ロードマップが記されていて、
プライマリ-セカンダリ構成のクラスタであったり、現在のような Pull 型の同期方式ではなく、MySQL レプリケーションのような Push 型 にデザインする構想があるようです。
Roadmap
This is an overview of the features related to clustering, and not a complete list. None the following is impletemented yet.
Implementation may be different than what is listed right now:
- support for master election: the word master was intentionally chosen instead of leader
- only master proxy is writable/configurable
- implementation of MySQL-like replication from master to slaves, allowing to push configuration in real-time instead of pulling it
- implementation of MySQL-like replication from master to candidate-masters
- implementation of MySQL-like replication from candidate-masters to slaves
- creation of a quorum with only candidate-masters: normal slaves are not part of the quorum
現状では設定同期のみか…、と思われるかもしれませんが、ProxySQL は複数ノードで利用されることが多いので(アプリケーションサーバと同居する構成が推奨)、ProxySQL Cluster を有効にすることで以下のメリットがあります。
- 設定変更は1ノードのみで行えばよくなる
- 作業やチェックにかかるコストが削減される
- もし Ansible や Chef などの構成管理ツールを用いて自動化していた場合は、それらの仕組みが不要になる
- Ansible だと、Community.Proxysql コレクションが公開されていたりしますが、バージョンアップを追随したりする必要もなくなります。
- ノード追加が容易になる
- クラスタメンバーに追加するだけで、設定情報が同期できるので、簡単にスケールアウトすることができます。
また、設定が自動同期される、ということは、例えば DB 側のレプリケーションフェイルオーバが発生し、何らかの仕組みで ProxySQL 内の接続先DB情報(mysql_servers
, mysql_replication_hostgroups
) が更新された場合、クラスタメンバーもほぼ同タイミングで新しい接続先DBセットを参照できるようにもなります。
これらのメリットを踏まえると、冗長化・スケーラビリティの向上・高可用性構成の補助的な機能向上に貢献、といった効果があると言えます。
同期対象の設定情報
以下のクラスター用 GLOBAL 変数(チェックサム生成要否)を true
(デフォルト) にすることで同期対象となります。
1 2 3 4 5 6 7 8 9 10 11 12 |
Admin> SHOW VARIABLES LIKE 'admin-checksum_%'; +----------------------------------+-------+ | Variable_name | Value | +----------------------------------+-------+ | admin-checksum_mysql_query_rules | true | | admin-checksum_mysql_servers | true | | admin-checksum_mysql_users | true | | admin-checksum_mysql_variables | true | | admin-checksum_admin_variables | true | | admin-checksum_ldap_variables | true | +----------------------------------+-------+ 6 rows in set (0.00 sec) |
基本的に ProxySQL を使用するうえでの主要テーブルが同期対象となっています。
runtime_checksums_values
テーブルでは、 version
が 1以上のモジュール(設定情報)が該当します。
1 2 3 4 5 6 7 8 9 10 11 12 |
Admin> SELECT * FROM runtime_checksums_values; +-------------------+---------+------------+--------------------+ | name | version | epoch | checksum | +-------------------+---------+------------+--------------------+ | admin_variables | 2 | 1673414818 | 0xE91E48EBCDD39863 | | mysql_query_rules | 2 | 1673414943 | 0xBD3B25C8289D9083 | | mysql_servers | 2 | 1673414858 | 0x6210CDBF15E2F4A0 | | mysql_users | 3 | 1673414943 | 0xECC427D29D8D9533 | | mysql_variables | 3 | 1673414903 | 0xE022855E29693A2F | | proxysql_servers | 1 | 1673414734 | 0x0000000000000000 | +-------------------+---------+------------+--------------------+ 6 rows in set (0.00 sec) |
上記確認結果から分かる通り、6モジュールが v2.4 の時点で同期可能です。
主要な設定情報(mysql_servers,mysql_users,mysql_query_rules)と、GLOBAL変数(admin_variables,mysql_variables)、そしてクラスタメンバー情報テーブル(proxysql_servers)が同期の対象となっています。
※version
は自ノードで Runtime へ設定を反映(LOAD ... TO RUNTIME
)するとカウントアップされます。
引用:Configuring ProxySQL – ProxySQL
ProxySQL Cluster の公式ドキュメントページには明記が無いですが、Admin Variables ページ の 各 admin-checksum_%
変数の説明文や、リリースノートとソースコードを見ると、正確には以下の設定情報も同期されます。
mysql_users
の同期時に、ldap_auth_plugin
プラグインが見つかったら、ldap_variables
(ldap-%) とmysql_ldap_mapping
を同期mysql_query_rules
の同期時に、mysql_query_rules_fast_routing
も同期mysql_servers
の同期時に、以下のデータも同期mysql_replication_hostgroups
mysql_group_replication_hostgroups
mysql_galera_hostgroups
mysql_aws_aurora_hostgroups
※以下の公式ブログ記事は、v1.4 で ProxySQL Cluster が初期リリースされた頃の内容で、4モジュールのみが同期対象となっていますのでご注意ください。
Native ProxySQL Clustering now available – ProxySQL
注意事項
-
すべての設定が同期されるわけではない点に気を付けてください。
具体的には、以下の設定は現時点のバージョンでは同期されません。(今後追加されるかもしれません)
- Firewall whitelist 関連
mysql_firewall_whitelist_rules
mysql_firewall_whitelist_sqli_fingerprints
mysql_firewall_whitelist_users
- REST API 設定
restapi_routes
- Scheduler 設定
scheduler
- Firewall whitelist 関連
-
v2.1.0 以降は、クラスタメンバー同士の ProxySQL のバージョンを揃える必要があります。(異なるバージョン間の同期不整合を防ぐため)
クラスタ設定の確認
それでは、実際に ProxySQL Cluster の構築を行ってみたいと思います。
使用環境
- ProxySQL : v2.4.5
- OS : Rocky Linux 8.6
インストール手順は公式ドキュメントページをご参照ください。
または、公式の Docker イメージもありますので、そちらで手軽に試すこともできます。
クラスタ構成シナリオ
今回は各種設定済み ProxySQL ノードをシードとして、クラスタを構成してみたいと思います。
※未設定状態の 新規 ProxySQL ノード同士でまずクラスタを構成したのち、設定を投入して同期する、という流れも可能です。
- シードノード(hostname:rha-proxy-01) は、
mysql_servers
,mysql_users
,mysql_query_rules
に各種設定を投入済み、GLOBAL 変数も一部変更済みの状態です。 - 追加ノード(rha-proxy-02)は、ProxySQL サービスを起動後、管理者ユーザのパスワードを変更したのみの状態です。
クラスタ用パラメータの設定
シードノード、追加ノードそれぞれで ProxySQL の CLI 管理コンソールにログインし、同一の各パラメータを設定していきます。
※bootstrap用の構成ファイル(/etc/proxysql.cnf
) に設定して起動、という方法でも勿論可能です。
まずは、クラスタ構成に最低限必要なパラメータとして、クラスタメンバー間の相互認証用にクラスタ専用のユーザ名とパスワードを設定します。
admin-admin_credentials
にも追加しておく必要があります。
1 2 3 |
Admin> SET admin-admin_credentials="admin:ProxySQL1;rha-db-cluster:ProxySQL2"; Admin> SET admin-cluster_username="rha-db-cluster"; Admin> SET admin-cluster_password="ProxySQL2"; |
なお、ProxySQL ノード同士の認証は MySQL プロトコルで行われます。
ちなみに ProxySQL Cluster にはクラスタ名の設定がありません。複数の異なるクラスタを構成したい場合は、クラスタごとに一意となる admin-cluster_username
を設定します。(1つの ProxySQL ノードが複数のクラスタに属することはできません)
以降のパラメータはデフォルトのままでも構いませんが、今回は説明のため敢えて取り上げています。
以下は、チェック間隔のパラメータです。デフォルト値を記載していますが、適宜変更してください。
1 2 |
Admin> SET admin-cluster_check_interval_ms=1000; Admin> SET admin-cluster_check_status_frequency=10; |
以下は、他のピアから設定を同期した後、自ノードの Disk にすぐ同期(永続化)するか否かを指定するパラメータです。(デフォルト:true
)
1 2 3 4 |
Admin> SET admin-cluster_mysql_query_rules_save_to_disk="true"; Admin> SET admin-cluster_mysql_servers_save_to_disk="true"; Admin> SET admin-cluster_mysql_users_save_to_disk="true"; Admin> SET admin-cluster_proxysql_servers_save_to_disk="true"; |
以下は、指定回数チェックされるのを待ってから同期を行うパラメータです。
1 2 3 4 |
Admin> SET admin-cluster_mysql_query_rules_diffs_before_sync=3; Admin> SET admin-cluster_mysql_servers_diffs_before_sync=3; Admin> SET admin-cluster_mysql_users_diffs_before_sync=3; Admin> SET admin-cluster_proxysql_servers_diffs_before_sync=3; |
-
これは、各ProxySQL はそれぞれが独立してバックエンドDBの状態をチェックしていていて、以下のようなイベントが発生した場合、互いに同じ動作を行うので、同期する必要が無く、非常に短い時間で同じ設定内容に収束する可能性があるためです。
- レプリケーショントポロジーの変化を検出
- 一時的にNW遅延状態などの理由でヘルスチェック失敗したバックエンドDBとの接続を切断 (参考:Backend Monitoring – ProxySQL)
- レプリケーション遅延発生により閾値(
mysql_servers.max_replication_lag
)を超過したレプリカサーバが追い付くまで接続断
admin-cluster_*_diffs_before_sync
で指定した回数のチェックののち、まだローカルとリモートとで設定に差分がある場合、同期が実行されるようになります。
ここまでのパラメータを Runtime にロードおよび Disk に永続化しておきます。
1 2 |
Admin> LOAD ADMIN VARIABLES TO RUNTIME; Admin> SAVE ADMIN VARIABLES TO DISK; |
ちなみに、それぞれのクラスタメンバーが異なる設定変更を各自で実行した場合、最後にロードされた設定が反映されます。(後勝ち方式)
ただし、異なる設定が同時にロードされた場合においては、競合の解決が不可能なため、収束しないポイントまで反映することになります。
クラスタノードの登録
こちらもシードノード、追加ノードそれぞれで同一設定を投入します。
proxysql_servers
へクラスタメンバーを登録し、Runtime にロードするとすぐに、ピアのチェックと設定の同期が行われます。
1 2 3 4 5 |
Admin> INSERT INTO proxysql_servers (hostname,port,comment) VALUES ('192.168.101.166',6032,'rha-proxy-01'); Admin> INSERT INTO proxysql_servers (hostname,port,comment) VALUES ('192.168.101.205',6032,'rha-proxy-02'); Admin> LOAD PROXYSQL SERVERS TO RUNTIME; Admin> SAVE PROXYSQL SERVERS TO DISK; |
各ProxySQLのログファイル(/var/lib/proxysql/proxysql.log
)に、クラスタの同期状況が次々と出力されていきます。(ログ量が多いのでここでは割愛します)
シードノードで事前投入していた設定情報のうち同期対象の設定内容は、もれなく追加ノードにも反映されていました。(こちらも割愛します)
これでクラスタの構成は完了です。
なお、公式ドキュメントには 3ノードでの設定例が紹介されていますが、最小ノードが3ということではありません。
クラスタとしての Bootstrap は (今回のように)1ノードからでも可能です。
ノード追加時
ノード追加する際は、やはり同じように新規ノードでクラスタ用のパラメータを設定した後、proxysql_servers
へは以下のように設定投入します。
- 新規ノードにて、全クラスタメンバーの情報を登録します。
- この時点で、新規ノードは既存クラスタメンバーから設定情報を Pull して同期します。
しかし、既存メンバーは新規ノードをソースとした同期は行いません。(自ノードのproxysql_servers
テーブルに登録がないのでソースとしての信頼性が無いと見做されるため)
- この時点で、新規ノードは既存クラスタメンバーから設定情報を Pull して同期します。
- 既存の任意の1ノードにて、新規ノードの情報を登録します。
- すべてのクラスタメンバーの
proxysql_servers
テーブルに新規ノードの情報が追加されて初めて、新規ノードは正式にクラスタメンバーとして参加となります。
クラスタの状態確認
以下、新たに追加されたクラスタ用の各種テーブルを参照することで、クラスタの状態を確認することができます。
-
proxysql_servers
テーブルでクラスタに参加しているメンバーを確認することができます。12345678Admin> SELECT * FROM proxysql_servers;+-----------------+------+--------+--------------+| hostname | port | weight | comment |+-----------------+------+--------+--------------+| 192.168.101.166 | 6032 | 0 | rha-proxy-01 || 192.168.101.205 | 6032 | 0 | rha-proxy-02 |+-----------------+------+--------+--------------+2 rows in set (0.00 sec)※
weight
(重み付け) は現在機能せず、今後の開発ロードマップでの拡張が予定されているようです。 -
クラスタ同期の状況を監視するための以下のテーブルが stats に追加されています。
123456789Admin> SHOW TABLES FROM stats;:| stats_proxysql_message_metrics || stats_proxysql_message_metrics_reset || stats_proxysql_servers_checksums || stats_proxysql_servers_clients_status || stats_proxysql_servers_metrics || stats_proxysql_servers_status |:上記のうち、
stats_proxysql_message_metrics
,stats_proxysql_message_metrics_reset
,stats_proxysql_servers_status
はまだ使用できず、空のテーブルです。-
stats_proxysql_servers_checksums
テーブルではクラスタメンバーごとの各同期モジュールのチェックサムや変更日時を俯瞰することができます。123456789101112131415161718Admin> SELECT * FROM stats_proxysql_servers_checksums;+-----------------+------+-------------------+---------+------------+--------------------+------------+------------+------------+| hostname | port | name | version | epoch | checksum | changed_at | updated_at | diff_check |+-----------------+------+-------------------+---------+------------+--------------------+------------+------------+------------+| 192.168.101.205 | 6032 | admin_variables | 3 | 1673424449 | 0x46B8291D3E5A9E2F | 1673424522 | 1673426322 | 0 || 192.168.101.205 | 6032 | mysql_query_rules | 2 | 1673414943 | 0xBD3B25C8289D9083 | 1673425074 | 1673426322 | 0 || 192.168.101.205 | 6032 | mysql_servers | 2 | 1673414858 | 0x6210CDBF15E2F4A0 | 1673425074 | 1673426322 | 0 || 192.168.101.205 | 6032 | mysql_users | 2 | 1673414943 | 0xECC427D29D8D9533 | 1673425074 | 1673426322 | 0 || 192.168.101.205 | 6032 | mysql_variables | 2 | 1673415683 | 0x337C6C75238066CD | 1673425074 | 1673426322 | 0 || 192.168.101.205 | 6032 | proxysql_servers | 2 | 1673425071 | 0xE26992C386875B83 | 1673425071 | 1673426322 | 0 || 192.168.101.166 | 6032 | admin_variables | 6 | 1673424449 | 0x46B8291D3E5A9E2F | 1673424526 | 1673426323 | 0 || 192.168.101.166 | 6032 | mysql_query_rules | 2 | 1673414943 | 0xBD3B25C8289D9083 | 1673424522 | 1673426323 | 0 || 192.168.101.166 | 6032 | mysql_servers | 2 | 1673414858 | 0x6210CDBF15E2F4A0 | 1673424522 | 1673426323 | 0 || 192.168.101.166 | 6032 | mysql_users | 3 | 1673414943 | 0xECC427D29D8D9533 | 1673424522 | 1673426323 | 0 || 192.168.101.166 | 6032 | mysql_variables | 5 | 1673415683 | 0x337C6C75238066CD | 1673424522 | 1673426323 | 0 || 192.168.101.166 | 6032 | proxysql_servers | 2 | 1673424522 | 0xE26992C386875B83 | 1673424522 | 1673426323 | 0 |+-----------------+------+-------------------+---------+------------+--------------------+------------+------------+------------+12 rows in set (0.01 sec) -
stats_proxysql_servers_clients_status
テーブルではクラスタに参加するときの各ノードの UUID(起動オプション-U
または--uuid
で指定可能。指定なしの場合は自動生成) やホスト名、ポート番号といった情報が確認できます。12345678Admin> SELECT * FROM stats_proxysql_servers_clients_status;+--------------------------------------+-----------------+-------+--------------------+--------------+| uuid | hostname | port | admin_mysql_ifaces | last_seen_at |+--------------------------------------+-----------------+-------+--------------------+--------------+| 52e6ba59-1cdc-458b-8c37-b3a62f493d76 | 192.168.101.205 | 47442 | 0.0.0.0:6032 | 1673426333 || 4f776f9a-e1b4-4810-8424-8d8197e0866c | 192.168.101.166 | 33216 | 0.0.0.0:6032 | 1673426334 |+--------------------------------------+-----------------+-------+--------------------+--------------+2 rows in set (0.00 sec) -
stats_proxysql_servers_metrics
テーブルでは各クラスタメンバーの稼働状況統計が確認できます。12345678Admin> SELECT * FROM stats_proxysql_servers_metrics;+-----------------+------+--------+--------------+------------------+----------+---------------+---------+------------------------------+----------------------------+| hostname | port | weight | comment | response_time_ms | Uptime_s | last_check_ms | Queries | Client_Connections_connected | Client_Connections_created |+-----------------+------+--------+--------------+------------------+----------+---------------+---------+------------------------------+----------------------------+| 192.168.101.205 | 6032 | 0 | rha-proxy-02 | 5 | 11608 | 1156 | 0 | 0 | 0 || 192.168.101.166 | 6032 | 0 | rha-proxy-01 | 4 | 11607 | 1623 | 0 | 0 | 0 |+-----------------+------+--------+--------------+------------------+----------+---------------+---------+------------------------------+----------------------------+2 rows in set (0.00 sec)
-
ノード削除時
いずれかのクラスタメンバーノードで proxysql_servers
テーブルから対象ノードのレコードを削除します。
削除対象ノードから実行しても問題ありません。(この設定変更までクラスタメンバーに伝搬されるため)
1 2 3 |
Admin> DELETE FROM proxysql_servers WHERE hostname = '192.168.101.205' and port = '6032'; Admin> LOAD PROXYSQL SERVERS TO RUNTIME; Admin> SAVE PROXYSQL SERVERS TO DISK; |
その他注意事項など
本記事で取り上げていない仕様や制約事項などは 公式ドキュメント の Q&A セクションを確認することをお勧めします。
おわりに
今回紹介しました通り、ProxySQL Cluster は専用の設定を追加するだけの簡単な手順でクラスタ化が構成可能です。
個々の ProxySQL ノードで設定の同期が困難な環境は安易に導入できないかもしれませんが、多くの場合は標準的にクラスタ化しておくことのメリットは大きいのではと思いますので、ぜひ試してみてはいかがでしょうか。
開発ロードマップに挙がっている機能拡張が今後どのように進んでいくのかも非常に楽しみです。