CockroachDB это вам не PostgreSQL

CockroachDB что это?

Сегодня хотел бы поделиться своими ощущениями о 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

insecure_console

В консоли множество полезной информации, пробегитесь по ней, думаю, вам будет интересно ознакомиться, полезно то, что это часть функционала сервиса, то есть вы получаете это сразу из коробки, не надо ставить дополнительно 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, вы будете предупреждены что сертификат сервера не является доверенным, просто пройдите игнорируя предупреждение, вы снова попадете на страницу с консолью, но в этот раз, вам нужно будет авторизоваться, а для этого нам нужно будет создать пользователя, на странице вам дают подсказку как это сделать. Что ж, делаем как написано.

insecure_console

За одно назначим этому пользователю привилегии для управления базой которую мы создали ранее:

>>> 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')) 

Ссылки по теме



Home »