CockroachDB это вам не PostgreSQL
Thu 09 February 2023CockroachDB что это?
Сегодня хотел бы поделиться своими ощущениями о CockroachDB. Это распределенная (и как заверяют авторы, именно – распределенная), масштабируемая и «не убиваемая» база данных. На период 2023 года, база находится уже в стабильном релизе и доступна как на официальном сайте разработчиков так и на docker hub. По уверению разработчика CockroachDB сочетает в себе все преимущества и некую метаморфозу между SQL и NoSQL базами данных. То есть реляционными и нет. Это уже интересно! Для меня, так же плюсом стало то, что база разрабатывается на Go, и поддерживает практически полный синтаксис PostgreSQL. Еще одним плюсом идет поддержка Kubernetes из коробки. Да и в целом, на мой взгляд, это прекрасная замена PostgreSQL. Работая с MongoDB я получал огромное удовольствие от скорости и довольно грамотной репликации. Которая в отличии от того же PostgreSQL не требовала танцев вокруг и прикручивания сторонних инструментов. И вот, мир увидел стабильную версию CockroachDB. И мы получили все возможности реплики, масштабирования и других «плюшек» имея при этом синтаксис и структуру SQL. Прекрасно же! Я искренне желаю разработчикам развития! Но давайте перейдем к действиям и попробуем её в деле! Разворачивать все мы конечно будем в docker. Поехали!
Запускаем insecure кластер.
В документации разработчика сказано, что если, мы хотим только попробовать работать с сервисом или использовать его для разработки, мы можем запускать, так называемые не безопасные (insecure) кластера. Потому как в боевой середе CockroachDB, работает только по средствам шифрования SSL. И это ещё один плюс этой БД. Поэтому, сначала запустим кластер в не безопасном режиме. Для развертывания будем использовать официальный образ с docker hub, и что бы попробовать кластер опишем сразу три ноды в нем:
>>> vi docker-compose.yaml
version: '3.8'
services:
cockroach01:
image: cockroachdb/cockroach
container_name: cdb01
hostname: cdb01
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- ./cdb01:/cockroach/cockroach-data
ports:
- 26257:26257
- 8080:8080
command: start --join=cdb01,cdb02,cdb03 --listen-addr=:26257 --http-addr=:8080 --insecure
networks:
- cockroach
cockroach02:
image: cockroachdb/cockroach
container_name: cdb02
hostname: cdb02
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- ./cdb02:/cockroach/cockroach-data
command: start --join=cdb01,cdb02,cdb03 --listen-addr=:26257 --http-addr=:8080 --insecure
networks:
- cockroach
cockroach03:
image: cockroachdb/cockroach
container_name: cdb03
hostname: cdb03
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- ./cdb03:/cockroach/cockroach-data
command: start --join=cdb01,cdb02,cdb03 --listen-addr=:26257 --http-addr=:8080 --insecure
networks:
- cockroach
networks:
cockroach:
driver: bridge
Теперь пробуем запустить наш кластер:
>>> docker compose up --detach
[+] Running 4/4
⠿ Network cockroachdb_cockroach Created 0.1s
⠿ Container cdb01 Started 1.1s
⠿ Container cdb03 Started 1.2s
⠿ Container cdb02 Started 1.2s
>>> docker compose ps -a
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
cdb01 cockroachdb/cockroach "/cockroach/cockroac…" cockroach01 About a minute ago Up About a minute 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp, 0.0.0.0:26257->26257/tcp, :::26257->26257/tcp
cdb02 cockroachdb/cockroach "/cockroach/cockroac…" cockroach02 About a minute ago Up About a minute 8080/tcp, 26257/tcp
cdb03 cockroachdb/cockroach "/cockroach/cockroac…" cockroach03 About a minute ago Up About a minute 8080/tcp, 26257/tcp
Теперь нам необходимо инициализировать и запустить кластер:
>>> docker exec -it cdb01 sh -c 'cockroach init --insecure --host=cdb01:26257'
Cluster successfully initialized
После запуска, вам будет доступна панель состояния кластера, она находится по адресу первой ноды, порта 8080, в моем случае это, http://127.0.0.1:8080
В консоли множество полезной информации, пробегитесь по ней, думаю, вам будет интересно ознакомиться, полезно то,
что это часть функционала сервиса, то есть вы получаете это сразу из коробки, не надо ставить дополнительно
web интерфейс. Ну что ж, отлично, создадим базу данных и добавим пару записей, при установке не безопасного кластера
логин и пароль по умолчанию root:root
>>> docker exec -it cdb01 sh
sh-4.4# ./cockroach sql --insecure
#
# Welcome to the CockroachDB SQL shell.
# All statements must be terminated by a semicolon.
# To exit, type: \q.
#
# Server version: CockroachDB CCL v22.2.3 (x86_64-pc-linux-gnu, built 2023/01/23 19:11:57, go1.19.1) (same version as client)
# Cluster ID: 7dfd6b3d-7f18-4b4c-a945-09da1b1bbc39
#
# Enter \? for a brief introduction.
#
root@localhost:26257/defaultdb>
В консоли создаем базу, добавляем запись, и выходим:
CREATE DATABASE bank;
CREATE TABLE bank.accounts (id INT PRIMARY KEY, balance DECIMAL);
INSERT INTO bank.accounts VALUES (1, 1000.50);
SELECT * FROM bank.accounts;
Если все прошло хорошо, то вывод должен быть следующим:
id | balance
-----+----------
1 | 1000.50
(1 row)
Time: 4ms total (execution 3ms / network 0ms)
Вот и все, по сути, мы уже можем использовать кластер, попробую выбрать оттуда данные с помощью Python, используя при этом PostgreSQL драйвер, создам файл get.py со следующим кодом:
import psycopg2
conn = psycopg2.connect(dbname='bank', user='root',password='root',
host='localhost', port='26257')
cursor = conn.cursor()
cursor.execute('SELECT * FROM accounts LIMIT 10')
records = cursor.fetchall()
for row in records:
print('id: %s, balance: %s' % row, '\nRaw data:', row, '\n')
cursor.close()
conn.close()
Вывод:
>>> python get.py
id: 1, balance: 1000.50
Raw data: (1, Decimal('1000.50'))
Подключаем SSL и запускаем рабочий кластер
В документации написано, что мы можем использовать чистый openssl для генерации сертификатов, мы так же можем использовать Let'sEncrypt для получения сертификатов. Но в комплект самой БД входит утилита для создания сертификатов. Да, да, авторы позаботились и об этом! По этому переходим созданию сертификатов. Для начала нам нужно изменить наш docker-compose.yaml и добавить в него volume для хранения сертификатов, теперь он будет выглядеть так:
version: '3.8'
services:
cockroach01:
image: cockroachdb/cockroach
container_name: cdb01
hostname: cdb01
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- ./cdb01:/cockroach/cockroach-data
- ./certs:/certs
ports:
- 26257:26257
- 8080:8080
command: start --join=cdb01,cdb02,cdb03 --listen-addr=:26257 --http-addr=:8080 --insecure
networks:
- cockroach
cockroach02:
image: cockroachdb/cockroach
container_name: cdb02
hostname: cdb02
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- ./cdb02:/cockroach/cockroach-data
- ./certs:/certs
command: start --join=cdb01,cdb02,cdb03 --listen-addr=:26257 --http-addr=:8080 --insecure
networks:
- cockroach
cockroach03:
image: cockroachdb/cockroach
container_name: cdb03
hostname: cdb03
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- ./cdb03:/cockroach/cockroach-data
- ./certs:/certs
command: start --join=cdb01,cdb02,cdb03 --listen-addr=:26257 --http-addr=:8080 --insecure
networks:
- cockroach
networks:
cockroach:
driver: bridge
Перезапустите docker compose что бы изменения применились к контейнерам, после чего можно заходить в основной, он же первая нода и генерировать сертификаты:
>>> docker exec -it cdb01 sh
sh-4.4# cockroach cert create-ca --certs-dir=/certs --ca-key=/certs/ca.key
sh-4.4# cockroach cert create-node cdb01 cdb02 cdb03 --certs-dir=/certs --ca-key=/certs/ca.key
sh-4.4# cockroach cert create-client root --certs-dir=/certs --ca-key=/certs/ca.key
sh-4.4# ls /certs
ca.crt ca.key client.craig.crt client.craig.key node.crt node.key
Сертификаты готовы, теперь нам надо запустить кластер уже с использованием SSL, выходим из контейнера и снова поправим наш docker-compose.yaml
version: '3.8'
services:
cockroach01:
image: cockroachdb/cockroach
container_name: cdb01
hostname: cdb01
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- ./cdb01:/cockroach/cockroach-data
- ./certs:/certs
ports:
- 26257:26257
- 8080:8080
command: start --join=cdb01,cdb02,cdb03 --listen-addr=:26257 --http-addr=:8080 --certs-dir=/certs
networks:
- cockroach
cockroach02:
image: cockroachdb/cockroach
container_name: cdb02
hostname: cdb02
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- ./cdb02:/cockroach/cockroach-data
- ./certs:/certs
command: start --join=cdb01,cdb02,cdb03 --listen-addr=:26257 --http-addr=:8080 --certs-dir=/certs
networks:
- cockroach
cockroach03:
image: cockroachdb/cockroach
container_name: cdb03
hostname: cdb03
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- ./cdb03:/cockroach/cockroach-data
- ./certs:/certs
command: start --join=cdb01,cdb02,cdb03 --listen-addr=:26257 --http-addr=:8080 --certs-dir=/certs
networks:
- cockroach
networks:
cockroach:
driver: bridge
Перезапускаем docker compose и снова заходим в бразуер http://127.0.0.1:8080, вы будете предупреждены что сертификат сервера не является доверенным, просто пройдите игнорируя предупреждение, вы снова попадете на страницу с консолью, но в этот раз, вам нужно будет авторизоваться, а для этого нам нужно будет создать пользователя, на странице вам дают подсказку как это сделать. Что ж, делаем как написано.
За одно назначим этому пользователю привилегии для управления базой которую мы создали ранее:
>>> docker exec -it cdb01 sh
cockroach sql --certs-dir=/certs --host=cdb01
CREATE USER craig WITH PASSWORD 'cockroach';
GRANT ALL ON DATABASE bank TO craig WITH GRANT OPTION;
GRANT ALL ON TABLE bank.* TO craig;
SHOW GRANTS ON TABLE bank.accounts;
Теперь вы можете зайти в браузер с логином craig
и паролем cockroach
. Как видим, мы запустили кластер уже в
боевом режиме. Теперь все данные шифруются и все работает так как должно. Конечно на production серед вы должны
ограничить доступ к порту базы только необходимыми хостами, безопасности не бывает много.
Но теперь мне снова хочется выбрать данные через python, немного изменю свой скрипт, добавив в него необходимость использовать SSL а так же укажем путь до сертификата:
import psycopg2
conn = psycopg2.connect(dbname='bank',user='craig', password='cockroach',
host='localhost', port='26257',
sslmode='require', sslrootcert='./certs/ca.crt')
cursor = conn.cursor()
cursor.execute('SELECT * FROM accounts LIMIT 10')
records = cursor.fetchall()
for row in records:
print('id: %s, balance: %s' % row, '\nRaw data:', row, '\n')
cursor.close()
conn.close()
Вывод:
>>> python get.py
id: 1, balance: 1000.50
Raw data: (1, Decimal('1000.50'))
Ссылки по теме
- https://www.cockroachlabs.com/docs/stable/start-a-local-cluster.html
- https://www.cockroachlabs.com/docs/stable/manage-certs-cli.html
- https://www.cockroachlabs.com/docs/stable/connection-parameters.html
- https://github.com/cockroachdb/cockroach
- https://pypi.org/project/psycopg2/
- https://www.psycopg.org/docs/usage.html#passing-parameters-to-sql-queries
Home »