From a787851b41f99cbcfff42f4dde4d5c1810ea6ad6 Mon Sep 17 00:00:00 2001 From: marregui Date: Fri, 31 Jan 2020 15:08:07 +0100 Subject: [PATCH 1/8] Add tutorial on how to downscale a Vanilla cluster The tutorial is really my draft for answering https://community.crate.io/t/from-three-node-cluster-to-single-node/326 so I want it to be self contained and on context. I will likely work on it during the weekend. I will amend this commit message when/if we merge. --- docs/downscaling/README.rst | 202 ++++++++++++++++++++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 docs/downscaling/README.rst diff --git a/docs/downscaling/README.rst b/docs/downscaling/README.rst new file mode 100644 index 0000000..a1b9a15 --- /dev/null +++ b/docs/downscaling/README.rst @@ -0,0 +1,202 @@ +=========== +Downscaling +=========== + +In this tutorial we: + +1. We create a Vanilla cluster. +2. Downscaling!, using replicas. +3. Downscaling!, using snapshots. + + +Starting a Vanilla cluster +-------------------------- + +A Vanilla cluster is a three node cluster that runs on a single host. Each of the +nodes share the file system and operating system scheduler of the host, to form a cluster. +This rig provides parallel processing power on large scale data, when you only have one +host, and this comes at the cost increased latency in writes. + +Steps: + +1. `git clone https://github.com/crate/crate.git` + + Naturally, **git**, **java 11** or later, and a **terminal** are available to you, + and you have an account in GitHub_. + +2. Execute: + + - `cd crate` + - `./gradlew clean` (if you already had the clone) + - `./gradlew distTar`. + +3. Create a folder somewhere, I suggest `~/workspace/DATA`. It should contain this structure: + + - `~/workspace/DATA/dist`: **CrateDB** distributions. + - `~/workspace/DATA/conf`: **CrateDB** configurations, each node has a folder in there, and the + folder contains the `crate.yml` and `log4j2.properties` configuration files. + - `~/workspace/DATA/data`: **CrateDB** data, be mindful on how you setup the `path.data`. + - `~/workspace/DATA/repo`: **CrateDB** repo, be mindful on how you setup the `path.repo`. + - `~/workspace/DATA/startnode`: script to start **CrateDB** on a given config, read on. + - `~/workspace/DATA/crate`: a symlink to a particular distribution in the `dist` folder. + +4. `cp crate/app/build/distributions/crate-X.Y.Z-SNAPSHOT-.tar.xz ~/workspace/DATA/dist` + +5. Execute: + + - `cd ~/workspace/DATA/dist` + - `tar -xzvf crate-X.Y.Z-SNAPSHOT-.tar.xz` + + Now you have a folder `~/workspace/DATA/dist/crate-X.Y.Z` with the latest **CrateDB**. + - `cd ~/workspace/DATA` + - `rm -f crate` + - `ln -s dist/crate-X.Y.Z crate` + +6.- Now we need the configuration for the Vanilla cluster: + + - `cat ~/workspace/DATA/conf/n1/crate.yml` + + :: + + cluster.name: vanilla + node.name: n1 + stats.service.interval: 0 + network.host: _local_ + node.max_local_storage_nodes: 3 + http.cors.enabled: true + http.cors.allow-origin: "*" + transport.tcp.port: 4301 + gateway.expected_nodes: 3 + gateway.recover_after_nodes: 2 + discovery.seed_hosts: + - 127.0.0.1:4301 + - 127.0.0.1:4302 + cluster.initial_master_nodes: + - 127.0.0.1:4301 + - 127.0.0.1:4302 + + - `cat ~/workspace/DATA/conf/n2/crate.yml` + + :: + + cluster.name: vanilla + node.name: n2 + stats.service.interval: 0 + network.host: _local_ + node.max_local_storage_nodes: 3 + http.cors.enabled: true + http.cors.allow-origin: "*" + transport.tcp.port: 4302 + gateway.expected_nodes: 3 + gateway.recover_after_nodes: 2 + discovery.seed_hosts: + - 127.0.0.1:4301 + - 127.0.0.1:4302 + cluster.initial_master_nodes: + - 127.0.0.1:4301 + - 127.0.0.1:4302 + + - `cat ~/workspace/DATA/conf/n2/crate.yml` + + :: + + cluster.name: vanilla + node.name: n3 + stats.service.interval: 0 + network.host: _local_ + node.max_local_storage_nodes: 3 + http.cors.enabled: true + http.cors.allow-origin: "*" + transport.tcp.port: 4303 + gateway.expected_nodes: 3 + gateway.recover_after_nodes: 2 + discovery.seed_hosts: + - 127.0.0.1:4301 + - 127.0.0.1:4302 + cluster.initial_master_nodes: + - 127.0.0.1:4301 + - 127.0.0.1:4302 + + - You may use this `log4j2.properties` setup: + + :: + + status = error + rootLogger.level = info + rootLogger.appenderRef.console.ref = console + # log action execution errors for easier debugging + logger.action.name = org.crate.action.sql + logger.action.level = debug + appender.console.type = Console + appender.console.name = console + appender.console.layout.type = PatternLayout + appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c{1.}] [%node_name] %marker%m%n + +7. The `startnode` script could look something like this: + + :: + + #!/bin/sh + + node_name=default + path_data=$(pwd)/data + path_repo=$(pwd)/repo + case $# in + 1) + node_name=$1 + ;; + + 2) + node_name=$1 + path_data=$2 + ;; + + 3) + node_name=$1 + path_data=$2 + path_repo=$3 + ;; + + -h | -help | --h | --help) + echo "syntax: $0 [node_name [data_path [repo_path]]]" + echo 'defaults: ' + echo " - node_name: default" + echo " - path_data: $path_data" + echo " - path_repo: $path_repo" + exit 1 + ;; + esac + + path_conf="$(pwd)/conf/$node_name" + if [ ! -d $path_conf ]; then + echo "No configuration available in [conf/$node_name]." + exit 1 + fi + + export CRATE_HEAP_SIZE=2G + echo 'setup: ' + echo " - node_name: $node_name" + echo " - path_data: $path_data" + echo " - path_repo: $path_repo" + echo " - CRATE_HEAP_SIZE: $CRATE_HEAP_SIZE" + + ./crate/bin/crate -Cpath.conf=$path_conf -Cpath.data=$path_data -Cpath.repo=$path_repo + +8. Now in three separate terminals, start the three nodes: + + - `./startnode n1` + - `./startnode n2` + - `./startnode n3` + + Which will form the Vanilla cluster. + + +Downscaling (by means of replicas) +---------------------------------- + + +Downscaling (by means of snapshots) +----------------------------------- + + +.. _GitHub: https://github.com/crate/crate.git \ No newline at end of file From c7edea001e147f0b80b71697f777176bae30a9f5 Mon Sep 17 00:00:00 2001 From: marregui Date: Sun, 2 Feb 2020 19:22:43 +0100 Subject: [PATCH 2/8] Add a load data section --- docs/downscaling/README.rst | 160 ++++++++++++++++++++++++++++-------- 1 file changed, 126 insertions(+), 34 deletions(-) diff --git a/docs/downscaling/README.rst b/docs/downscaling/README.rst index a1b9a15..3dcc193 100644 --- a/docs/downscaling/README.rst +++ b/docs/downscaling/README.rst @@ -4,9 +4,9 @@ Downscaling In this tutorial we: -1. We create a Vanilla cluster. -2. Downscaling!, using replicas. -3. Downscaling!, using snapshots. +1. Create a Vanilla cluster. +2. Downscale it!, using replicas. +3. Downscale it!, using snapshots. Starting a Vanilla cluster @@ -17,44 +17,47 @@ nodes share the file system and operating system scheduler of the host, to form This rig provides parallel processing power on large scale data, when you only have one host, and this comes at the cost increased latency in writes. -Steps: +Proceed: -1. `git clone https://github.com/crate/crate.git` +1. *git clone https://github.com/crate/crate.git* - Naturally, **git**, **java 11** or later, and a **terminal** are available to you, + Assumed **git**, **java 11** or later, and a **terminal** are available to you, and you have an account in GitHub_. -2. Execute: +2. - - `cd crate` - - `./gradlew clean` (if you already had the clone) - - `./gradlew distTar`. + - *cd crate* + - *./gradlew clean* (if you already had the clone) + - *./gradlew distTar*. -3. Create a folder somewhere, I suggest `~/workspace/DATA`. It should contain this structure: +3. Create a folder somewhere, I suggest *~/workspace/DATA*. It should contain this structure: - - `~/workspace/DATA/dist`: **CrateDB** distributions. - - `~/workspace/DATA/conf`: **CrateDB** configurations, each node has a folder in there, and the - folder contains the `crate.yml` and `log4j2.properties` configuration files. - - `~/workspace/DATA/data`: **CrateDB** data, be mindful on how you setup the `path.data`. - - `~/workspace/DATA/repo`: **CrateDB** repo, be mindful on how you setup the `path.repo`. - - `~/workspace/DATA/startnode`: script to start **CrateDB** on a given config, read on. - - `~/workspace/DATA/crate`: a symlink to a particular distribution in the `dist` folder. + - *dist*: **CrateDB** distributions. + - *conf*: **CrateDB** configurations, each node in the cluster has a folder in there, with + the *crate.yml* and *log4j2.properties* configuration files in it. + - *data*: **CrateDB** through configuration the nodes will log under *data/nodes/[0,1,2]* + - *repo*: **CrateDB** repo, for snapshotting. + - *startnode*: script to start **CrateDB** with a given config. + - *crate*: a symlink to a particular distribution in the *dist* folder (not the **CrateDB**, + executable script). -4. `cp crate/app/build/distributions/crate-X.Y.Z-SNAPSHOT-.tar.xz ~/workspace/DATA/dist` +4. *cp crate/app/build/distributions/crate-X.Y.Z-SNAPSHOT-.tar.xz ~/workspace/DATA/dist* -5. Execute: +5. - - `cd ~/workspace/DATA/dist` - - `tar -xzvf crate-X.Y.Z-SNAPSHOT-.tar.xz` + - *cd ~/workspace/DATA/dist* + - *tar -xzvf crate-X.Y.Z-SNAPSHOT-.tar.xz* - Now you have a folder `~/workspace/DATA/dist/crate-X.Y.Z` with the latest **CrateDB**. - - `cd ~/workspace/DATA` - - `rm -f crate` - - `ln -s dist/crate-X.Y.Z crate` + At this point you have a folder, *~/workspace/DATA/dist/crate-X.Y.Z*, containing the + latest, unreleased, **CrateDB**. + + - *cd ~/workspace/DATA* + - *rm -f crate* + - *ln -s dist/crate-X.Y.Z crate* 6.- Now we need the configuration for the Vanilla cluster: - - `cat ~/workspace/DATA/conf/n1/crate.yml` + - *cat ~/workspace/DATA/conf/n1/crate.yml* :: @@ -75,7 +78,7 @@ Steps: - 127.0.0.1:4301 - 127.0.0.1:4302 - - `cat ~/workspace/DATA/conf/n2/crate.yml` + - *cat ~/workspace/DATA/conf/n2/crate.yml* :: @@ -96,7 +99,7 @@ Steps: - 127.0.0.1:4301 - 127.0.0.1:4302 - - `cat ~/workspace/DATA/conf/n2/crate.yml` + - *cat ~/workspace/DATA/conf/n3/crate.yml* :: @@ -117,7 +120,8 @@ Steps: - 127.0.0.1:4301 - 127.0.0.1:4302 - - You may use this `log4j2.properties` setup: + - And for convenience, you may use this *log4j2.properties* setup, save it to a file + alongside each *crate.yml*.: :: @@ -132,7 +136,7 @@ Steps: appender.console.layout.type = PatternLayout appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c{1.}] [%node_name] %marker%m%n -7. The `startnode` script could look something like this: +7. The *startnode* script could look something like this: :: @@ -184,17 +188,105 @@ Steps: 8. Now in three separate terminals, start the three nodes: - - `./startnode n1` - - `./startnode n2` - - `./startnode n3` + - *./startnode n1* + - *./startnode n2* + - *./startnode n3* Which will form the Vanilla cluster. +Adding some data to the cluster +------------------------------- + +You can interact with the Vanilla cluster by opening a browser and pointing it to +*http://localhost:4200*. + +Proceed: + +1. Create a table: + + :: + + CREATE TABLE logs (log_time timestamp NOT NULL, + client_ip ip NOT NULL, + request string NOT NULL, + status_code short NOT NULL, + object_size long NOT NULL); + +2. Produce a CSV file with some data for the logs table. You could use a script like: + + :: + + #!/usr/bin/env python3 + + import random + import string + import ipaddress + import time + + + # to achieve log lines as in: + # 2012-01-01T00:00:00Z,25.152.171.147,/books/Six_Easy_Pieces.html,404,271 + # -> timestamp, + # -> random ip address, + # -> random request, + # -> random status code, + # -> random object size, + + def timestamp_range(start, end, format): + st = int(time.mktime(time.strptime(start, format))) + et = int(time.mktime(time.strptime(end, format))) + dt = 1 # 1 sec + fmt = lambda x: time.strftime(format, time.localtime(x)) + return (fmt(x) for x in range(st, et, dt)) + + def rand_ip(): + return str(ipaddress.IPv4Address(random.getrandbits(32))) + + def rand_request(): + rand = lambda src: src[random.randint(0, len(src) - 1)] + path = lambda: "/".join((rand(("usr", "bin", "workspace", "temp", "home", "crate"))) for _ in range(4)) + name = lambda: ''.join(random.sample(string.ascii_lowercase, 7)) + ext = lambda: rand(("html", "pdf", "log", "gif", "jpeg", "js")) + return "{}/{}.{}".format(path(), name(), ext()) + + def rand_object_size(): + return str(random.randint(0, 1024)) + + def rand_status_code(): + return str(random.randint(100, 500)) + + if __name__ == "__main__": + print("log_time,client_ip,request,status_code,object_size") + for ts in timestamp_range("2019-01-01T00:00:00Z", "2019-01-01T01:00:00Z", '%Y-%m-%dT%H:%M:%SZ'): + print(",".join([ts, rand_ip(), rand_request(), rand_status_code(), rand_object_size()])) + + to produce 3600 rows: + + :: + + ./data.py > logs.csv + +3. Load the data: + + :: + + COPY logs FROM 'file:///...../logs.csv'; + REFRESH TABLE logs; + SELECT count(*) FROM logs; + + The three nodes would have performed the copy, so we are expecting to see 3600 * 3 rows, with "repeated" + data. Because we did not define a primary key, **CrateDB** created the default *_id*, which is a + monotonic unique long. + + Downscaling (by means of replicas) ---------------------------------- + + + Downscaling (by means of snapshots) ----------------------------------- From e9b6050abe1edf813ba896005f0b5a69786107a3 Mon Sep 17 00:00:00 2001 From: marregui Date: Tue, 4 Feb 2020 12:48:06 +0100 Subject: [PATCH 3/8] Add some progress --- docs/downscaling/README.rst | 131 +++++++++++++++++++++----- docs/downscaling/imgs/shards-view.png | Bin 0 -> 158516 bytes 2 files changed, 107 insertions(+), 24 deletions(-) create mode 100644 docs/downscaling/imgs/shards-view.png diff --git a/docs/downscaling/README.rst b/docs/downscaling/README.rst index 3dcc193..d7d7de7 100644 --- a/docs/downscaling/README.rst +++ b/docs/downscaling/README.rst @@ -4,18 +4,18 @@ Downscaling In this tutorial we: -1. Create a Vanilla cluster. -2. Downscale it!, using replicas. -3. Downscale it!, using snapshots. +- Create a Vanilla cluster. +- Downscale it, using replicas. +- Downscale it, using snapshots. Starting a Vanilla cluster -------------------------- A Vanilla cluster is a three node cluster that runs on a single host. Each of the -nodes share the file system and operating system scheduler of the host, to form a cluster. -This rig provides parallel processing power on large scale data, when you only have one -host, and this comes at the cost increased latency in writes. +nodes share the file system and operating system scheduler of the host, to form a +cluster. This rig provides parallel processing power on large scale data, when you +only have one host, and this comes at the cost increased latency in writes. Proceed: @@ -30,16 +30,19 @@ Proceed: - *./gradlew clean* (if you already had the clone) - *./gradlew distTar*. -3. Create a folder somewhere, I suggest *~/workspace/DATA*. It should contain this structure: +3. Create a folder somewhere, I suggest *~/workspace/DATA*. It should contain this + structure: - *dist*: **CrateDB** distributions. - - *conf*: **CrateDB** configurations, each node in the cluster has a folder in there, with - the *crate.yml* and *log4j2.properties* configuration files in it. - - *data*: **CrateDB** through configuration the nodes will log under *data/nodes/[0,1,2]* + - *conf*: **CrateDB** configurations, each node in the cluster has a folder + in there, with the *crate.yml* and *log4j2.properties* configuration files + in it. + - *data*: **CrateDB** through configuration the nodes will log under + *data/nodes/[0,1,2]* - *repo*: **CrateDB** repo, for snapshotting. - *startnode*: script to start **CrateDB** with a given config. - - *crate*: a symlink to a particular distribution in the *dist* folder (not the **CrateDB**, - executable script). + - *crate*: a symlink to a particular distribution in the *dist* folder (not + the **CrateDB**, executable script). 4. *cp crate/app/build/distributions/crate-X.Y.Z-SNAPSHOT-.tar.xz ~/workspace/DATA/dist* @@ -55,7 +58,7 @@ Proceed: - *rm -f crate* - *ln -s dist/crate-X.Y.Z crate* -6.- Now we need the configuration for the Vanilla cluster: +6.- Now you need the configuration for the Vanilla cluster: - *cat ~/workspace/DATA/conf/n1/crate.yml* @@ -192,15 +195,14 @@ Proceed: - *./startnode n2* - *./startnode n3* - Which will form the Vanilla cluster. + Which will form the Vanilla cluster, electing a leader. You can interact + with the Vanilla cluster by opening a browser and pointing it to + *http://localhost:4200*. Adding some data to the cluster ------------------------------- -You can interact with the Vanilla cluster by opening a browser and pointing it to -*http://localhost:4200*. - Proceed: 1. Create a table: @@ -213,7 +215,8 @@ Proceed: status_code short NOT NULL, object_size long NOT NULL); -2. Produce a CSV file with some data for the logs table. You could use a script like: +2. Produce a CSV file with some data for the logs table. You could use a *data.py* + script similar to: :: @@ -261,7 +264,7 @@ Proceed: for ts in timestamp_range("2019-01-01T00:00:00Z", "2019-01-01T01:00:00Z", '%Y-%m-%dT%H:%M:%SZ'): print(",".join([ts, rand_ip(), rand_request(), rand_status_code(), rand_object_size()])) - to produce 3600 rows: + to produce 3600 rows (1 hour's worth of logs @1Hz): :: @@ -271,24 +274,104 @@ Proceed: :: - COPY logs FROM 'file:///...../logs.csv'; + COPY logs FROM 'file:///..../logs.csv'; REFRESH TABLE logs; SELECT count(*) FROM logs; - The three nodes would have performed the copy, so we are expecting to see 3600 * 3 rows, with "repeated" - data. Because we did not define a primary key, **CrateDB** created the default *_id*, which is a - monotonic unique long. + The three nodes perform the copy, so we are expecting to see 3600 * 3 rows, with + "repeated" data. Because we did not define a primary key, **CrateDB** created the + default *_id* primary key, which is a unique hash (varchar), so in effect, because + each row has a unique id, they are all inserted, and the net effect is that you + think there are duplicates. + + :: + + select _id, * from logs order by log_time limit 10000; + + +Exploring the Data +------------------ + +Using the `Admin UI`_, shards view on the left: + +.. image:: imgs/shards-view.png + +We can see the three nodes, each having a number of shards, specifically: + + +-------+---+---+---+---+---+---+ + | Shard | 0 | 1 | 2 | 3 | 4 | 5 | + +=======+===+===+===+===+===+===+ + | n1 | . | . | . | | . | | + +-------+---+---+---+---+---+---+ + | n2 | . | . | | . | | . | + +-------+---+---+---+---+---+---+ + | n3 | | | . | . | . | . | + +-------+---+---+---+---+---+---+ + +Thus in this cluster setup, one node can crash, yet the data in the cluster +will still remain fully available because any two nodes have access to all +the shards, when they work together to fulfill query requests. A SQL table +is a composite of shards, six in our case. When a query is executed, the +planner will define steps for accessing all the shards of the table. + +Having a look at the setup for table *logs*: + +:: + + SHOW CREATE TABLE logs; + + CREATE TABLE IF NOT EXISTS "doc"."logs" ( + "log_time" TIMESTAMP WITH TIME ZONE NOT NULL, + "client_ip" IP NOT NULL, + "request" TEXT NOT NULL, + "status_code" SMALLINT NOT NULL, + "object_size" BIGINT NOT NULL + ) + CLUSTERED INTO 6 SHARDS + WITH ( + ... + number_of_replicas = '0-1', + ... + ) + +We have a default min number of replicas of zero, and a max of one for each +of our six shards. A replica is simply a copy or a shard. Downscaling (by means of replicas) ---------------------------------- +Downscaling by means of replicas is achieved by making sure the surviving nodes +of the cluster have access to all the shards, even when one node is missing. + +1.- We need to ensure that the number of replicas matches the number of nodes: + +:: + + ALTER TABLE logs SET (number_of_replicas = '1-all'); + +In the `Admin UI`_, we can follow the progress of the replication, and when it +is completed we can take two nodes down. + +At this point we just need to adjust the configuration of the surviving node, +and then restart it: + +:: + *cat ~/workspace/DATA/conf/n2/crate.yml* + :: + + node.name: n2 + stats.service.interval: 0 + network.host: _local_ + http.cors.enabled: true + http.cors.allow-origin: "*" Downscaling (by means of snapshots) ----------------------------------- -.. _GitHub: https://github.com/crate/crate.git \ No newline at end of file +.. _GitHub: https://github.com/crate/crate.git +.. _`Admin UI`: http://localhost:4200 \ No newline at end of file diff --git a/docs/downscaling/imgs/shards-view.png b/docs/downscaling/imgs/shards-view.png new file mode 100644 index 0000000000000000000000000000000000000000..e4245a1d7e809f8c432721f70b6006f7a2844a88 GIT binary patch literal 158516 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 z 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%0A>?&aX$WO~bmev_gXBuUU%B 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 Date: Wed, 5 Feb 2020 13:12:30 +0100 Subject: [PATCH 4/8] Add the scripts and reference to them, making the experience easier --- .gitignore | 5 + docs/downscaling/README.rst | 298 ++++-------------- scripts/downscaling/bootstrap-node.sh | 9 + scripts/downscaling/common.sh | 60 ++++ scripts/downscaling/conf/log4j2.properties | 13 + scripts/downscaling/conf/n1/crate.yml | 18 ++ scripts/downscaling/conf/n1/crate.yml.orig | 18 ++ scripts/downscaling/conf/n1/log4j2.properties | 1 + scripts/downscaling/conf/n2/crate.yml | 18 ++ scripts/downscaling/conf/n2/log4j2.properties | 1 + scripts/downscaling/conf/n3/crate.yml | 18 ++ scripts/downscaling/conf/n3/log4j2.properties | 1 + scripts/downscaling/data.py | 49 +++ scripts/downscaling/detach-node | 9 + scripts/downscaling/start-node | 9 + scripts/downscaling/update-dist | 26 ++ 16 files changed, 310 insertions(+), 243 deletions(-) create mode 100755 scripts/downscaling/bootstrap-node.sh create mode 100755 scripts/downscaling/common.sh create mode 100644 scripts/downscaling/conf/log4j2.properties create mode 100644 scripts/downscaling/conf/n1/crate.yml create mode 100644 scripts/downscaling/conf/n1/crate.yml.orig create mode 120000 scripts/downscaling/conf/n1/log4j2.properties create mode 100644 scripts/downscaling/conf/n2/crate.yml create mode 120000 scripts/downscaling/conf/n2/log4j2.properties create mode 100644 scripts/downscaling/conf/n3/crate.yml create mode 120000 scripts/downscaling/conf/n3/log4j2.properties create mode 100755 scripts/downscaling/data.py create mode 100755 scripts/downscaling/detach-node create mode 100755 scripts/downscaling/start-node create mode 100755 scripts/downscaling/update-dist diff --git a/.gitignore b/.gitignore index 49950ab..b8d69e5 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,8 @@ .env .style *.lint +scripts/downscaling/crate +scripts/downscaling/dist/* +scripts/downscaling/data/* +scripts/downscaling/repo/* +scripts/downscaling/logs.csv diff --git a/docs/downscaling/README.rst b/docs/downscaling/README.rst index d7d7de7..203858e 100644 --- a/docs/downscaling/README.rst +++ b/docs/downscaling/README.rst @@ -6,7 +6,6 @@ In this tutorial we: - Create a Vanilla cluster. - Downscale it, using replicas. -- Downscale it, using snapshots. Starting a Vanilla cluster @@ -19,185 +18,45 @@ only have one host, and this comes at the cost increased latency in writes. Proceed: -1. *git clone https://github.com/crate/crate.git* - - Assumed **git**, **java 11** or later, and a **terminal** are available to you, - and you have an account in GitHub_. - -2. - - - *cd crate* - - *./gradlew clean* (if you already had the clone) - - *./gradlew distTar*. - -3. Create a folder somewhere, I suggest *~/workspace/DATA*. It should contain this - structure: +1. *~/.../crate-tutorials/scripts/downscaling* should contain: + - *update-dist*: script to install **CrateDB**. - *dist*: **CrateDB** distributions. + - *crate*: a symlink to a particular distribution in the *dist* folder (not + the **CrateDB**, executable script), where you will also find a *crate-clone* + git repository. - *conf*: **CrateDB** configurations, each node in the cluster has a folder - in there, with the *crate.yml* and *log4j2.properties* configuration files - in it. - - *data*: **CrateDB** through configuration the nodes will log under - *data/nodes/[0,1,2]* + in there, with the *crate.yml* and *log4j2.properties*. + - *data*: **CrateDB** the nodes will persist their data under *data/nodes/[0,1,2]*. - *repo*: **CrateDB** repo, for snapshotting. - - *startnode*: script to start **CrateDB** with a given config. - - *crate*: a symlink to a particular distribution in the *dist* folder (not - the **CrateDB**, executable script). - -4. *cp crate/app/build/distributions/crate-X.Y.Z-SNAPSHOT-.tar.xz ~/workspace/DATA/dist* - -5. - - - *cd ~/workspace/DATA/dist* - - *tar -xzvf crate-X.Y.Z-SNAPSHOT-.tar.xz* - - At this point you have a folder, *~/workspace/DATA/dist/crate-X.Y.Z*, containing the - latest, unreleased, **CrateDB**. - - - *cd ~/workspace/DATA* - - *rm -f crate* - - *ln -s dist/crate-X.Y.Z crate* - -6.- Now you need the configuration for the Vanilla cluster: - - - *cat ~/workspace/DATA/conf/n1/crate.yml* - - :: - - cluster.name: vanilla - node.name: n1 - stats.service.interval: 0 - network.host: _local_ - node.max_local_storage_nodes: 3 - http.cors.enabled: true - http.cors.allow-origin: "*" - transport.tcp.port: 4301 - gateway.expected_nodes: 3 - gateway.recover_after_nodes: 2 - discovery.seed_hosts: - - 127.0.0.1:4301 - - 127.0.0.1:4302 - cluster.initial_master_nodes: - - 127.0.0.1:4301 - - 127.0.0.1:4302 - - - *cat ~/workspace/DATA/conf/n2/crate.yml* + - *start-node*: script to start **CrateDB** with a given configuration. + - *detach-node*: script to detach a node from the cluster. + - *bootstrap-node*: script to bootstrap a node to form a new cluster. + - *data.py*: script produce dummy data. - :: +2. Run *./update-dist* - cluster.name: vanilla - node.name: n2 - stats.service.interval: 0 - network.host: _local_ - node.max_local_storage_nodes: 3 - http.cors.enabled: true - http.cors.allow-origin: "*" - transport.tcp.port: 4302 - gateway.expected_nodes: 3 - gateway.recover_after_nodes: 2 - discovery.seed_hosts: - - 127.0.0.1:4301 - - 127.0.0.1:4302 - cluster.initial_master_nodes: - - 127.0.0.1:4301 - - 127.0.0.1:4302 - - - *cat ~/workspace/DATA/conf/n3/crate.yml* + - This will install the latest, unreleased, **CrateDB** under *dist/*, creating + a link *./crate -> dist/crate..*. + - Assumed **git**, **java 11** or later, **python3** and a **terminal** are + available to you, and you have an account in GitHub_. - :: - - cluster.name: vanilla - node.name: n3 - stats.service.interval: 0 - network.host: _local_ - node.max_local_storage_nodes: 3 - http.cors.enabled: true - http.cors.allow-origin: "*" - transport.tcp.port: 4303 - gateway.expected_nodes: 3 - gateway.recover_after_nodes: 2 - discovery.seed_hosts: - - 127.0.0.1:4301 - - 127.0.0.1:4302 - cluster.initial_master_nodes: - - 127.0.0.1:4301 - - 127.0.0.1:4302 - - - And for convenience, you may use this *log4j2.properties* setup, save it to a file - alongside each *crate.yml*.: +3. The configuration for the Vanilla cluster: - :: + - *~/.../crate-tutorials/scripts/downscaling/conf/n1/crate.yml* + - *~/.../crate-tutorials/scripts/downscaling/conf/n2/crate.yml* + - *~/.../crate-tutorials/scripts/downscaling/conf/n3/crate.yml* + - *~/.../crate-tutorials/scripts/downscaling/conf/log4j2.properties* - status = error - rootLogger.level = info - rootLogger.appenderRef.console.ref = console - # log action execution errors for easier debugging - logger.action.name = org.crate.action.sql - logger.action.level = debug - appender.console.type = Console - appender.console.name = console - appender.console.layout.type = PatternLayout - appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c{1.}] [%node_name] %marker%m%n - -7. The *startnode* script could look something like this: - - :: - - #!/bin/sh - - node_name=default - path_data=$(pwd)/data - path_repo=$(pwd)/repo - case $# in - 1) - node_name=$1 - ;; - - 2) - node_name=$1 - path_data=$2 - ;; - - 3) - node_name=$1 - path_data=$2 - path_repo=$3 - ;; - - -h | -help | --h | --help) - echo "syntax: $0 [node_name [data_path [repo_path]]]" - echo 'defaults: ' - echo " - node_name: default" - echo " - path_data: $path_data" - echo " - path_repo: $path_repo" - exit 1 - ;; - esac - - path_conf="$(pwd)/conf/$node_name" - if [ ! -d $path_conf ]; then - echo "No configuration available in [conf/$node_name]." - exit 1 - fi - - export CRATE_HEAP_SIZE=2G - echo 'setup: ' - echo " - node_name: $node_name" - echo " - path_data: $path_data" - echo " - path_repo: $path_repo" - echo " - CRATE_HEAP_SIZE: $CRATE_HEAP_SIZE" - - ./crate/bin/crate -Cpath.conf=$path_conf -Cpath.data=$path_data -Cpath.repo=$path_repo - -8. Now in three separate terminals, start the three nodes: +4. Run *./startnode* in three different terminals - *./startnode n1* - *./startnode n2* - *./startnode n3* - Which will form the Vanilla cluster, electing a leader. You can interact - with the Vanilla cluster by opening a browser and pointing it to - *http://localhost:4200*. + Which will form the Vanilla cluster, electing a master. You can + interact with the Vanilla cluster by opening a browser and pointing + it to *http://localhost:4200*, *CrateDB*'s `Admin UI`_. Adding some data to the cluster @@ -205,7 +64,13 @@ Adding some data to the cluster Proceed: -1. Create a table: +1. Produce a CSV_ file containing 3600 rows of log data (1 hour's worth of logs @1Hz): + + :: + + ./data.py > logs.csv + +2. In the `Admin UI`_: :: @@ -215,78 +80,14 @@ Proceed: status_code short NOT NULL, object_size long NOT NULL); -2. Produce a CSV file with some data for the logs table. You could use a *data.py* - script similar to: - - :: - - #!/usr/bin/env python3 - - import random - import string - import ipaddress - import time - - - # to achieve log lines as in: - # 2012-01-01T00:00:00Z,25.152.171.147,/books/Six_Easy_Pieces.html,404,271 - # -> timestamp, - # -> random ip address, - # -> random request, - # -> random status code, - # -> random object size, - - def timestamp_range(start, end, format): - st = int(time.mktime(time.strptime(start, format))) - et = int(time.mktime(time.strptime(end, format))) - dt = 1 # 1 sec - fmt = lambda x: time.strftime(format, time.localtime(x)) - return (fmt(x) for x in range(st, et, dt)) - - def rand_ip(): - return str(ipaddress.IPv4Address(random.getrandbits(32))) - - def rand_request(): - rand = lambda src: src[random.randint(0, len(src) - 1)] - path = lambda: "/".join((rand(("usr", "bin", "workspace", "temp", "home", "crate"))) for _ in range(4)) - name = lambda: ''.join(random.sample(string.ascii_lowercase, 7)) - ext = lambda: rand(("html", "pdf", "log", "gif", "jpeg", "js")) - return "{}/{}.{}".format(path(), name(), ext()) - - def rand_object_size(): - return str(random.randint(0, 1024)) - - def rand_status_code(): - return str(random.randint(100, 500)) - - if __name__ == "__main__": - print("log_time,client_ip,request,status_code,object_size") - for ts in timestamp_range("2019-01-01T00:00:00Z", "2019-01-01T01:00:00Z", '%Y-%m-%dT%H:%M:%SZ'): - print(",".join([ts, rand_ip(), rand_request(), rand_status_code(), rand_object_size()])) - - to produce 3600 rows (1 hour's worth of logs @1Hz): - - :: - - ./data.py > logs.csv - -3. Load the data: - - :: - - COPY logs FROM 'file:///..../logs.csv'; + COPY logs FROM 'file:///.../crate-tutorials/scripts/downscaling/logs.csv'; REFRESH TABLE logs; - SELECT count(*) FROM logs; - - The three nodes perform the copy, so we are expecting to see 3600 * 3 rows, with - "repeated" data. Because we did not define a primary key, **CrateDB** created the - default *_id* primary key, which is a unique hash (varchar), so in effect, because - each row has a unique id, they are all inserted, and the net effect is that you - think there are duplicates. + select * from logs order by log_time limit 10800; - :: - - select _id, * from logs order by log_time limit 10000; + The three nodes perform the copy, so we are expecting to see 3600 * 3 rows, with + what looks like "repeated" data. Because we did not define a primary key, **CrateDB** + created the default *_id* primary key, which is a unique hash (varchar), so in effect, + because each row has a unique id, they are all inserted. Exploring the Data @@ -313,6 +114,8 @@ will still remain fully available because any two nodes have access to all the shards, when they work together to fulfill query requests. A SQL table is a composite of shards, six in our case. When a query is executed, the planner will define steps for accessing all the shards of the table. +By adding nodes to the cluster, the data is spread over more nodes, so that +the computing is parallelized. Having a look at the setup for table *logs*: @@ -320,6 +123,10 @@ Having a look at the setup for table *logs*: SHOW CREATE TABLE logs; +Will return: + +:: + CREATE TABLE IF NOT EXISTS "doc"."logs" ( "log_time" TIMESTAMP WITH TIME ZONE NOT NULL, "client_ip" IP NOT NULL, @@ -342,16 +149,20 @@ Downscaling (by means of replicas) ---------------------------------- Downscaling by means of replicas is achieved by making sure the surviving nodes -of the cluster have access to all the shards, even when one node is missing. +of the cluster have access to all the shards, even when the other nodes are missing. -1.- We need to ensure that the number of replicas matches the number of nodes: +1. We need to ensure that the number of replicas matches the number of nodes: :: ALTER TABLE logs SET (number_of_replicas = '1-all'); In the `Admin UI`_, we can follow the progress of the replication, and when it -is completed we can take two nodes down. +is completed we can take the nodes down (*ctrl^C* in the terminal). + +2. Run *./detach-node* to detach **n1** from the cluster: + + At this point we just need to adjust the configuration of the surviving node, and then restart it: @@ -369,9 +180,10 @@ and then restart it: http.cors.allow-origin: "*" -Downscaling (by means of snapshots) ------------------------------------ + .. _GitHub: https://github.com/crate/crate.git -.. _`Admin UI`: http://localhost:4200 \ No newline at end of file +.. _`Admin UI`: http://localhost:4200 +.. _crate-node: https://crate.io/docs/crate/reference/en/latest/cli-tools.html#cli-crate-node +.. _CSV: https://en.wikipedia.org/wiki/Comma-separated_values \ No newline at end of file diff --git a/scripts/downscaling/bootstrap-node.sh b/scripts/downscaling/bootstrap-node.sh new file mode 100755 index 0000000..1f110d3 --- /dev/null +++ b/scripts/downscaling/bootstrap-node.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +source common.sh + +./crate/bin/crate-node unsafe-bootstrap \ + -Cpath.home=$path_home \ + -Cpath.conf=$path_conf \ + -Cpath.data=$path_data \ + -Cpath.repo=$path_repo diff --git a/scripts/downscaling/common.sh b/scripts/downscaling/common.sh new file mode 100755 index 0000000..ac44ff4 --- /dev/null +++ b/scripts/downscaling/common.sh @@ -0,0 +1,60 @@ +#!/bin/sh + + +display_usage_and_exit() { + echo "usage: $0 node_name [data_path [repo_path]]" + echo 'defaults: ' + echo " - node_name: default" + echo " - path_data: $path_data" + echo " - path_repo: $path_repo" + exit 1 +} + +if [ $# -lt 1 ]; then + display_usage_and_exit +fi + + +path_home=$(pwd)/crate +node_name=$1 +path_data=$(pwd)/data +path_repo=$(pwd)/repo + +case $# in + 1) + node_name=$1 + ;; + + 2) + node_name=$1 + path_data=$2 + ;; + + 3) + node_name=$1 + path_data=$2 + path_repo=$3 + ;; + + -h | -help | --h | --help) + display_usage_and_exit + ;; +esac + +path_conf="$(pwd)/conf/$node_name" +if [ ! -d $path_conf ]; then + echo "No configuration available in [conf/$node_name]." + exit 1 +fi + + +if [ -z "$CRATE_HEAP_SIZE" ]; then + export CRATE_HEAP_SIZE="2G" +fi + +echo 'setup: ' +echo " - path_home: $path_home" +echo " - node_name: $node_name" +echo " - path_data: $path_data" +echo " - path_repo: $path_repo" +echo " - CRATE_HEAP_SIZE: $CRATE_HEAP_SIZE" diff --git a/scripts/downscaling/conf/log4j2.properties b/scripts/downscaling/conf/log4j2.properties new file mode 100644 index 0000000..c8daed4 --- /dev/null +++ b/scripts/downscaling/conf/log4j2.properties @@ -0,0 +1,13 @@ +status = error + +rootLogger.level = info +rootLogger.appenderRef.console.ref = console + +# log action execution errors for easier debugging +logger.action.name = org.crate.action.sql +logger.action.level = debug + +appender.console.type = Console +appender.console.name = console +appender.console.layout.type = PatternLayout +appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c{1.}] [%node_name] %marker%m%n diff --git a/scripts/downscaling/conf/n1/crate.yml b/scripts/downscaling/conf/n1/crate.yml new file mode 100644 index 0000000..5337e25 --- /dev/null +++ b/scripts/downscaling/conf/n1/crate.yml @@ -0,0 +1,18 @@ +cluster.name: vanilla +node.name: n1 +stats.service.interval: 0 +network.host: _local_ +node.max_local_storage_nodes: 3 + +http.cors.enabled: true +http.cors.allow-origin: "*" + +transport.tcp.port: 4301 +gateway.expected_nodes: 3 +gateway.recover_after_nodes: 2 +discovery.seed_hosts: + - 127.0.0.1:4301 + - 127.0.0.1:4302 +cluster.initial_master_nodes: + - 127.0.0.1:4301 + - 127.0.0.1:4302 diff --git a/scripts/downscaling/conf/n1/crate.yml.orig b/scripts/downscaling/conf/n1/crate.yml.orig new file mode 100644 index 0000000..5337e25 --- /dev/null +++ b/scripts/downscaling/conf/n1/crate.yml.orig @@ -0,0 +1,18 @@ +cluster.name: vanilla +node.name: n1 +stats.service.interval: 0 +network.host: _local_ +node.max_local_storage_nodes: 3 + +http.cors.enabled: true +http.cors.allow-origin: "*" + +transport.tcp.port: 4301 +gateway.expected_nodes: 3 +gateway.recover_after_nodes: 2 +discovery.seed_hosts: + - 127.0.0.1:4301 + - 127.0.0.1:4302 +cluster.initial_master_nodes: + - 127.0.0.1:4301 + - 127.0.0.1:4302 diff --git a/scripts/downscaling/conf/n1/log4j2.properties b/scripts/downscaling/conf/n1/log4j2.properties new file mode 120000 index 0000000..2a55cac --- /dev/null +++ b/scripts/downscaling/conf/n1/log4j2.properties @@ -0,0 +1 @@ +../log4j2.properties \ No newline at end of file diff --git a/scripts/downscaling/conf/n2/crate.yml b/scripts/downscaling/conf/n2/crate.yml new file mode 100644 index 0000000..57317d2 --- /dev/null +++ b/scripts/downscaling/conf/n2/crate.yml @@ -0,0 +1,18 @@ +cluster.name: vanilla +node.name: n2 +stats.service.interval: 0 +network.host: _local_ +node.max_local_storage_nodes: 3 + +http.cors.enabled: true +http.cors.allow-origin: "*" + +transport.tcp.port: 4302 +gateway.expected_nodes: 3 +gateway.recover_after_nodes: 2 +discovery.seed_hosts: +- 127.0.0.1:4301 +- 127.0.0.1:4302 +cluster.initial_master_nodes: +- 127.0.0.1:4301 +- 127.0.0.1:4302 diff --git a/scripts/downscaling/conf/n2/log4j2.properties b/scripts/downscaling/conf/n2/log4j2.properties new file mode 120000 index 0000000..2a55cac --- /dev/null +++ b/scripts/downscaling/conf/n2/log4j2.properties @@ -0,0 +1 @@ +../log4j2.properties \ No newline at end of file diff --git a/scripts/downscaling/conf/n3/crate.yml b/scripts/downscaling/conf/n3/crate.yml new file mode 100644 index 0000000..4472b07 --- /dev/null +++ b/scripts/downscaling/conf/n3/crate.yml @@ -0,0 +1,18 @@ +cluster.name: vanilla +node.name: n3 +stats.service.interval: 0 +network.host: _local_ +node.max_local_storage_nodes: 3 + +http.cors.enabled: true +http.cors.allow-origin: "*" + +transport.tcp.port: 4303 +gateway.expected_nodes: 3 +gateway.recover_after_nodes: 2 +discovery.seed_hosts: +- 127.0.0.1:4301 +- 127.0.0.1:4302 +cluster.initial_master_nodes: +- 127.0.0.1:4301 +- 127.0.0.1:4302 diff --git a/scripts/downscaling/conf/n3/log4j2.properties b/scripts/downscaling/conf/n3/log4j2.properties new file mode 120000 index 0000000..2a55cac --- /dev/null +++ b/scripts/downscaling/conf/n3/log4j2.properties @@ -0,0 +1 @@ +../log4j2.properties \ No newline at end of file diff --git a/scripts/downscaling/data.py b/scripts/downscaling/data.py new file mode 100755 index 0000000..65ed31a --- /dev/null +++ b/scripts/downscaling/data.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 + +import random +import string +import ipaddress +import time + + +# to achieve log lines as in: +# 2012-01-01T00:00:00Z,25.152.171.147,/crate/Five_Easy_Pieces.html,200,280278 +# -> timestamp, +# -> random ip address, +# -> random request (a path), +# -> random status code, +# -> random object size, + + +def timestamp_range(start, end, format): + st = int(time.mktime(time.strptime(start, format))) + et = int(time.mktime(time.strptime(end, format))) + dt = 1 # 1 sec + fmt = lambda x: time.strftime(format, time.localtime(x)) + return (fmt(x) for x in range(st, et, dt)) + + +def rand_ip(): + return str(ipaddress.IPv4Address(random.getrandbits(32))) + + +def rand_request(): + rand = lambda src: src[random.randint(0, len(src) - 1)] + path = lambda: "/".join((rand(("usr", "bin", "workspace", "temp", "home", "crate"))) for _ in range(4)) + name = lambda: ''.join(random.sample(string.ascii_lowercase, 7)) + ext = lambda: rand(("html", "pdf", "log", "gif", "jpeg", "js")) + return "{}/{}.{}".format(path(), name(), ext()) + + +def rand_object_size(): + return str(random.randint(0, 1024)) + + +def rand_status_code(): + return str(random.randint(100, 500)) + + +if __name__ == "__main__": + print("log_time,client_ip,request,status_code,object_size") + for ts in timestamp_range("2019-01-01T00:00:00Z", "2019-01-01T01:00:00Z", '%Y-%m-%dT%H:%M:%SZ'): + print(",".join([ts, rand_ip(), rand_request(), rand_status_code(), rand_object_size()])) diff --git a/scripts/downscaling/detach-node b/scripts/downscaling/detach-node new file mode 100755 index 0000000..3e58941 --- /dev/null +++ b/scripts/downscaling/detach-node @@ -0,0 +1,9 @@ +#!/bin/sh + +source common.sh + +./crate/bin/crate-node detach-cluster \ + -Cpath.home=$path_home \ + -Cpath.conf=$path_conf \ + -Cpath.data=$path_data \ + -Cpath.repo=$path_repo diff --git a/scripts/downscaling/start-node b/scripts/downscaling/start-node new file mode 100755 index 0000000..65e4b69 --- /dev/null +++ b/scripts/downscaling/start-node @@ -0,0 +1,9 @@ +#!/bin/sh + +source common.sh + +./crate/bin/crate \ + -Cpath.home=$(pwd)/crate \ + -Cpath.conf=$path_conf \ + -Cpath.data=$path_data \ + -Cpath.repo=$path_repo diff --git a/scripts/downscaling/update-dist b/scripts/downscaling/update-dist new file mode 100755 index 0000000..38f84d3 --- /dev/null +++ b/scripts/downscaling/update-dist @@ -0,0 +1,26 @@ +#!/bin/sh + +if [ ! -d dist ]; then + mkdir dist +fi + +if [ ! -d dist/crate-clone ]; then + git clone https://github.com/crate/crate.git dist/crate-clone +fi + +cd dist/crate-clone +git pull +./gradlew clean +./gradlew disTar + +latest_tar_ball=$(find ./app/build/distributions -name 'crate-*.tar.gz') +cp $latest_tar_ball .. +cd .. +name=$(basename $latest_tar_ball) +tar -xzvf $name +rm -f $name +name=${name/.tar.gz/} +cd .. +rm -f crate +ln -s dist/$name crate +echo "Crate $name has been installed." From 39535fc410cb9895c5eff758a62667dbaca3dc12 Mon Sep 17 00:00:00 2001 From: marregui Date: Wed, 5 Feb 2020 15:57:05 +0100 Subject: [PATCH 5/8] First draft ready --- docs/downscaling/README.rst | 43 ++++++++++++++------- scripts/downscaling/common.sh | 38 ++---------------- scripts/downscaling/conf/n1/crate.yml | 2 +- scripts/downscaling/conf/n1/crate.yml.orig | 18 --------- scripts/downscaling/conf/n1/crate.yml.short | 10 +++++ 5 files changed, 45 insertions(+), 66 deletions(-) delete mode 100644 scripts/downscaling/conf/n1/crate.yml.orig create mode 100644 scripts/downscaling/conf/n1/crate.yml.short diff --git a/docs/downscaling/README.rst b/docs/downscaling/README.rst index 203858e..9c8f8ed 100644 --- a/docs/downscaling/README.rst +++ b/docs/downscaling/README.rst @@ -157,30 +157,47 @@ of the cluster have access to all the shards, even when the other nodes are miss ALTER TABLE logs SET (number_of_replicas = '1-all'); -In the `Admin UI`_, we can follow the progress of the replication, and when it -is completed we can take the nodes down (*ctrl^C* in the terminal). +In the `Admin UI`_, we can follow the progress of replication. -2. Run *./detach-node* to detach **n1** from the cluster: +2. After replication is completed, we can take down all the nodes in the cluster + (*ctrl^C* in the terminal). +3. Run *./detach-node ni* to detach **n1**, **n2** and **n3** from the cluster. +4. Change the configuration *crate.yml* of the node you want to be your single + node **CrateDB** cluster to: -At this point we just need to adjust the configuration of the surviving node, -and then restart it: + :: + cluster.name: single # this has changed, it does not need to + node.name: n1 + stats.service.interval: 0 + network.host: _local_ + node.max_local_storage_nodes: 1 # this has changed -:: + http.cors.enabled: true + http.cors.allow-origin: "*" + + transport.tcp.port: 4301 + #gateway.expected_nodes: 3 + #gateway.recover_after_nodes: 2 + #discovery.seed_hosts: + # - 127.0.0.1:4301 + # - 127.0.0.1:4302 + #cluster.initial_master_nodes: + # - 127.0.0.1:4301 + # - 127.0.0.1:4302 - *cat ~/workspace/DATA/conf/n2/crate.yml* + I want **n1** to be that node. - :: +5. Run *./bootstrap-node n1* to let **n1** join a new cluster when it starts. - node.name: n2 - stats.service.interval: 0 - network.host: _local_ - http.cors.enabled: true - http.cors.allow-origin: "*" +6. Run *./start-node n1*. +7. Again, we need to ensure that the number of replicas matches the number of nodes: +:: + ALTER TABLE logs SET (number_of_replicas = '0-1'); .. _GitHub: https://github.com/crate/crate.git diff --git a/scripts/downscaling/common.sh b/scripts/downscaling/common.sh index ac44ff4..295926a 100755 --- a/scripts/downscaling/common.sh +++ b/scripts/downscaling/common.sh @@ -1,12 +1,7 @@ #!/bin/sh - display_usage_and_exit() { - echo "usage: $0 node_name [data_path [repo_path]]" - echo 'defaults: ' - echo " - node_name: default" - echo " - path_data: $path_data" - echo " - path_repo: $path_repo" + echo "usage: $0 node_name" exit 1 } @@ -14,44 +9,19 @@ if [ $# -lt 1 ]; then display_usage_and_exit fi - -path_home=$(pwd)/crate node_name=$1 -path_data=$(pwd)/data -path_repo=$(pwd)/repo - -case $# in - 1) - node_name=$1 - ;; - - 2) - node_name=$1 - path_data=$2 - ;; - - 3) - node_name=$1 - path_data=$2 - path_repo=$3 - ;; - - -h | -help | --h | --help) - display_usage_and_exit - ;; -esac - path_conf="$(pwd)/conf/$node_name" if [ ! -d $path_conf ]; then echo "No configuration available in [conf/$node_name]." exit 1 fi - +path_home=$(pwd)/crate +path_data=$(pwd)/data +path_repo=$(pwd)/repo if [ -z "$CRATE_HEAP_SIZE" ]; then export CRATE_HEAP_SIZE="2G" fi - echo 'setup: ' echo " - path_home: $path_home" echo " - node_name: $node_name" diff --git a/scripts/downscaling/conf/n1/crate.yml b/scripts/downscaling/conf/n1/crate.yml index 5337e25..2c258c4 100644 --- a/scripts/downscaling/conf/n1/crate.yml +++ b/scripts/downscaling/conf/n1/crate.yml @@ -2,7 +2,7 @@ cluster.name: vanilla node.name: n1 stats.service.interval: 0 network.host: _local_ -node.max_local_storage_nodes: 3 +node.max_local_storage_nodes: 1 http.cors.enabled: true http.cors.allow-origin: "*" diff --git a/scripts/downscaling/conf/n1/crate.yml.orig b/scripts/downscaling/conf/n1/crate.yml.orig deleted file mode 100644 index 5337e25..0000000 --- a/scripts/downscaling/conf/n1/crate.yml.orig +++ /dev/null @@ -1,18 +0,0 @@ -cluster.name: vanilla -node.name: n1 -stats.service.interval: 0 -network.host: _local_ -node.max_local_storage_nodes: 3 - -http.cors.enabled: true -http.cors.allow-origin: "*" - -transport.tcp.port: 4301 -gateway.expected_nodes: 3 -gateway.recover_after_nodes: 2 -discovery.seed_hosts: - - 127.0.0.1:4301 - - 127.0.0.1:4302 -cluster.initial_master_nodes: - - 127.0.0.1:4301 - - 127.0.0.1:4302 diff --git a/scripts/downscaling/conf/n1/crate.yml.short b/scripts/downscaling/conf/n1/crate.yml.short new file mode 100644 index 0000000..14ca126 --- /dev/null +++ b/scripts/downscaling/conf/n1/crate.yml.short @@ -0,0 +1,10 @@ +cluster.name: vanilla +node.name: n1 +stats.service.interval: 0 +network.host: _local_ +node.max_local_storage_nodes: 1 + +http.cors.enabled: true +http.cors.allow-origin: "*" + +transport.tcp.port: 4301 From 9042b5a97ec11bad24b2307342c4ba892a76f824 Mon Sep 17 00:00:00 2001 From: marregui Date: Wed, 5 Feb 2020 15:58:13 +0100 Subject: [PATCH 6/8] Rename bootstrap-node script --- scripts/downscaling/{bootstrap-node.sh => bootstrap-node} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename scripts/downscaling/{bootstrap-node.sh => bootstrap-node} (100%) diff --git a/scripts/downscaling/bootstrap-node.sh b/scripts/downscaling/bootstrap-node similarity index 100% rename from scripts/downscaling/bootstrap-node.sh rename to scripts/downscaling/bootstrap-node From a204ce0820bd677d6953f40a6547b6dd8ba67c36 Mon Sep 17 00:00:00 2001 From: marregui Date: Wed, 5 Feb 2020 20:43:13 +0100 Subject: [PATCH 7/8] Last touches --- docs/downscaling/README.rst | 37 +++++++++++++++++---------- scripts/downscaling/common.sh | 2 +- scripts/downscaling/conf/n1/crate.yml | 10 ++++---- scripts/downscaling/conf/n2/crate.yml | 2 +- scripts/downscaling/conf/n3/crate.yml | 2 +- 5 files changed, 31 insertions(+), 22 deletions(-) diff --git a/docs/downscaling/README.rst b/docs/downscaling/README.rst index 9c8f8ed..d452428 100644 --- a/docs/downscaling/README.rst +++ b/docs/downscaling/README.rst @@ -5,7 +5,8 @@ Downscaling In this tutorial we: - Create a Vanilla cluster. -- Downscale it, using replicas. +- Add some data to it. +- Downscale it to a single node cluster. Starting a Vanilla cluster @@ -27,11 +28,13 @@ Proceed: git repository. - *conf*: **CrateDB** configurations, each node in the cluster has a folder in there, with the *crate.yml* and *log4j2.properties*. - - *data*: **CrateDB** the nodes will persist their data under *data/nodes/[0,1,2]*. + - *data*: **CrateDB** the nodes will persist their data under *data/ni/nodes/0*. - *repo*: **CrateDB** repo, for snapshotting. - *start-node*: script to start **CrateDB** with a given configuration. - *detach-node*: script to detach a node from the cluster. - - *bootstrap-node*: script to bootstrap a node to form a new cluster. + - *bootstrap-node*: script to bootstrap a node to form a new cluster. Which + means, recreating its cluster state so that it may be started on its own + forming a new cluster that has access to the data in the previous. - *data.py*: script produce dummy data. 2. Run *./update-dist* @@ -162,17 +165,23 @@ In the `Admin UI`_, we can follow the progress of replication. 2. After replication is completed, we can take down all the nodes in the cluster (*ctrl^C* in the terminal). -3. Run *./detach-node ni* to detach **n1**, **n2** and **n3** from the cluster. +3. Run *./detach-node ni*, where i in [2,3], to detach **n2** and **n3** from the cluster. + We will let **n1** form a new cluster all by itself, with access to the original data. -4. Change the configuration *crate.yml* of the node you want to be your single - node **CrateDB** cluster to: +4. Change **n1**'s configuration *crate.yml*. The best practice is to select the node + that was master, as then we know it has the latest version of the cluster state. For + our tutorial, we are running in a single host so cluster state is more or less + guaranteed to be consistent across nodes, but, in principle, the cluster could be + running across multiple hosts, and then we would want the master node to become the + new single node cluster: :: - cluster.name: single # this has changed, it does not need to + + cluster.name: simple # don't need to change this node.name: n1 stats.service.interval: 0 network.host: _local_ - node.max_local_storage_nodes: 1 # this has changed + node.max_local_storage_nodes: 1 http.cors.enabled: true http.cors.allow-origin: "*" @@ -187,20 +196,20 @@ In the `Admin UI`_, we can follow the progress of replication. # - 127.0.0.1:4301 # - 127.0.0.1:4302 - I want **n1** to be that node. - 5. Run *./bootstrap-node n1* to let **n1** join a new cluster when it starts. 6. Run *./start-node n1*. + Panic not, the cluster state is *[YELLOW]*, we sort that out with: -7. Again, we need to ensure that the number of replicas matches the number of nodes: + :: -:: + ALTER TABLE logs SET (number_of_replicas = '0-1'); - ALTER TABLE logs SET (number_of_replicas = '0-1'); +Further reading: node-tool_. .. _GitHub: https://github.com/crate/crate.git .. _`Admin UI`: http://localhost:4200 .. _crate-node: https://crate.io/docs/crate/reference/en/latest/cli-tools.html#cli-crate-node -.. _CSV: https://en.wikipedia.org/wiki/Comma-separated_values \ No newline at end of file +.. _CSV: https://en.wikipedia.org/wiki/Comma-separated_values +.. _crate-node: https://crate.io/docs/crate/guide/en/latest/best-practices/crate-node.html \ No newline at end of file diff --git a/scripts/downscaling/common.sh b/scripts/downscaling/common.sh index 295926a..60b19c7 100755 --- a/scripts/downscaling/common.sh +++ b/scripts/downscaling/common.sh @@ -16,7 +16,7 @@ if [ ! -d $path_conf ]; then exit 1 fi path_home=$(pwd)/crate -path_data=$(pwd)/data +path_data=$(pwd)/data/$node_name path_repo=$(pwd)/repo if [ -z "$CRATE_HEAP_SIZE" ]; then diff --git a/scripts/downscaling/conf/n1/crate.yml b/scripts/downscaling/conf/n1/crate.yml index 2c258c4..9b01240 100644 --- a/scripts/downscaling/conf/n1/crate.yml +++ b/scripts/downscaling/conf/n1/crate.yml @@ -1,4 +1,4 @@ -cluster.name: vanilla +cluster.name: vanilla node.name: n1 stats.service.interval: 0 network.host: _local_ @@ -11,8 +11,8 @@ transport.tcp.port: 4301 gateway.expected_nodes: 3 gateway.recover_after_nodes: 2 discovery.seed_hosts: - - 127.0.0.1:4301 - - 127.0.0.1:4302 +- 127.0.0.1:4301 +- 127.0.0.1:4302 cluster.initial_master_nodes: - - 127.0.0.1:4301 - - 127.0.0.1:4302 +- 127.0.0.1:4301 +- 127.0.0.1:4302 diff --git a/scripts/downscaling/conf/n2/crate.yml b/scripts/downscaling/conf/n2/crate.yml index 57317d2..bfa6f39 100644 --- a/scripts/downscaling/conf/n2/crate.yml +++ b/scripts/downscaling/conf/n2/crate.yml @@ -2,7 +2,7 @@ cluster.name: vanilla node.name: n2 stats.service.interval: 0 network.host: _local_ -node.max_local_storage_nodes: 3 +node.max_local_storage_nodes: 1 http.cors.enabled: true http.cors.allow-origin: "*" diff --git a/scripts/downscaling/conf/n3/crate.yml b/scripts/downscaling/conf/n3/crate.yml index 4472b07..24bf3d7 100644 --- a/scripts/downscaling/conf/n3/crate.yml +++ b/scripts/downscaling/conf/n3/crate.yml @@ -2,7 +2,7 @@ cluster.name: vanilla node.name: n3 stats.service.interval: 0 network.host: _local_ -node.max_local_storage_nodes: 3 +node.max_local_storage_nodes: 1 http.cors.enabled: true http.cors.allow-origin: "*" From 33730bc9a2820cc7ac8967321e428870ec00763e Mon Sep 17 00:00:00 2001 From: marregui Date: Wed, 5 Feb 2020 20:45:07 +0100 Subject: [PATCH 8/8] Fixup --- docs/downscaling/README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/downscaling/README.rst b/docs/downscaling/README.rst index d452428..1958d44 100644 --- a/docs/downscaling/README.rst +++ b/docs/downscaling/README.rst @@ -205,7 +205,7 @@ In the `Admin UI`_, we can follow the progress of replication. ALTER TABLE logs SET (number_of_replicas = '0-1'); -Further reading: node-tool_. +Further reading: crate-node_. .. _GitHub: https://github.com/crate/crate.git