Руководство для начинающих¶
В этом руководстве вы познакомитесь с основными возможностями Tarantool CDC.
В примере мы разворачиваем кластер Tarantool CDC и две тестовые СУБД (PostgreSQL и TarantoolDB), запускаем синхронизацию данных из PostgreSQL в TarantoolDB, а затем проверяем работу стенда с помощью мониторинга и запускаем нагрузочное тестирование.
Для простоты развертывания в примере используются Docker и minikube.
Важно
Запуск в Docker и minikube является вспомогательным способом и используется
для тестирования и демонстрации в примерах документации.
Для целевого развертывания Tarantool CDC используйте Руководство по установке.
Руководство включает следующие шаги:
Требования к окружению¶
Данный пример можно запускать в разных ОС (Linux, MacOS, Windows) на архитектуре x86.
Для работы с примером нужно установить локально:
Prometheus 2.30+ и Grafana 9.5+ (инструкция по их установке приведена ниже, в разделе TarantoolDB 2.x, шаг 2)
Также в примере используются Docker-образы PostgreSQL 16.4 (БД-источник) и TarantoolDB 2.0 (БД-приемник). Инструкции по их установке приводятся ниже.
Установка и конфигурация¶
Minikube¶
Для minikube рекомендуется выделить достаточное количество ресурсов, как минимум:
4CPU+
10Gb+ RAM
50Gb+ Disk
Запустите minikube со следующими параметрами:
minikube start --driver=docker --cpus 4 --memory=10240 --disk-size 50GB
Убедитесь, что minikube успешно запущен:
$ minikube status
minikube
type: Control Plane
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured
PostgreSQL¶
В качестве примера мы используем СУБД PostgreSQL 16.4, запущенную в Docker.
Создайте файл
init.sql:-- Create Person table CREATE TYPE gender AS ENUM ('male', 'female'); CREATE TABLE "Person" ( "uid" BIGINT PRIMARY KEY, "firstname" VARCHAR(256) NOT NULL, "lastname" VARCHAR(256) NOT NULL, "gender" gender NOT NULL, "birthdate" TIMESTAMPTZ NOT NULL, "age" INT, "metadata" JSONB, "description" TEXT, "enabled" BOOLEAN DEFAULT false ); -- Insert 10,000 random tuples into the Person table INSERT INTO "Person" (uid, firstname, lastname, gender, birthdate, age, metadata, description, enabled) SELECT gs AS uid, md5(random()::text || clock_timestamp()::text)::varchar(8) AS firstname, md5(random()::text || clock_timestamp()::text)::varchar(10) AS lastname, (ARRAY['male', 'female'])[floor(random() * 2 + 1)]::gender AS gender, timestamp '1950-01-01' + random() * (timestamp '2000-01-01' - timestamp '1950-01-01') AS birthdate, (random() * (70 - 18) + 18)::INT AS age, jsonb_build_object('key1', md5(random()::text)::varchar(5), 'key2', (random() * 100)::INT, 'key3', (random() > 0.5)) AS metadata, md5(random()::text || clock_timestamp()::text)::varchar(50) AS description, (random() > 0.5) AS enabled FROM generate_series(1, 10000) AS gs;
Скачайте и запустите Docker-контейнер с PostgreSQL 16.4 (для удобства дальнейшей работы рекомендуется выполнять эту команду в отдельном окне терминала):
docker run --rm --name postgresql-sourcedb -p 5432:5432 -m 1g \ -e POSTGRES_USER=demouser -e POSTGRES_PASSWORD=demopasswd -e POSTGRES_DB=demo \ -e POSTGRES_INITDB_ARGS="--encoding=UTF-8 --lc-collate=C --lc-ctype=C" \ -v $(pwd)/init.sql:/docker-entrypoint-initdb.d/init.sql \ postgres:16.4 -c wal_level=logical -c max_connections=500
Здесь мы настраиваем PostgreSQL так, как описано в требованиях к работе с Tarantool CDC.
Примечание
Увеличенное значение
max_connectionsнужно для корректной работы нагрузочного скрипта для K6.В случае успешного запуска в консоли появятся записи такого рода:
<...> waiting for server to start....2025-02-26 18:16:06.713 UTC [47] LOG: starting PostgreSQL 16.4 (Debian 16.4-1.pgdg120+2) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit 2025-02-26 18:16:06.716 UTC [47] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432" 2025-02-26 18:16:06.724 UTC [50] LOG: database system was shut down at 2025-02-26 18:16:06 UTC 2025-02-26 18:16:06.730 UTC [47] LOG: database system is ready to accept connections done server started CREATE DATABASE /usr/local/bin/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/init.sql CREATE TYPE CREATE TABLE INSERT 0 10000 <...> PostgreSQL init process complete; ready for start up. <...> 2025-02-26 18:16:07.744 UTC [1] LOG: database system is ready to accept connections
TarantoolDB 2.x¶
Как и для PostgreSQL, в качестве примера мы используем СУБД TarantoolDB 2.0, запущенную в Docker.
Установите Docker-образ TarantoolDB:
a. Скачайте aрхив tarantooldb-docker-image-2.0.0.linux.x86_64.tar.gz с Docker-образом TarantoolDB 2.0.0 в личном кабинете на сайте
tarantool.io, в разделе packages/tarantooldb/release/docker-image/2.x/.b. Загрузите архив в Docker:
docker image load --input tarantooldb-docker-image-2.0.0.linux.x86_64.tar
c. Добавьте для Docker-образа тег 2x-latest:
docker image tag tarantooldb:2.0.0 tarantooldb:2x-latest
Установите Docker-образы Prometheus и Grafana:
a. Скачайте архивы с этими Docker-образами в личном кабинете на сайте
tarantool.io, в разделе third-party-docker-images.b. Загрузите архивы в Docker:
docker image load --input grafana_9.5.14.tar docker image load --input prometheus_v2.30.3.tar
c. Проверьте, что Docker-образы успешно загружены:
docker image list
Скачайте и распакуйте исходные файлы примера
up_with_docker_composeдля развертывания тестового кластера TarantoolDB.С помощью скрипта миграции создайте новый спейс
Person, повторяющий схему данных в БД-источнике. Код миграции сохраните в файле003_create_space_person.luaв директорииcluster/migrations/scenario/из распакованного на предыдущем шаге архива с примером.local helpers = require('tt-migrations.helpers') local function up() -- table with the same fields as in Person table in PostgreSQL, -- plus bucket_id field for sharding local space = box.schema.space.create('Person', { if_not_exists = true, format = { { name = 'uid', type = 'number' }, { name = 'firstname', type = 'string' }, { name = 'lastname', type = 'string'}, { name = 'gender', type = 'string' }, { name = 'birthDate', type = 'datetime' }, -- since sink connector doesn't work with logical types { name = 'age', type = 'number', is_nullable = true }, { name = 'metadata', type = 'any', is_nullable = true }, { name = 'description', type = 'string', is_nullable = true }, { name = 'enabled', type = 'boolean'}, { name = 'bucket_id', type = 'unsigned'}, } }) space:create_index('pk', { parts = { 'uid' }, if_not_exists = true }) space:create_index('bucket_id', { parts = { 'bucket_id' }, unique = false, if_not_exists = true }) helpers.register_sharding_key(space.name, { 'uid' }) end return { apply = { scenario = up } }
Здесь мы настраиваем TarantoolDB так, как описано в требованиях к работе с Tarantool CDC.
Примечание
Для примера мы не создаем отдельного пользователя для Tarantool CDC, а используем существующего по умолчанию пользователя
admin.Перейдите в директорию примера
up_with_docker_composeи запустите кластер TarantoolDB:cd up_with_docker_compose make start
В случае успешного запуска в консоли появятся записи такого рода:
$ make start 45dc73a20f5142057688c7200a1e581fdca25491651b22e6e1a4047426ce6b82 [+] Running 6/6 ✔ Container tools-prometheus-1 Started 1.7s ✔ Container tools-grafana-1 Started 1.8s ✔ Container tools-tcm-1-1 Started 1.6s ✔ Container tools-etcd1-1 Started 1.8s ✔ Container tools-etcd2-1 Started 1.6s ✔ Container tools-etcd3-1 Started 2.0s Load config done [+] Running 9/9 ✔ Container cluster-tarantool-router-spb-1 Started 4.1s ✔ Container cluster-tarantool-storage-1-spb-1 Started 3.9s ✔ Container cluster-tarantool-storage-2-spb-1 Started 3.4s ✔ Container cluster-tarantool-router-msk-1 Started 3.6s ✔ Container cluster-tarantool-storage-2-brn-1 Started 3.6s ✔ Container cluster-tarantool-storage-1-brn-1 Started 3.1s ✔ Container cluster-tarantool-storage-2-msk-1 Started 3.9s ✔ Container cluster-tarantool-storage-1-msk-1 Started 3.7s ✔ Container cluster-init_host-1 Started
Tarantool CDC¶
В отличие от обеих СУБД, запущенных в Docker, образы компонентов Tarantool CDC разворачиваются в minikube.
Скачайте пакет поставки Tarantool CDC, как написано в инструкции.
Вам понадобятся:
Главный архив (
tarantool-cdc-bundle-0.9.0.tar.gz).Файл конфигурации для панели мониторинга Grafana (
tarantool-cdc-dashboard_rev3.json).
Распакуйте главный архив
tarantool-cdc-bundle-0.9.0.tar.gzи загрузите вminikubeвсе входящие в него образы:minikube image load sink-worker-all-0.9.0-docker-image.tar.gz \ tt-docker-image-2.10.0.tar.gz \ source-worker-all-0.9.0-docker-image.tar.gz \ message-queue-ee-2.5.3-docker-image.tar.gz
Настройте
kubectlдля работы сminikube:kubectl config use-context minikube
или установите
kubeconfigчерез переменную окружения:export KUBECONFIG=~/.kube/config kubectl config current-context
Создайте пространство имен (namespace), в котором будет разворачиваться кластер Tarantool CDC:
kubectl create namespace tarantool-cdc-demo
Теперь Tarantool CDC готов к запуску. Но сначала нужно настроить мониторинг с помощью Grafana.
Настройка мониторинга¶
Добавьте репозиторий с
kube-prometheus-stackвminikube:helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
Оставьте только нужные компоненты
kube-prometheus-stack. Для этого создайте файлkube-prometheus-stack-values.yaml:# Disable components that are not needed defaultRules: create: false alertmanager: enabled: false kubeApiServer: enabled: false kubelet: enabled: false cAdvisorMetricRelabelings: [] kubeControllerManager: enabled: false coreDns: enabled: false kubeDns: enabled: false kubeEtcd: enabled: false kubeScheduler: enabled: false kubeProxy: enabled: false nodeExporter: enabled: false kubernetesServiceMonitors: enabled: false prometheusOperator: enabled: true # Enable Prometheus prometheus: enabled: true prometheusSpec: podMonitorSelectorNilUsesHelmValues: false serviceMonitorSelectorNilUsesHelmValues: false scrapeInterval: "5s" # Set the scrape interval to 5 seconds # Enable Grafana grafana: enabled: true # Disable additional exporters and services kubeStateMetrics: enabled: false # Disable additional monitoring additionalPrometheusRulesMap: {} additionalScrapeConfigs: []
Установите
kube-prometheus-stackвminikubeили используйте уже установленный:helm upgrade kube-prometheus-stack --install --namespace monitoring --create-namespace \ prometheus-community/kube-prometheus-stack -f kube-prometheus-stack-values.yaml
Запуск подов может занять 1-2 минуты. Убедитесь, что они находятся в статусе
Running:$ kubectl -n monitoring get pod NAME READY STATUS RESTARTS AGE kube-prometheus-stack-grafana-6bbf7df694-lc8rv 3/3 Running 12 (2m45s ago) 13d kube-prometheus-stack-operator-df7db7df9-n6zt4 1/1 Running 25 (118s ago) 13d prometheus-kube-prometheus-stack-prometheus-0 2/2 Running 14 (2m45s ago) 13d
Создайте файл
tarantool-cdc-monitors.yaml:--- kind: PodMonitor apiVersion: monitoring.coreos.com/v1 metadata: name: tqe-grpc-monitor namespace: monitoring spec: namespaceSelector: matchNames: - tarantool-cdc-demo selector: matchExpressions: - key: app operator: In values: - cdc-tqe-api-consumer-0 - cdc-tqe-api-publisher - cdc-tqe-api-pubsub podMetricsEndpoints: - path: /metrics port: monitoring ... --- kind: PodMonitor apiVersion: monitoring.coreos.com/v1 metadata: name: tqe-tarantool-monitor namespace: monitoring spec: namespaceSelector: matchNames: - tarantool-cdc-demo selector: matchExpressions: - key: app operator: In values: - tarantool podMetricsEndpoints: - path: /metrics port: http ... --- kind: PodMonitor apiVersion: monitoring.coreos.com/v1 metadata: name: cdc-monitor namespace: monitoring spec: namespaceSelector: matchNames: - tarantool-cdc-demo selector: matchLabels: cdc.tarantool.io/component: worker podMetricsEndpoints: - path: /actuator/prometheus port: http ...
Подключите PodMonitor к мониторингу:
kubectl apply -f tarantool-cdc-monitors.yaml
Пробросьте порт от Grafana с помощью
kubectl:kubectl -n monitoring get svc kubectl -n monitoring port-forward svc/kube-prometheus-stack-grafana 3000:80 &
или воспользуйтесь функцией
port-forwardв K9s (SHIFT-Fна под сgrafana).Зайдите в Grafana (
localhost:3000), используя стандартные логин и пароль:admin:prom-operator.Импортируйте панель мониторинга
tarantool-cdc-dashboard_rev3.jsonиз пакета поставки Tarantool CDC:a. Нажмите Dashboards в меню слева.
b. Нажмите New. В выпадающем меню выберите пункт Import.
c. Загрузите JSON-файл с панелью мониторинга.
d. Нажмите Import.
В результате отобразится панель мониторинга Tarantool CDC, но данные в ней появятся только после запуска CDC.
Запуск CDC¶
Перейдите в директорию с распакованным главным архивом:
cd tarantool-cdc-bundle-0.9.0
Распакуйте архив с helm-чартом в новую директорию
helm-chart-cdc:mkdir helm-chart-cdc tar -xzf helm-chart-cdc-0.8.2.tar.gz -C helm-chart-cdc --strip-components=1
Скачайте YAML-файл cdc-pg-tdb-example.yaml с примером конфигурации для helm-чарта. Сохраните файл в директории с распакованным главным архивом.
Примечание
Для запуска на Windows и macOS, в этом файле нужно поменять все вхождения подстроки
minikube.host.internalнаhost.docker.internal.Запустите кластер Tarantool CDC.
Удалите PVC от предыдущих запусков:
kubectl -n tarantool-cdc-demo delete pvc --all
Установите кластер:
helm install -n tarantool-cdc-demo -f k8s/samples/quickstart/cdc-pg-tdb-example.yaml cdc helm-chart-cdc/
Запуск всех подов может занять 1-2 минуты.
Проверьте, что кластер Tarantool CDC успешно запустился:
a. В K9s откройте список всех подов в пространстве имен
tarantool-cdc-demo:k9s -n tarantool-cdc-demo
b. Убедитесь, что все поды находятся в статусе Running или Completed (колонка STATUS).
Если под находится в статусе Init, то нужно подождать еще немного, чтобы он загрузился.

c. Убедитесь, что в журналах обработчиков (worker) отсутствуют ошибки подключения к БД
(в списке выберите по очереди каждый из подов, у которого в имени есть worker, и нажмите клавишу L).

Проверьте, что данные о кластере Tarantool CDC появились на панели мониторинга в Grafana (обновите страницу мониторинга в браузере).

Запуск постоянной нагрузки¶
Теперь проверим работу стенда, запустив нагрузочное тестирование с помощью утилиты K6.
Создайте скрипт
load_test_tarantool_const_rps.jsдля нагрузочного тестирования:import { check, sleep } from 'k6'; import exec from 'k6/execution'; import faker from "k6/x/faker"; import sql from "k6/x/sql"; import driver from "k6/x/sql/driver/postgres"; // Database connection configuration const db = sql.open(driver, 'postgres://demouser:demopasswd@localhost:5432/demo?sslmode=disable'); // k6 options export const options = { scenarios: { constant_rps: { executor: 'constant-arrival-rate', rate: 150, // 150 iterations per second timeUnit: '1s', // Time unit for the rate duration: '10m', // Total duration of the test preAllocatedVUs: 50, // Pre-allocate VUs for the test maxVUs: 200, // Maximum VUs to allow for the test }, }, thresholds: { http_req_duration: ['p(95)<500'], // 95% of requests should complete below 500ms }, }; // Define the range of UIDs to use const UID_START = 1; const UID_END = 100; // Function to get a random UID within the specified range function getRandomUid() { return Math.floor(Math.random() * (UID_END - UID_START + 1)) + UID_START; } export default function () { // Randomly select a UID for each operation const uid = getRandomUid(); // Generate fake data const firstname = faker.person.firstName(); const lastname = faker.person.lastName(); const gender = faker.person.gender(); const birthDate = faker.time.date("RFC3339"); const age = faker.numbers.int16(); const metadata = JSON.stringify({ key1: faker.word.word(), key2: faker.numbers.int8(), key3: faker.numbers.boolean(), }); const description = faker.word.sentence(5); const enabled = faker.numbers.boolean(); // Insert operation (using a unique value to avoid conflicts) let insertResult = db.exec( 'INSERT INTO "Person" (uid, firstname, lastname, gender, birthdate, age, metadata, description, enabled) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) ON CONFLICT (uid) DO NOTHING', uid + 1000, firstname, lastname, gender, birthDate, age, metadata, description, enabled ); // console.log('[INSERT] res: ', insertResult); check(insertResult, { 'insert successful': (r) => r.err == '', }); // Update operation let updateResult = db.exec( 'UPDATE "Person" SET firstname = $1, lastname = $2, age = $3 WHERE uid = $4', firstname, lastname, age, uid + 1000 ); // console.log('[UPDATE] res: ', updateResult); check(updateResult, { 'update successful': (r) => r.err == '', }); // Delete operation let deleteResult = db.exec('DELETE FROM "Person" WHERE uid = $1', uid + 1000); // console.log('[DELETE] res: ', updateResult); check(deleteResult, { 'delete successful': (r) => r.err == '', }); } export function teardown() { db.close(); }
Запустите Docker-контейнер с K6 SQL:
Для Linux
docker run --rm -it -u "$(id -u):$(id -g)" -v "${PWD}:/xk6" \ grafana/xk6 build v0.57.0 \ --with github.com/grafana/xk6-sql@v1.0.4 \ --with github.com/grafana/xk6-sql-driver-postgres \ --with github.com/grafana/xk6-faker@v0.4.2
Для macOS
docker run --rm -it -e GOOS=darwin -u "$(id -u):$(id -g)" -v "${PWD}:/xk6" \ grafana/xk6 build v0.57.0 \ --with github.com/grafana/xk6-sql@v1.0.4 \ --with github.com/grafana/xk6-sql-driver-postgres \ --with github.com/grafana/xk6-faker@v0.4.2
Для Windows (PowerShell)
docker run --rm -it -e GOOS=windows -u "$(id -u):$(id -g)" -v "${PWD}:/xk6" ` grafana/xk6 build v0.57.0 --output k6.exe ` --with github.com/grafana/xk6-sql@v1.0.4 ` --with github.com/grafana/xk6-sql-driver-postgres ` --with github.com/grafana/xk6-faker@v0.4.2
В результате будет создан исполняемый файл
k6илиk6.exe. Поместите его в ту же директорию, что и скрипт для нагрузочного тестирования.Запустите скрипт с циклической нагрузкой:
Для Linux/macOS
./k6 run load_test_tarantool_const_rps.js
Для Windows (PowerShell)
k6.exe run load_test_tarantool_const_rps.js
Проконтролируйте работу CDC с помощью Grafana.
В панели мониторинга Tarantool CDC отображаются основные параметры работы системы:
количество обработанных событий CDC в секунду;
объем трафика, проходящего через систему;
ошибки.
Остановка стенда¶
Чтобы корректно остановить Tarantool CDC и обе СУБД, выполните следующие команды:
# Остановите кластер Tarantool CDC:
helm uninstall cdc -n tarantool-cdc-demo
minikube stop
# Остановите кластер TarantoolDB (из директории up_with_docker_compose):
make stop
# Остановите PostgreSQL:
docker stop postgresql-sourcedb