CockroachDB をスケールインするお話
今回は CockroachDB クラスタをスケールインする方法についてのお話です。スケールイン (クラスタからのノード削除) の方法については、公式ドキュメントの Decommission Nodes にも記載されています。
環境
今回は以下の環境 (Docker を利用したローカルの Insecure クラスタ) で検証しています。
Ubuntu : 19.10
Docker : 19.03.5
CockroachDB : 19.2.5
Container Image : cockroachdb/cockroach
クラスタ構築 (スケールイン前)
まずは以下のような 7匹構成のクラスタ (Insecure クラスタ) を構築します。
$ sudo docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a5f098cb2d3c cockroachdb/cockroach:v19.2.5 "/cockroach/cockroac…" 2 minutes ago Up 2 minutes 26257/tcp, 127.0.0.1:8087->8080/tcp cockroach-7 c59078822378 cockroachdb/cockroach:v19.2.5 "/cockroach/cockroac…" 2 minutes ago Up 2 minutes 26257/tcp, 127.0.0.1:8086->8080/tcp cockroach-6 2b297fe4fe30 cockroachdb/cockroach:v19.2.5 "/cockroach/cockroac…" 3 minutes ago Up 3 minutes 26257/tcp, 127.0.0.1:8085->8080/tcp cockroach-5 41402f232d68 cockroachdb/cockroach:v19.2.5 "/cockroach/cockroac…" 3 minutes ago Up 3 minutes 26257/tcp, 127.0.0.1:8084->8080/tcp cockroach-4 def2c5f6f733 cockroachdb/cockroach:v19.2.5 "/cockroach/cockroac…" 3 minutes ago Up 3 minutes 26257/tcp, 127.0.0.1:8083->8080/tcp cockroach-3 0427c72146e7 cockroachdb/cockroach:v19.2.5 "/cockroach/cockroac…" 3 minutes ago Up 3 minutes 26257/tcp, 127.0.0.1:8082->8080/tcp cockroach-2 dc317ca40cd7 cockroachdb/cockroach:v19.2.5 "/cockroach/cockroac…" 3 minutes ago Up 3 minutes 127.0.0.1:26257->26257/tcp, 127.0.0.1:8081->8080/tcp cockroach-1
$ cockroach node status --insecure id | address | sql_address | build | started_at | updated_at | locality | is_available | is_live +----+-------------------+-------------------+---------+----------------------------------+----------------------------------+----------+--------------+---------+ 1 | cockroach-1:26257 | cockroach-1:26257 | v19.2.5 | 2020-04-08 01:32:31.00667+00:00 | 2020-04-08 01:36:25.063551+00:00 | | true | true 2 | cockroach-2:26257 | cockroach-2:26257 | v19.2.5 | 2020-04-08 01:32:37.648252+00:00 | 2020-04-08 01:36:22.680406+00:00 | | true | true 3 | cockroach-3:26257 | cockroach-3:26257 | v19.2.5 | 2020-04-08 01:32:41.144215+00:00 | 2020-04-08 01:36:21.69463+00:00 | | true | true 4 | cockroach-4:26257 | cockroach-4:26257 | v19.2.5 | 2020-04-08 01:32:45.0741+00:00 | 2020-04-08 01:36:25.622117+00:00 | | true | true 5 | cockroach-5:26257 | cockroach-5:26257 | v19.2.5 | 2020-04-08 01:32:48.51479+00:00 | 2020-04-08 01:36:24.568432+00:00 | | true | true 6 | cockroach-6:26257 | cockroach-6:26257 | v19.2.5 | 2020-04-08 01:32:52.145479+00:00 | 2020-04-08 01:36:23.726916+00:00 | | true | true 7 | cockroach-7:26257 | cockroach-7:26257 | v19.2.5 | 2020-04-08 01:32:55.55426+00:00 | 2020-04-08 01:36:22.604514+00:00 | | true | true (7 rows)
クラスタ構築方法の詳細は割愛しますが、Docker を利用したローカルクラスタの構築方法についてはこちらの記事や、こちらのメモをご覧ください。
テストデータ作成
スケールインした際の動作 (データの動き) を確認するために、root ユーザで DB に接続し、テスト用のテーブル (t0, t1, t2) の作成と適当なデータの INSERT を実施しておきます。
$ sudo docker exec -it cockroach-1 ./cockroach sql --host=cockroach-1 --insecure # # Welcome to the CockroachDB SQL shell. # All statements must be terminated by a semicolon. # To exit, type: \q. # # Server version: CockroachDB CCL v19.2.5 (x86_64-unknown-linux-gnu, built 2020/03/16 18:27:12, go1.12.12) (same version as client) # Cluster ID: 31f31234-d7aa-4ff3-9a40-51498a17bab8 # # Enter \? for a brief introduction. # root@cockroach-1:26257/defaultdb> root@cockroach-1:26257/defaultdb> CREATE TABLE t0 (id INT PRIMARY KEY, c1 INT, c2 INT, c3 INT); CREATE TABLE Time: 69.435726ms root@cockroach-1:26257/defaultdb> root@cockroach-1:26257/defaultdb> CREATE TABLE t1 (id INT PRIMARY KEY, c1 INT, c2 INT, c3 INT); CREATE TABLE Time: 62.660318ms root@cockroach-1:26257/defaultdb> root@cockroach-1:26257/defaultdb> CREATE TABLE t2 (id INT PRIMARY KEY, c1 INT, c2 INT, c3 INT); CREATE TABLE Time: 70.644974ms root@cockroach-1:26257/defaultdb> root@cockroach-1:26257/defaultdb> INSERT INTO t0 SELECT num, (random() * 100)::int, (random() * 100)::int, (random() * 100)::int FROM generate_series(1,1000000) AS num; INSERT 1000000 Time: 15.746965716s root@cockroach-1:26257/defaultdb> root@cockroach-1:26257/defaultdb> INSERT INTO t1 SELECT num, (random() * 100)::int, (random() * 100)::int, (random() * 100)::int FROM generate_series(1,1000000) AS num; INSERT 1000000 Time: 20.899031416s root@cockroach-1:26257/defaultdb> root@cockroach-1:26257/defaultdb> INSERT INTO t2 SELECT num, (random() * 100)::int, (random() * 100)::int, (random() * 100)::int FROM generate_series(1,1000000) AS num; INSERT 1000000 Time: 16.953153829s root@cockroach-1:26257/defaultdb>
テーブル作成後、各テーブル (t0, t1, t2) の Range (Replica) がどのノードに配置されているかを確認します。
root@cockroach-1:26257/defaultdb> SELECT table_name, range_id, replicas FROM crdb_internal.ranges WHERE database_name = 'defaultdb'; table_name | range_id | replicas +------------+----------+----------+ t0 | 26 | {1,5,6} t0 | 29 | {5,6,7} t0 | 45 | {5,6,7} t1 | 27 | {5,6,7} t1 | 30 | {2,5,7} t1 | 31 | {2,5,7} t2 | 28 | {5,6,7} t2 | 32 | {5,6,7} t2 | 33 | {5,6,7} (9 rows) Time: 4.404418ms
crdb_internal.ranges.replicas の数字は各ノードの ID です。ノード ID は cockroach node status
コマンドで確認できます。
$ cockroach node status --insecure id | address | sql_address | build | started_at | updated_at | locality | is_available | is_live +----+-------------------+-------------------+---------+----------------------------------+----------------------------------+----------+--------------+---------+ 1 | cockroach-1:26257 | cockroach-1:26257 | v19.2.5 | 2020-04-08 01:32:31.00667+00:00 | 2020-04-08 01:48:16.051763+00:00 | | true | true 2 | cockroach-2:26257 | cockroach-2:26257 | v19.2.5 | 2020-04-08 01:32:37.648252+00:00 | 2020-04-08 01:48:13.68015+00:00 | | true | true 3 | cockroach-3:26257 | cockroach-3:26257 | v19.2.5 | 2020-04-08 01:32:41.144215+00:00 | 2020-04-08 01:48:17.201878+00:00 | | true | true 4 | cockroach-4:26257 | cockroach-4:26257 | v19.2.5 | 2020-04-08 01:32:45.0741+00:00 | 2020-04-08 01:48:16.630182+00:00 | | true | true 5 | cockroach-5:26257 | cockroach-5:26257 | v19.2.5 | 2020-04-08 01:32:48.51479+00:00 | 2020-04-08 01:48:15.571834+00:00 | | true | true 6 | cockroach-6:26257 | cockroach-6:26257 | v19.2.5 | 2020-04-08 01:32:52.145479+00:00 | 2020-04-08 01:48:14.726143+00:00 | | true | true 7 | cockroach-7:26257 | cockroach-7:26257 | v19.2.5 | 2020-04-08 01:32:55.55426+00:00 | 2020-04-08 01:48:13.615297+00:00 | | true | true (7 rows)
上記結果の場合、各テーブル (t0, t1, t2) のデータは 3つの Range に分割されており、各 Range の Replica (デフォルトだと Range 毎に 3つの Replica が作成される) は以下のように分散されて配置されています。
[t0 のデータ]
Range ID: 26 -> cockroach-1, cockroach-5, cockroach-6 Range ID: 29 -> cockroach-5, cockroach-6, cockroach-7 Range ID: 45 -> cockroach-5, cockroach-6, cockroach-7
[t1 のデータ]
Range ID: 27 -> cockroach-5, cockroach-6, cockroach-7 Range ID: 30 -> cockroach-2, cockroach-5, cockroach-7 Range ID: 31 -> cockroach-2, cockroach-5, cockroach-7
[t2 のデータ]
Range ID: 28 -> cockroach-5, cockroach-6, cockroach-7 Range ID: 32 -> cockroach-5, cockroach-6, cockroach-7 Range ID: 33 -> cockroach-5, cockroach-6, cockroach-7
スケールイン (7匹 -> 6匹)
それでは、CockroachDB をスケールインしてみます。CockroachDB をスケールインする場合は、cockroach quit
コマンドに --decommission
オプションを付け、--host
オプションにスケールイン対象のノードを指定して実行します。
今回は、以下のようなコマンドで cockroach-7 をクラスタから除外してみます。
$ sudo docker exec -it cockroach-1 ./cockroach quit --decommission --host=cockroach-7 --insecure
実際にコマンドを実行すると、指定したノード (cockroach-7) の残り Replica 数が表示され、最終的に replicas 欄の数字が "0" になります。
$ sudo docker exec -it cockroach-1 ./cockroach quit --decommission --host=cockroach-7 --insecure id | is_live | replicas | is_decommissioning | is_draining +----+---------+----------+--------------------+-------------+ 7 | true | 24 | true | false (1 row) ....... id | is_live | replicas | is_decommissioning | is_draining +----+---------+----------+--------------------+-------------+ 7 | true | 23 | true | false (1 row) ....... id | is_live | replicas | is_decommissioning | is_draining +----+---------+----------+--------------------+-------------+ 7 | true | 22 | true | false (1 row) ........ id | is_live | replicas | is_decommissioning | is_draining +----+---------+----------+--------------------+-------------+ 7 | true | 20 | true | false (1 row) ........ id | is_live | replicas | is_decommissioning | is_draining +----+---------+----------+--------------------+-------------+ 7 | true | 19 | true | false (1 row) ..... id | is_live | replicas | is_decommissioning | is_draining +----+---------+----------+--------------------+-------------+ 7 | true | 18 | true | false (1 row) .......... id | is_live | replicas | is_decommissioning | is_draining +----+---------+----------+--------------------+-------------+ 7 | true | 13 | true | false (1 row) ....... id | is_live | replicas | is_decommissioning | is_draining +----+---------+----------+--------------------+-------------+ 7 | true | 12 | true | false (1 row) ........ id | is_live | replicas | is_decommissioning | is_draining +----+---------+----------+--------------------+-------------+ 7 | true | 11 | true | false (1 row) ...... id | is_live | replicas | is_decommissioning | is_draining +----+---------+----------+--------------------+-------------+ 7 | true | 10 | true | false (1 row) ......... id | is_live | replicas | is_decommissioning | is_draining +----+---------+----------+--------------------+-------------+ 7 | true | 8 | true | false (1 row) ......... id | is_live | replicas | is_decommissioning | is_draining +----+---------+----------+--------------------+-------------+ 7 | true | 7 | true | false (1 row) ..... id | is_live | replicas | is_decommissioning | is_draining +----+---------+----------+--------------------+-------------+ 7 | true | 6 | true | false (1 row) ......... id | is_live | replicas | is_decommissioning | is_draining +----+---------+----------+--------------------+-------------+ 7 | true | 5 | true | false (1 row) ........ id | is_live | replicas | is_decommissioning | is_draining +----+---------+----------+--------------------+-------------+ 7 | true | 4 | true | false (1 row) ........ id | is_live | replicas | is_decommissioning | is_draining +----+---------+----------+--------------------+-------------+ 7 | true | 3 | true | false (1 row) .......... id | is_live | replicas | is_decommissioning | is_draining +----+---------+----------+--------------------+-------------+ 7 | true | 2 | true | false (1 row) .......... id | is_live | replicas | is_decommissioning | is_draining +----+---------+----------+--------------------+-------------+ 7 | true | 1 | true | false (1 row) ............ id | is_live | replicas | is_decommissioning | is_draining +----+---------+----------+--------------------+-------------+ 7 | true | 0 | true | false (1 row) No more data reported on target nodes. Please verify cluster health before removing the nodes. ok
最後に "ok" が出力されればスケールイン完了です。cockroach node status
コマンドで確認すると、cockroach-7 がクラスタから除外されている (表示されない) ことが確認できます。
$ cockroach node status --insecure id | address | sql_address | build | started_at | updated_at | locality | is_available | is_live +----+-------------------+-------------------+---------+----------------------------------+----------------------------------+----------+--------------+---------+ 1 | cockroach-1:26257 | cockroach-1:26257 | v19.2.5 | 2020-04-08 01:32:31.00667+00:00 | 2020-04-08 01:50:22.049631+00:00 | | true | true 2 | cockroach-2:26257 | cockroach-2:26257 | v19.2.5 | 2020-04-08 01:32:37.648252+00:00 | 2020-04-08 01:50:24.195174+00:00 | | true | true 3 | cockroach-3:26257 | cockroach-3:26257 | v19.2.5 | 2020-04-08 01:32:41.144215+00:00 | 2020-04-08 01:50:23.201134+00:00 | | true | true 4 | cockroach-4:26257 | cockroach-4:26257 | v19.2.5 | 2020-04-08 01:32:45.0741+00:00 | 2020-04-08 01:50:22.622891+00:00 | | true | true 5 | cockroach-5:26257 | cockroach-5:26257 | v19.2.5 | 2020-04-08 01:32:48.51479+00:00 | 2020-04-08 01:50:21.568323+00:00 | | true | true 6 | cockroach-6:26257 | cockroach-6:26257 | v19.2.5 | 2020-04-08 01:32:52.145479+00:00 | 2020-04-08 01:50:25.221+00:00 | | true | true (6 rows)
また、Admin (Web) UI から見ると、最初は SUSPECT NODES として cockroach-7 が扱われている (カウントされている) ことが確認できます。
[SUSPECT NODES]
5分ほどすると SUSPECT NODES の数が 1 から 0 になり、ノード一覧で cockroach-7 が "Decommissioned Nodes" 欄に表示されます。
[Decommissioned Nodes]
スケールイン完了 (6匹構成になっていること) を確認後、改めて先程作成した各テーブルの Rnage (Replica) がどのノードに配置されているかを確認します。
root@cockroach-1:26257/defaultdb> SELECT table_name, range_id, replicas FROM crdb_internal.ranges WHERE database_name = 'defaultdb'; table_name | range_id | replicas +------------+----------+----------+ t0 | 26 | {1,5,6} t0 | 29 | {4,5,6} t0 | 45 | {3,5,6} t1 | 27 | {3,5,6} t1 | 30 | {2,4,5} t1 | 31 | {2,3,5} t2 | 28 | {1,5,6} t2 | 32 | {1,5,6} t2 | 33 | {4,5,6} (9 rows) Time: 4.471505ms
すると、先程とは Range (Replica) の配置が変わっていることが確認できます。上記結果の場合、各 Range の Replica は以下のように配置されています。スケールイン前と比べて、クラスタから除外した cockroach-7 に格納されていた Replica が他のノードに移動していることが確認できます。
[t0 のデータ]
Range ID: 26 -> cockroach-1, cockroach-5, cockroach-6 Range ID: 29 -> cockroach-4, cockroach-5, cockroach-6 Range ID: 45 -> cockroach-3, cockroach-5, cockroach-6
[t1 のデータ]
Range ID: 27 -> cockroach-3, cockroach-5, cockroach-6 Range ID: 30 -> cockroach-2, cockroach-4, cockroach-5 Range ID: 31 -> cockroach-2, cockroach-3, cockroach-5
[t2 のデータ]
Range ID: 28 -> cockroach-1, cockroach-5, cockroach-6 Range ID: 32 -> cockroach-1, cockroach-5, cockroach-6 Range ID: 33 -> cockroach-4, cockroach-5, cockroach-6
また、Admin UI (Web UI) の Metrics タブ (http://localhost:8081/#/metrics/overview/cluster) を開くと、"Replicas per Node" の項目で各ノードが保持している Replica 数の推移をグラフで見ることができます。
今回のようにスケールインすると、以下のように各ノードが保持している Replica 数が変化していること (cockroach-7 が保持していた replica が他のノードに移動していること) が確認できます。
[Replicas per Node]
また、表示されているグラフをマウスオーバーすると、各ノードが保持している Replica 数が表示されます。各タイミング (7匹構成, 6匹構成) における各ノードが保持している Replica 数は以下のようになっています。
[7匹構成 (スケールイン前)]
[6匹構成 (スケールイン後)]
スケールイン前 (7匹構成) は各ノードが 19 ~ 24 の Replica を保持していますが、6匹構成時 (スケールイン後) は各ノードが 24 ~ 26 の Replica を保持しており、1ノードあたりの Replica 数が増加していることが確認できます。
スケールイン (6匹 -> 5匹)
同じように cockroach-6 もクラスタから除外してみます。
$ sudo docker exec -it cockroach-1 ./cockroach quit --decommission --host=cockroach-6 --insecure
$ sudo docker exec -it cockroach-1 ./cockroach quit --decommission --host=cockroach-6 --insecure id | is_live | replicas | is_decommissioning | is_draining +----+---------+----------+--------------------+-------------+ 6 | true | 25 | true | false (1 row) ......... id | is_live | replicas | is_decommissioning | is_draining +----+---------+----------+--------------------+-------------+ 6 | true | 23 | true | false (1 row) ....... id | is_live | replicas | is_decommissioning | is_draining +----+---------+----------+--------------------+-------------+ 6 | true | 22 | true | false (1 row) .... id | is_live | replicas | is_decommissioning | is_draining +----+---------+----------+--------------------+-------------+ 6 | true | 21 | true | false (1 row) ... id | is_live | replicas | is_decommissioning | is_draining +----+---------+----------+--------------------+-------------+ 6 | true | 20 | true | false (1 row) ........ id | is_live | replicas | is_decommissioning | is_draining +----+---------+----------+--------------------+-------------+ 6 | true | 19 | true | false (1 row) ....... id | is_live | replicas | is_decommissioning | is_draining +----+---------+----------+--------------------+-------------+ 6 | true | 18 | true | false (1 row) ....... id | is_live | replicas | is_decommissioning | is_draining +----+---------+----------+--------------------+-------------+ 6 | true | 17 | true | false (1 row) .... id | is_live | replicas | is_decommissioning | is_draining +----+---------+----------+--------------------+-------------+ 6 | true | 15 | true | false (1 row) .... id | is_live | replicas | is_decommissioning | is_draining +----+---------+----------+--------------------+-------------+ 6 | true | 14 | true | false (1 row) ......... id | is_live | replicas | is_decommissioning | is_draining +----+---------+----------+--------------------+-------------+ 6 | true | 12 | true | false (1 row) .......... id | is_live | replicas | is_decommissioning | is_draining +----+---------+----------+--------------------+-------------+ 6 | true | 10 | true | false (1 row) ......... id | is_live | replicas | is_decommissioning | is_draining +----+---------+----------+--------------------+-------------+ 6 | true | 6 | true | false (1 row) ........ id | is_live | replicas | is_decommissioning | is_draining +----+---------+----------+--------------------+-------------+ 6 | true | 5 | true | false (1 row) ......... id | is_live | replicas | is_decommissioning | is_draining +----+---------+----------+--------------------+-------------+ 6 | true | 3 | true | false (1 row) ...... id | is_live | replicas | is_decommissioning | is_draining +----+---------+----------+--------------------+-------------+ 6 | true | 2 | true | false (1 row) ...... id | is_live | replicas | is_decommissioning | is_draining +----+---------+----------+--------------------+-------------+ 6 | true | 1 | true | false (1 row) ........... id | is_live | replicas | is_decommissioning | is_draining +----+---------+----------+--------------------+-------------+ 6 | true | 0 | true | false (1 row) No more data reported on target nodes. Please verify cluster health before removing the nodes. ok
$ sudo docker exec -it cockroach-1 ./cockroach node status --insecure id | address | sql_address | build | started_at | updated_at | locality | is_available | is_live +----+-------------------+-------------------+---------+----------------------------------+----------------------------------+----------+--------------+---------+ 1 | cockroach-1:26257 | cockroach-1:26257 | v19.2.5 | 2020-04-08 01:32:31.00667+00:00 | 2020-04-08 02:00:52.046273+00:00 | | true | true 2 | cockroach-2:26257 | cockroach-2:26257 | v19.2.5 | 2020-04-08 01:32:37.648252+00:00 | 2020-04-08 02:00:49.703439+00:00 | | true | true 3 | cockroach-3:26257 | cockroach-3:26257 | v19.2.5 | 2020-04-08 01:32:41.144215+00:00 | 2020-04-08 02:00:53.19274+00:00 | | true | true 4 | cockroach-4:26257 | cockroach-4:26257 | v19.2.5 | 2020-04-08 01:32:45.0741+00:00 | 2020-04-08 02:00:52.624689+00:00 | | true | true 5 | cockroach-5:26257 | cockroach-5:26257 | v19.2.5 | 2020-04-08 01:32:48.51479+00:00 | 2020-04-08 02:00:51.564729+00:00 | | true | true (5 rows)
root@cockroach-1:26257/defaultdb> SELECT table_name, range_id, replicas FROM crdb_internal.ranges WHERE database_name = 'defaultdb'; table_name | range_id | replicas +------------+----------+----------+ t0 | 26 | {1,2,5} t0 | 29 | {3,4,5} t0 | 45 | {2,3,5} t1 | 27 | {1,3,5} t1 | 30 | {2,4,5} t1 | 31 | {2,3,5} t2 | 28 | {1,3,5} t2 | 32 | {1,4,5} t2 | 33 | {2,4,5} (9 rows) Time: 4.367832ms
[Decommissioned Nodes]
[Replicas per Node]
[6匹構成 (スケールイン前)]
[5匹構成 (スケールイン後)]
上記の通り、6匹目もクラスタから除外することができました。
まとめ
CockroachDB はとてもシンプルな手順でスケールインすることができます。
ただし、以前の記事で紹介したスケールアウトの時と同じように、クラスタから除外するノードが保持していた Replica が他のノードに移動することになるので、スケールイン実施時におけるクラスタ内のネットワーク帯域や各ノードのディスク I/O には注意が必要な雰囲気 (一時的に負荷が上がる可能性がありそう) です。