Руководство пользователя
Настоящее Руководство содержит описание функционала, доступного пользователям Tarantool Change Data Capture.
Tarantool Change Data Capture (далее Tarantool CDC) - это решение, предназначенное для репликации данных между несколькими информационными системами в реальном времени на основе потока событий изменений данных.
Tarantool CDC позволяет решать следующие задачи:
- Поддержание актуальности и согласованности данных в ИТ-контуре компании.
- Снижение нагрузки на оперативные базы данных.
- Предоставление данных для работы сервисов принятия решений в реальном времени (RTDM).
- Наполнение Источников данных для подготовки отчетности и аналитики в режиме реального времени.
- Разные сценарии переноса данных в том числе:
- Синхронизация данных из Tarantool в другие СУБД.
- Двусторонняя синхронизация Tarantool ↔ PostgreSQL.
- Миграция данных из проприетарных СУБД.
- Наполнение кэш-витрин в Tarantool из мастер-базы (в том числе Oracle без GoldenGate).
Tarantool CDC применяется в высоконагруженных ИТ-решениях в таких сферах, как финтех, маркетинг в реальном времени, логистика, телеком.
Преимущества Tarantool Change Data Capture:
- Высокая производительность.
- Отказоустойчивость и масштабируемость из коробки в том числе за счет очереди Tarantool Queue Enterprise.
- Репликация из Oracle в реальном времени без использования Golden Gate.
- Нативная совместимость с экосистемой Debezium (готовые коннекторы):
- из PostgreSQL (Debezium), Oracle + OLR (Debezium).
- в ClickHouse (через коннектор для KafkaConnect) и в любую СУБД с JDBC-интерфейсом, например PostgreSQL (Debezium).
- Собственные коннекторы:
- из Tarantool (Tarantool DB 1x/ 2x, Tarantool Data Grid 2.11+, Tarantool Queue Enterprise 2.x/ 3.x) и Kafka.
- в Tarantool (Tarantool DB 1x/ 2x, Tarantool Queue Enterprise 2.x/ 3.x), Elasticsearch, Kafka.
Документация Tarantool CDC включает следующие руководства:
- Описание архитектуры.
- Руководство по установке.
- Руководство администратора.
- Руководство пользователя.
В этом разделе вы познакомитесь с основными возможностями Tarantool CDC на двух примерах.
Вы развернете кластер Tarantool CDC и две СУБД (PostgreSQL и TarantoolDB):
- В первом примере вы настроите передачу данных из PostgreSQL в TarantoolDB через очередь TQE.
- Во втором примере вы настроите передачу данных из PostgreSQL в TarantoolDB напрямую.
Успешное выполнение примеров быстрого старта зависит от доступных ресурсов на вашей локальной машине.
При недостатке ресурсов возможны периодические падения подов (CrashLoopBackOff, OOMKilled) с последующим
восстановлением, медленная передача данных и ошибки подключения к базам данных.
В конце каждого примера вы проверите работу стенда через мониторинг и запустите нагрузочное тестирование.
Для простоты развертывания в примерах используются Docker и kind.
Примеры этого раздела можно запускать в разных ОС (Linux, macOS, Windows) на архитектуре x86 и в macOS на архитектуре ARM64 (macOS Apple Silicon).
- Для удобства и наглядности создайте и перейдите в директорию, в которой будет проходить работа с примером:
mkdir quickstart && cd quickstart
-
Установите локально:
- Docker Engine или Docker Desktop.
- kind v0.20+ (Kubernetes in Docker).
- kubectl v1.28.9+.
- helm v3.14+.
- K9s.
-
Скачайте и переместите в рабочую директорию следующие образы Docker:
- Образ tarantooldb-docker-image-2.0.0.linux.x86_64.tar.gz. В обоих примерах он будет использоваться как образец Приемника.
- Образы Prometheus и Grafana из каталога (third-party-docker-images).
Инструкции по установке этих образов приводятся ниже.
Пример включает следующие шаги:
- Установка и конфигурация.
- Настройка мониторинга в Grafana.
- Подготовка потока данных из PostgreSQL в очередь TQE.
- Подготовка потока данных из очереди TQE в TarantoolDB.
- Запуск постоянной нагрузки.
- Остановка стенда.
Запуск kind будет выполняться через docker. Для успешного запуска в настройках docker выделите
достаточное количество ресурсов. Оптимальное количество ресурсов:
- 8 CPU+.
- 12 GB+ RAM.
- 50 GB+ Disk.
Создайте файл kind-config.yaml:
cat > kind-config.yaml <<'EOF'kind: ClusterapiVersion: kind.x-k8s.io/v1alpha4name: cdc-demonodes:- role: control-planeimage: kindest/node:v1.32.0kubeadmConfigPatches:- |kind: InitConfigurationnodeRegistration:kubeletExtraArgs:node-ip: 0.0.0.0EOF
Запустите kind-кластер:
-
Для OS Linux, macOS, Windows на архитектуре x86 выполните:
kind create cluster --config kind-config.yaml -
Для macOS на архитектуре ARM64 выполните:
env -u DOCKER_DEFAULT_PLATFORM kind create cluster --config kind-config.yaml
Убедитесь, что kind-кластер успешно запущен:
$ kubectl cluster-infoKubernetes control plane is running at https://127.0.0.1:XXXXX...$ kind get clusterscdc-demo
В качестве примера используется СУБД PostgreSQL 16.4, запущенная в Docker.
-
Создайте файл
init.sql:cat > init.sql << 'EOF'-- Create Person tableCREATE 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 tableINSERT INTO "Person" (uid, firstname, lastname, gender, birthdate, age, metadata, description, enabled)SELECTgs 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 enabledFROM generate_series(1, 10000) AS gs;EOF -
Проверьте, что файл с нужным наполнением создан:
tail -10 init.sql -
Откройте отдельное окно терминала для запуска PostgreSQL.
-
Скачайте образ 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-bit2025-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 UTC2025-02-26 18:16:06.730 UTC [47] LOG: database system is ready to accept connectionsdoneserver startedCREATE DATABASE/usr/local/bin/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/init.sqlCREATE TYPECREATE TABLEINSERT 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.0, запущенная в Docker.
-
Установите Docker-образ TarantoolDB:
a. Загрузите ранее скачанный образ TarantoolDB в Docker:
docker image load --input tarantooldb-docker-image-2.0.0.linux.x86_64.tar.gzb. Присвойте образу Docker тег
2x-latest:docker image tag tarantooldb:2.0.0 tarantooldb:2x-latest -
Установите Docker-образы Prometheus и Grafana:
a. Загрузите ранее скачанные образы в Docker:
docker image load --input grafana_9.5.14.tar.gzdocker image load --input prometheus_v2.30.3.tar.gzb. Проверьте, что Docker-образы успешно загружены:
docker image list -
Скачайте, перенесите в рабочую директорию и распакуйте исходные файлы примера
up_with_docker_composeдля развертывания тестового кластера TarantoolDB.
-
В рабочей директории замените содержимое файла
docker-compose.ymlв директорииup_with_docker_compose/cluster:cat > up_with_docker_compose/cluster/docker-compose.yml <<'EOF'services:tarantool-router-msk:image: tarantooldb:2x-latestnetworks:- tarantooldb_networkports:- "3301:3301"environment:- TT_INSTANCE_NAME=router-msk- TT_CONFIG_ETCD_ENDPOINTS=http://etcd1:2379,http://etcd2:2379,http://etcd3:2379- TT_CONFIG_ETCD_PREFIX=/tdb- TT_CONFIG_ETCD_HTTP_REQUEST_TIMEOUT=3tarantool-storage-1-msk:image: tarantooldb:2x-latestnetworks:- tarantooldb_networkports:- "3303:3301"environment:- TT_INSTANCE_NAME=storage-1-msk- TT_CONFIG_ETCD_ENDPOINTS=http://etcd1:2379,http://etcd2:2379,http://etcd3:2379- TT_CONFIG_ETCD_PREFIX=/tdb- TT_CONFIG_ETCD_HTTP_REQUEST_TIMEOUT=3init_host:image: tarantooldb:2x-latestnetworks:- tarantooldb_networkvolumes:- ./migrations/:/app/tarantooldb/migrations/depends_on:- tarantool-router-msk- tarantool-storage-1-mskenvironment:- TT_CLI_USERNAME=admin- TT_CLI_PASSWORD=secret-cluster-cookiecommand: /bin/sh -c "\tools/client/wait_instance_ready.sh 90 tarantool-router-msk:3301 \&& tools/client/wait_instance_ready.sh 90 tarantool-storage-1-msk:3301 \&& tt replicaset vshard bootstrap tarantool-router-msk:3301 \&& tt migrations publish http://etcd1:2379/tdb migrations \&& tt migrations apply http://etcd1:2379/tdb \&& echo Initialize has completed successfully."networks:tarantooldb_network:external: trueEOF -
В рабочей директории замените содержимое файла
config.ymlв директорииup_with_docker_compose/cluster:cat > up_with_docker_compose/cluster/config.yml <<'EOF'credentials:users:admin:password: 'secret-cluster-cookie'roles: [super]client:password: 'secret'roles: [super]replicator:password: 'secret'roles: [replication]storage:password: 'secret'roles: [sharding]iproto:advertise:peer:login: replicatorsharding:login: storagesharding:bucket_count: 30000roles_cfg:roles.metrics-export:http:- endpoints:- format: prometheuspath: /metricslisten: 8081groups:routers:replication:failover: manualsharding:roles: [router]roles:- roles.crud-router- roles.metrics-export- roles.dictionary-routerroles_cfg:roles.crud-router:stats: truestats_driver: metricsstats_quantiles: truestats_quantile_tolerated_error: 0.001stats_quantile_age_buckets_count: 5stats_quantile_max_age_time: 180replicasets:router-msk:leader: router-mskinstances:router-msk:iproto:listen:- uri: tarantool-router-msk:3301advertise:client: tarantool-router-msk:3301storages:replication:failover: electionsharding:roles: [storage]roles:- roles.crud-storage- roles.metrics-export- roles.dictionary-storageroles_cfg:roles.expirationd: [ ]replicasets:storage-1:instances:storage-1-msk:iproto:listen:- uri: tarantool-storage-1-msk:3301advertise:client: tarantool-storage-1-msk:3301EOF -
В рабочей директории создайте файл
003_create_space_person.luaв директорииup_with_docker_compose/cluster/migrations/scenario/со скриптом из примера ниже. Это скрипт миграции, который создает новый спейсPerson, повторяющий схему данных в Источнике (файлinit.sql).cat > up_with_docker_compose/cluster/migrations/scenario/003_create_space_person.lua << 'EOF'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 shardinglocal 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' })endreturn {apply = {scenario = up}}EOFЗдесь вы настраиваете TarantoolDB согласно требованиям к работе с Tarantool CDC.
Внимание! В примере не создается отдельный пользователь для Tarantool CDC. Используется существующий по умолчанию пользователь
admin. -
Перейдите в директорию примера
up_with_docker_composeи запустите кластер TarantoolDB:cd up_with_docker_composemake startПри успешном запуске в консоли появятся записи вида:
$ make start45dc73a20f5142057688c7200a1e581fdca25491651b22e6e1a4047426ce6b82[+] 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.0sLoad config done[+] Running 9/9✔ Container cluster-tarantool-router-msk-1 Started 3.6s✔ Container cluster-tarantool-storage-1-msk-1 Started 3.7s✔ Container cluster-init_host-1 Started
При повторном прохождении сценария вы можете получить ошибку Error response from daemon: network with name <network_name> already exists. В таком случае остановите и удалите предыдущий кластер:
make stopmake clean
После этих действий команда make start отработает штатно.
В отличие от СУБД, запущенных в Docker, компоненты Tarantool CDC разворачиваются в kind.
-
Скачайте архив tarantool-cdc-bundle-
-0.12.0.tar.gz Гдеos- это название операционной системы, дистрибутив которой использован для Docker образов. В этом примере используется образ дистрибутива Ubuntu. -
Перенесите архив в рабочую директорию.
-
Распакуйте архив
tarantool-cdc-bundle-<os>-0.12.0.tar.gz. -
Перейдите в директорию распакованного архива и загрузите образ в Docker, а затем в
kind:docker image load --input cdc-worker-all-0.12.0-docker-image.tar.gzkind load docker-image --name cdc-demo tarantool-cdc/cdc-worker-all:0.12.0 -
Настройте
kubectlдля работы сkind-кластером:kubectl config use-context kind-cdc-demoили установите
kubeconfigчерез переменную окружения:export KUBECONFIG=~/.kube/configkubectl config current-context -
Создайте пространство имен (
namespace), в котором будет развернут кластер Tarantool CDC:kubectl create namespace tarantool-cdc-demo
TQE будет служить промежуточным буфером между PostgreSQL и TarantoolDB. Универсальный Обработчик будет читать изменения в PostgreSQL и отправлять их в эту очередь. Второй Обработчик будет читать изменения в очереди TQE и отправлять их в TarantoolDB.
-
Скачайте архивы:
- Основной архив очереди TQE, docker-message-queue-ee-v3.5.0.tar.gz.
- Архив c Helm-чартом helm-chart-tqe-3.5.0.tar.gz
-
Перенесите архивы в рабочую директорию.
-
Распакуйте архив с Helm-чартом:
tar -xzf helm-chart-tqe-3.5.0.tar.gz -
В рабочей директории загрузите образ очереди TQE в Docker, а затем в
kind:docker image load --input docker-message-queue-ee-v3.5.0.tar.gzkind load docker-image --name cdc-demo tarantool/message-queue-ee:v3.5.0 -
Создайте файл
tqe-values.yamlс настройками образа:cat > tqe-values.yaml <<'EOF'global:imagePullSecrets: []imagePullPolicy: "Never"securityContext:runAsNonRoot: truerunAsUser: 1000fsGroup: 1000image:repository: docker.io/tarantool/message-queue-eepullPolicy: "Never"pubsub:enabled: truereplicas: 1consumer:replicas: 1probes:readiness: { timeoutSeconds: 5, periodSeconds: 10, failureThreshold: 6 }liveness: { timeoutSeconds: 5, periodSeconds: 10, failureThreshold: 6 }producer:replicas: 1probes:readiness: { timeoutSeconds: 5, periodSeconds: 10, failureThreshold: 6 }liveness: { timeoutSeconds: 5, periodSeconds: 10, failureThreshold: 6 }etcdDiscovery:enabled: truetarantool:global:imagePullPolicy: "Never"ttConfigEtcdHttpRequestTimeout: 10image:repository: docker.io/tarantool/message-queue-eetag: v3.5.0pullPolicy: "Never"metrics_export:enabled: trueautoBootstrap:image:repository: docker.io/tarantool/message-queue-eetag: v3.5.0pullPolicy: "Never"storage:replicasetCount: 1replicaCount: 1persistence:storageClassName: ""resources:requests:cpu: 500mmemory: 1Gilimits:cpu: 500mmemory: 1Giprobes:liveness: { timeoutSeconds: 5, periodSeconds: 10, failureThreshold: 6 }router:replicasetCount: 1replicaCount: 1probes:liveness: { timeoutSeconds: 5, periodSeconds: 10, failureThreshold: 6 }config:memtx:memory: 536870912roles_cfg:roles.tqe-storage:queues:- name: cdcretention:length: 15000time: 0options:atomic_iteration: truepolicy: cleanup- name: offsetsdeduplication_mode: keep_latestetcd:replicaCount: 1persistence:storageClass: ""EOF -
В рабочей директории установите очередь TQE в кластер Kubernetes:
helm --namespace tarantool-cdc-demo install tqe ./tqe -f tqe-values.yamlЕсли такой под уже установлен, вы получите ошибку
Already exists. В таком случае удалите его и повторите установку:helm -n tarantool-cdc-demo uninstall tqekubectl -n tarantool-cdc-demo delete pvc --allhelm --namespace tarantool-cdc-demo install tqe ./tqe -f tqe-values.yaml -
Проверьте состояние подов:
kubectl -n tarantool-cdc-demo get podsОжидаемый результат: под
tqe-config-jobв статусеCompleted, остальные поды в состоянииREADY 1/1. Процесс может занять 2–3 минуты:NAME READY STATUS RESTARTS AGEtqe-auto-bootstrap-job-nq2qw 0/1 Completed 0 2m52stqe-etcd-0 1/1 Running 0 2m52stqe-replicaset-0-storage-0 1/1 Running 0 2m52stqe-router-0 1/1 Running 0 2m52stqe-tcm-6c7bff7576-rj7mm 1/1 Running 0 2m52stqe-tqe-api-consumer-0-0 1/1 Running 0 2m52stqe-tqe-api-producer-0 1/1 Running 2 (79s ago) 2m52stqe-tqe-api-pubsub-0 1/1 Running 0 2m52s -
Проверьте, что сервисы очереди созданы:
kubectl -n tarantool-cdc-demo get svc | grep tqeОжидаемый результат:
tqe-etcd ClusterIP 10.96.149.78 <none> 2379/TCP,2380/TCP 3m47stqe-etcd-headless ClusterIP None <none> 2379/TCP,2380/TCP 3m47stqe-replicaset-0-storage ClusterIP None <none> 3301/TCP,8081/TCP 3m47stqe-router ClusterIP None <none> 3301/TCP,8081/TCP 3m47stqe-tcm ClusterIP 10.96.252.176 <none> 8081/TCP 3m47stqe-tqe-api-consumer-0 ClusterIP None <none> 18184/TCP,18182/TCP 3m47stqe-tqe-api-producer ClusterIP None <none> 18184/TCP,18182/TCP 3m47stqe-tqe-api-pubsub ClusterIP None <none> 18184/TCP,18182/TCP 3m47s
Очередь TQE готова получать и передавать сообщения.
-
Добавьте репозиторий
kube-prometheus-stackвkind:helm repo add prometheus-community https://prometheus-community.github.io/helm-charts -
Оставьте только необходимые компоненты
kube-prometheus-stack. Для этого в рабочей директории создайте файлkube-prometheus-stack-values.yaml:cat > kube-prometheus-stack-values.yaml <<'EOF'defaultRules:create: falsealertmanager:enabled: falsekubeApiServer:enabled: falsekubelet:enabled: falsecAdvisorMetricRelabelings: []kubeControllerManager:enabled: falsecoreDns:enabled: falsekubeDns:enabled: falsekubeEtcd:enabled: falsekubeScheduler:enabled: falsekubeProxy:enabled: falsenodeExporter:enabled: falsekubernetesServiceMonitors:enabled: falseprometheusOperator:enabled: trueprometheus:enabled: trueprometheusSpec:podMonitorSelectorNilUsesHelmValues: falseserviceMonitorSelectorNilUsesHelmValues: falsescrapeInterval: "5s"grafana:enabled: truekubeStateMetrics:enabled: falseadditionalPrometheusRulesMap: {}additionalScrapeConfigs: []EOF -
Установите
kube-prometheus-stackвkindили используйте уже установленный:helm upgrade kube-prometheus-stack --install --namespace monitoring --create-namespace \prometheus-community/kube-prometheus-stack -f kube-prometheus-stack-values.yamlЗапуск подов может занять 3-5 минут. Убедитесь, что они находятся в состоянии
READY:$ kubectl -n monitoring get podNAME READY STATUS RESTARTS AGEkube-prometheus-stack-grafana-766d7c647d-l7bs8 3/3 Running 0 6m14skube-prometheus-stack-operator-7d5dd58c64-sqtcm 1/1 Running 0 6m14sprometheus-kube-prometheus-stack-prometheus-0 2/2 Running 0 6m6s -
Узнайте и сохраните пароль учетной записи
adminдля доступа в Grafana:kubectl --namespace monitoring get secrets kube-prometheus-stack-grafana -o jsonpath="{.data.admin-password}" | base64 -d ; echoВнимание! Команда возвращает пароль в незашифрованном виде. Команда получения пароля может отличаться в зависимости от версии чарта
kube-prometheus-stack. При написании этого раздела использовалась версия 80.0.0. -
В рабочей директории создайте файл
tarantool-cdc-monitors.yaml:cat > tarantool-cdc-monitors.yaml <<'EOF'---apiVersion: monitoring.coreos.com/v1kind: PodMonitormetadata:name: tqe-grpc-monitornamespace: monitoringspec:namespaceSelector:matchNames:- tarantool-cdc-demoselector:matchLabels:app.kubernetes.io/component: tqe-tqe-api-producerpodMetricsEndpoints:- path: /metricsport: monitoring---apiVersion: monitoring.coreos.com/v1kind: PodMonitormetadata:name: tqe-tarantool-monitornamespace: monitoringspec:namespaceSelector:matchNames:- tarantool-cdc-demoselector:matchLabels:app.kubernetes.io/name: tarantoolpodMetricsEndpoints:- path: /metricsport: http---apiVersion: monitoring.coreos.com/v1kind: PodMonitormetadata:name: cdc-monitornamespace: monitoringspec:namespaceSelector:matchNames:- tarantool-cdc-demoselector:matchLabels:cdc.tarantool.io/component: workerpodMetricsEndpoints:- path: /actuator/prometheusport: httpEOF -
Примените конфигурацию:
kubectl apply -f tarantool-cdc-monitors.yaml -
Пробросьте порт Grafana с помощью
kubectl:kubectl -n monitoring get svckubectl -n monitoring port-forward svc/kube-prometheus-stack-grafana 3000:80 &или воспользуйтесь функцией
port-forwardв K9s (SHIFT-Fна под сgrafana). -
В браузере зайдите в Grafana (
localhost:3000), используя логинadminи пароль, которые вы узнали в шаге4выше. -
Импортируйте панель мониторинга
universal-workers-dashboard_rev3.jsonиз основного архиваtarantool-cdc-bundle-<os>-0.12.0.tar.gz:a. Нажмите Dashboards в меню слева.
b. Нажмите New. В выпадающем меню выберите пункт Import.
c. Загрузите JSON-файл с панелью мониторинга.
d. Нажмите Import.
В результате отобразится панель мониторинга Tarantool CDC, но данные в ней появятся только после запуска CDC.
Здесь вы настроите первый поток данных: из PostgreSQL в очередь TQE.
-
Откройте новое окно терминала.
-
Перейдите в директорию с распакованным основным архивом:
cd tarantool-cdc-bundle-<os>-0.12.0 -
Создайте файл
cdc-pg-tqe.yamlс конфигурацией для потока PostgreSQL → TQE:cat > cdc-pg-tqe.yaml <<'EOF'sources:postgresql:common:connector:class: io.debezium.connector.postgresql.PostgresConnectorplugin.name: pgoutputdatabase:hostname: host.docker.internalport: 5432user: demouserpassword: demopasswddbname: demoskipped.operations: nonetombstones.on.delete: falsehstore.handling.mode: maptopic:prefix: cdcdelimiter: _time.precision.mode: adaptivetable.include.list: public.Personsinks:tarantool-queue:common:connector:class: io.tarantool.connector.sink.TQESinkConnectortarget: tqe-tqe-api-producer.tarantool-cdc-demo.svc:18182queue: cdckey.converter: org.apache.kafka.connect.json.JsonConvertervalue.converter: org.apache.kafka.connect.json.JsonConverterglobal:imagePullPolicy: "Never"image:repository: docker.io/tarantool-cdc/cdc-worker-alltag: 0.12.0pullPolicy: "Never"offset:storage:type: filefile.name: "/data/offsets.dat"persistence:enabled: truestorageClassName: "standard"storageSize: 1GimountPath: "/data"flow:- source: postgresqlsink: tarantool-queueresources:requests:cpu: 1500mmemory: 1Gilimits:cpu: 2memory: 3Gienv:JAVA_OPTS: -XX:MaxDirectMemorySize=256MEOF -
Установите Универсальный Обработчик в кластер Kubernetes:
helm -n tarantool-cdc-demo install cdc ./helm-chart-cdc -f cdc-pg-tqe.yamlЕсли такой под уже установлен, удалите его и повторите установку:
helm -n tarantool-cdc-demo uninstall cdchelm -n tarantool-cdc-demo install cdc ./helm-chart-cdc -f cdc-pg-tqe.yaml -
Проверьте, что под Универсального Обработчика запустился:
kubectl -n tarantool-cdc-demo get podsОжидаемый результат: появился под с именем, содержащим
cdc, в состоянииREADY 1/1:NAME READY STATUS RESTARTS AGEcdc-postgresql-0-tarantool-queue-0-7554ddc776-62z9v 1/1 Running 0 54stqe-etcd-0 1/1 Running 0 17m...Для детального просмотра вы можете использовать K9s:
k9s -n tarantool-cdc-demoУбедитесь, что все поды находятся в статусе Running или Completed (колонка STATUS).
Если под находится в статусе Init, подождите еще немного, пока он загрузится.
-
Проверьте журналы Универсального Обработчика на наличие ошибок:
kubectl -n tarantool-cdc-demo logs -l app.kubernetes.io/instance=cdc --tail=50В логах должны отсутствовать ошибки подключения к PostgreSQL и TQE.
В K9s в списке по очереди выберите каждый под, в имени которого есть
worker, и нажмите клавишу L. -
Для проверки работы потока передачи данных сгенерируйте событие в PostgreSQL:
docker exec -it postgresql-sourcedb psql -U demouser -d demo -c "INSERT INTO \"Person\" (uid, firstname, lastname, gender, birthdate, age, metadata, description, enabled) VALUES (10001, 'Grafana', 'Test', 'female', '1995-05-15', 30, '{\"key1\":\"monitoring\"}', 'test for grafana', true);" -
В браузере обновите окно с Grafana.

-
Убедитесь, что данные действительно попали в очередь TQE.
Запросите метрики хранилища TQE и посмотрите длину спейса очереди
queue_cdc:kubectl -n tarantool-cdc-demo exec tqe-replicaset-0-storage-0 -- \sh -c "curl -s localhost:8081/metrics | grep 'tnt_space_len'"Ожидаемый результат — счетчик
queue_cdcравен числу записей, переданных из PostgreSQL (в этом примере — 10001):tnt_space_len{alias="tqe-replicaset-0-storage-0",name="queue_cdc",engine="memtx"} 10001tnt_space_len{alias="tqe-replicaset-0-storage-0",name="consumer_state",engine="memtx"} 0tnt_space_len{alias="tqe-replicaset-0-storage-0",name="queue_offsets",engine="memtx"} 0
Теперь, когда данные из PostgreSQL поступают в очередь TQE, вы настроите второй поток, который будет забирать сообщения из очереди и записывать в TarantoolDB.
-
Откройте новое окно терминала.
-
Перейдите в рабочую директорию.
-
Убедитесь, что кластер TarantoolDB запущен:
docker ps | grep tarantooldb -
Перейдите в директорию основного архива Tarantool CDC.
cd tarantool-cdc-bundle-<os>-0.12.0 -
Для передачи данных из TQE в TarantoolDB настройте второй под Универсального Обработчика:
cat > cdc-tqe-tdb.yaml <<'EOF'sources:tarantool-queue:common:connector:class: io.tarantool.connector.source.TQESourceConnectortarget: tqe-tqe-api-consumer-0.tarantool-cdc-demo.svc:18182queue: cdcmax.batch.size: 500key.converter: org.apache.kafka.connect.json.JsonConvertervalue.converter: org.apache.kafka.connect.json.JsonConvertersinks:tarantool-db:common:connector:class: io.tarantool.connector.TarantoolSinkConnectortarantool.connection.groups: tarantool://host.docker.internal:3301/?size=4&user=admin&password=secret-cluster-cookiedelete.enabled: trueprimary.key.mode: record_keyinsert.mode: replacedatetime:handling.mode: datetimeinfinity.handling.enabled: truetransforms:chain:- topic-from-source-table- topic-from-source-space-nameconfig:topic-from-source-table:type: io.tarantool.cdc.transforms.smt.ExtractTopic$Valuefield.path: source.tableskip.missing.or.null: truetopic-from-source-space-name:type: io.tarantool.cdc.transforms.smt.ExtractTopic$Valuefield.path: source.space_nameskip.missing.or.null: trueglobal:imagePullPolicy: "Never"image:repository: docker.io/tarantool-cdc/cdc-worker-alltag: 0.12.0pullPolicy: "Never"startupProbe:failureThreshold: 40offset:storage:type: filefile.name: "/data/offsets.dat"persistence:enabled: truestorageClassName: "standard"storageSize: 1GimountPath: "/data"flow:- source: tarantool-queuesink: tarantool-dbthrottle:throttler:max:rps: 2000resources:requests:cpu: 500mmemory: 1Gilimits:cpu: 2memory: 3Gienv:JAVA_OPTS: -XX:MaxDirectMemorySize=256M -Xmx800mBPL_JVM_THREAD_COUNT: "50"EOF -
Установите второй под Универсального Обработчика:
helm -n tarantool-cdc-demo install cdc-tqe-tdb ./helm-chart-cdc -f cdc-tqe-tdb.yaml -
Проверьте, что второй под Универсального Обработчика запустился:
kubectl -n tarantool-cdc-demo get podsОжидаемый результат: поды с именем, содержащим
cdc, в состоянииREADY 1/1. Процесс может занять 4-7 минут. 2й под может перезапускаться несколько раз с различными статусами из-за оптимизированной конфигурации.NAME READY STATUS RESTARTS AGEcdc-postgresql-0-tarantool-queue-0-7554ddc776-62z9v 1/1 Running 0 8m49scdc-tqe-tdb-tarantool-queue-0-tarantool-db-0-84b74dd7d5-d477h 1/1 Running 0 2m2s... -
Убедитесь, что данные перелились из очереди TQE в TarantoolDB.
Подключитесь к роутеру TarantoolDB и посчитайте записи в спейс
Personодним из способов:-
Используйте утилиту
tt(Tarantool CLI) или установите согласно инструкции по установке и выполните:tt connect admin:secret-cluster-cookie@localhost:3301Эта команда открывает интерактивную консоль Tarantool. В интерактивной консоли выполните:
crud.count("Person")Ожидаемый результат — число записей совпадает с тем, что было передано в очередь (в этом примере — 10001):
---- 10001- null... -
Подключитесь к роутеру TarantoolDB изнутри его контейнера и выполните:
docker exec cluster-tarantool-router-msk-1 sh -c \'printf "crud.count(\"Person\")\n" | /app/tarantooldb/tt connect admin:secret-cluster-cookie@tarantool-router-msk:3301 -f -'Результат тот же — число записей в спейс
Person.
-
Проверьте работу стенда, запустив нагрузочное тестирование с помощью утилиты K6. Скрипт выполняет 167 итераций в секунду; каждая итерация — это три операции (insert, update, delete), то есть нагрузка на Источник составляет ~500 событий в секунду (EPS).
-
Создайте скрипт
load_test_tarantool_const_rps.jsдля нагрузочного тестирования:cat > load_test_tarantool_const_rps.js <<'EOF'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";const db = sql.open(driver, 'postgres://demouser:demopasswd@localhost:5432/demo?sslmode=disable');export const options = {scenarios: {constant_rps: {executor: 'constant-arrival-rate',rate: 167,timeUnit: '1s',duration: '5m',preAllocatedVUs: 50,maxVUs: 200,},},thresholds: {http_req_duration: ['p(95)<500'],},};const UID_START = 1;const UID_END = 100;function getRandomUid() {return Math.floor(Math.random() * (UID_END - UID_START + 1)) + UID_START;}export default function () {const uid = getRandomUid();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();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 + 100000, firstname, lastname, gender, birthDate, age, metadata, description, enabled);check(insertResult, {'insert successful': (r) => !r.err,});let updateResult = db.exec('UPDATE "Person" SET firstname = $1, lastname = $2, age = $3 WHERE uid = $4',firstname, lastname, age, uid + 100000);check(updateResult, {'update successful': (r) => !r.err,});let deleteResult = db.exec('DELETE FROM "Person" WHERE uid = $1', uid + 100000);check(deleteResult, {'delete successful': (r) => !r.err,});}export function teardown() {db.close();}EOF -
Запустите Docker-контейнер с K6 SQL:
Для Linux (x86_64):
docker run --rm -it -u "$(id -u):$(id -g)" -v "${PWD}:/xk6" \grafana/xk6 build latest \--with github.com/grafana/xk6-sql@latest \--with github.com/grafana/xk6-sql-driver-postgres@latest \--with github.com/grafana/xk6-faker@latestДля Windows (PowerShell):
docker run --rm -it -e GOOS=windows -u "$(id -u):$(id -g)" -v "${PWD}:/xk6" `grafana/xk6 build latest --output k6.exe `--with github.com/grafana/xk6-sql@latest `--with github.com/grafana/xk6-sql-driver-postgres `--with github.com/grafana/xk6-faker@latestДля macOS (ARM64):
docker run --rm -it -e GOOS=darwin -e GOARCH=arm64 -u "$(id -u):$(id -g)" -v "${PWD}:/xk6" \grafana/xk6 build latest \--with github.com/grafana/xk6-sql@latest \--with github.com/grafana/xk6-sql-driver-postgres@latest \--with github.com/grafana/xk6-faker@latestДля macOS (x86_64 - Intel):
docker run --rm -it -e GOOS=darwin -e GOARCH=amd64 -u "$(id -u):$(id -g)" -v "${PWD}:/xk6" \grafana/xk6 build latest \--with github.com/grafana/xk6-sql@latest \--with github.com/grafana/xk6-sql-driver-postgres@latest \--with github.com/grafana/xk6-faker@latestВ результате будет создан исполняемый файл
k6илиk6.exe. Поместите его в ту же директорию, что и скрипт нагрузочного тестирования.После сборки для Linux/macOS предоставьте права на выполнение файла:
chmod +x ./k6 -
Запустите скрипт с циклической нагрузкой:
Для 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-demohelm uninstall cdc-tqe-tdb -n tarantool-cdc-demo# Удалите namespacekubectl delete namespace tarantool-cdc-demo# Остановите мониторинг:helm uninstall kube-prometheus-stack -n monitoringkubectl delete namespace monitoring# Остановите kind-кластер:kind delete cluster --name cdc-demo# Остановите кластер TarantoolDB (из директории up_with_docker_compose):make stop# Остановите PostgreSQL:docker stop postgresql-sourcedb
При прохождении этого примера вы можете полностью или частично переиспользовать исполняемую среду, созданную в предыдущем примере. При повторном использовании убедитесь, что выбраны правильные директории при вводе команд в терминал.
Пример включает шаги:
- Установка и конфигурация. Пример прямой передачи данных.
- Настройка мониторинга в Grafana. Пример прямой передачи данных.
- Запуск CDC. Пример прямой передачи данных.
- Запуск постоянной нагрузки. Пример прямой передачи данных.
- Остановка стенда. Пример прямой передачи данных.
Требования к окружению данного примера полностью соответствуют требованиям примера с передачей данных при помощи TQE.
Требования к kind-кластеру и процесс его запуска полностью
соответствуют описанию примера
с передачей данных при помощи TQE.
Подготовка PostgreSQL в качестве Источника полностью соответствует подготовке PostgreSQL примера с передачей данных при помощи TQE.
Подготовка TarantoolDB 2.x в качестве Приемника полностью соответствует подготовке TarantoolDB 2.x примера с передачей данных при помощи TQE.
-
Скачайте основной архив (
tarantool-cdc-bundle-<os>-0.12.0.tar.gz) поставки Tarantool CDC, из личного кабинета. Гдеos- это название операционной системы, дистрибутив которой использован для Docker образов. В этом примере используется образ дистрибутива Ubuntu. -
Перенесите архив в рабочую директорию.
-
Файл панели мониторинга Grafana
universal-workers-dashboard_rev3.jsonвходит в основной архив — он понадобится позже при настройке мониторинга. -
Распакуйте архив
tarantool-cdc-bundle-<os>-0.12.0.tar.gz. -
Перейдите в директорию распакованного архива и загрузите входящий в него образ в Docker, а затем в
kind:docker image load --input cdc-worker-all-0.12.0-docker-image.tar.gzkind load docker-image --name cdc-demo tarantool-cdc/cdc-worker-all:0.12.0 -
Настройте
kubectlдля работы сkind-кластером:kubectl config use-context kind-cdc-demoили установите
kubeconfigчерез переменную окружения:export KUBECONFIG=~/.kube/configkubectl config current-context -
Создайте пространство имен (
namespace), в котором будет разворачиваться кластер Tarantool CDC:kubectl create namespace tarantool-cdc-demo
-
Добавьте репозиторий с
kube-prometheus-stackвkind:helm repo add prometheus-community https://prometheus-community.github.io/helm-charts -
Оставьте только необходимые компоненты
kube-prometheus-stack. Для этого в рабочей директории создайте файлkube-prometheus-stack-values.yaml:cat > kube-prometheus-stack-values.yaml <<'EOF'defaultRules:create: falsealertmanager:enabled: falsekubeApiServer:enabled: falsekubelet:enabled: falsecAdvisorMetricRelabelings: []kubeControllerManager:enabled: falsecoreDns:enabled: falsekubeDns:enabled: falsekubeEtcd:enabled: falsekubeScheduler:enabled: falsekubeProxy:enabled: falsenodeExporter:enabled: falsekubernetesServiceMonitors:enabled: falseprometheusOperator:enabled: true# Enable Prometheusprometheus:enabled: trueprometheusSpec:podMonitorSelectorNilUsesHelmValues: falseserviceMonitorSelectorNilUsesHelmValues: falsescrapeInterval: "5s" # Set the scrape interval to 5 seconds# Enable Grafanagrafana:enabled: true# Disable additional exporters and serviceskubeStateMetrics:enabled: false# Disable additional monitoringadditionalPrometheusRulesMap: {}additionalScrapeConfigs: []EOF -
Установите
kube-prometheus-stackвkindили используйте уже установленный:helm upgrade kube-prometheus-stack --install --namespace monitoring --create-namespace \prometheus-community/kube-prometheus-stack -f kube-prometheus-stack-values.yamlЗапуск подов может занять 1-2 минуты. Убедитесь, что они находятся в состоянии
READY:$ kubectl -n monitoring get podNAME READY STATUS RESTARTS AGEkube-prometheus-stack-grafana-659c7bb9dd-vprbx 3/3 Running 0 2m7skube-prometheus-stack-operator-7d5dd58c64-r4njf 1/1 Running 0 2m7sprometheus-kube-prometheus-stack-prometheus-0 2/2 Running 0 111s -
Узнайте и сохраните пароль учетной записи
adminдля доступа в Grafana:kubectl --namespace monitoring get secrets kube-prometheus-stack-grafana -o jsonpath="{.data.admin-password}" | base64 -d ; echoОбратите внимание, что команда возвращает пароль в незашифрованном виде. Команда получения пароля может отличаться в зависимости от версии чарта
kube-prometheus-stack. При написании этого раздела использовалась версия 80.0.0. -
В рабочей директории создайте файл
tarantool-cdc-monitors.yaml:cat > tarantool-cdc-monitors.yaml <<'EOF'kind: PodMonitorapiVersion: monitoring.coreos.com/v1metadata:name: cdc-monitornamespace: monitoringspec:namespaceSelector:any: trueselector:matchLabels:cdc.tarantool.io/component: workerpodMetricsEndpoints:- path: /actuator/prometheusport: httpEOF -
Подключите PodMonitor к мониторингу:
kubectl apply -f tarantool-cdc-monitors.yaml -
Пробросьте порт Grafana с помощью
kubectl:kubectl -n monitoring get svckubectl -n monitoring port-forward svc/kube-prometheus-stack-grafana 3000:80 &Или воспользуйтесь функцией
port-forwardв K9s (SHIFT-Fна под сgrafana). -
В браузере зайдите в Grafana (
localhost:3000), используя логин и пароль, которые вы узнали в шаге4выше. -
Импортируйте панель мониторинга
universal-workers-dashboard_rev3.json:a. Нажмите Dashboards в меню слева.
b. Нажмите New. В выпадающем меню выберите пункт Import.
c. Загрузите JSON-файл с панелью мониторинга.
d. Нажмите Import.
В результате отобразится панель мониторинга Tarantool CDC, но данные в ней появятся только после запуска CDC.
-
Откройте новое окно терминала.
-
Перейдите в директорию с распакованным основным архивом:
cd tarantool-cdc-bundle-<os>-0.12.0 -
Для передачи данных из PostgreSQL в TarantoolDB настройте под Универсального Обработчика:
cat > cdc-pg-tdb-direct.yaml <<'EOF'sources:postgresql:common:connector:class: io.debezium.connector.postgresql.PostgresConnectorplugin.name: pgoutputdatabase:hostname: host.docker.internalport: 5432user: demouserpassword: demopasswddbname: demoskipped.operations: nonetombstones.on.delete: falsehstore.handling.mode: maptopic:prefix: cdcdelimiter: _time.precision.mode: adaptivetable.include.list: public.Personsinks:tarantool-db:common:connector:class: io.tarantool.connector.TarantoolSinkConnectortarantool.connection.groups: tarantool://host.docker.internal:3301/?size=4&user=admin&password=secret-cluster-cookiedelete.enabled: trueprimary.key.mode: record_keyinsert.mode: replacedatetime:handling.mode: datetimeinfinity.handling.enabled: truetransforms:chain:- topic-from-source-table- topic-from-source-space-nameconfig:topic-from-source-table:type: io.tarantool.cdc.transforms.smt.ExtractTopic$Valuefield.path: source.tableskip.missing.or.null: truetopic-from-source-space-name:type: io.tarantool.cdc.transforms.smt.ExtractTopic$Valuefield.path: source.space_nameskip.missing.or.null: trueglobal:imagePullPolicy: "Never"image:repository: docker.io/tarantool-cdc/cdc-worker-alltag: 0.12.0.pullPolicy: "Never"startupProbe:failureThreshold: 40offset:storage:type: filefile.name: "/data/offsets.dat"persistence:enabled: truestorageClassName: "standard"storageSize: 1GimountPath: "/data"flow:- source: postgresqlsink: tarantool-dbresources:requests:cpu: 1500mmemory: 1Gilimits:cpu: 2memory: 3Gienv:JAVA_OPTS: -XX:MaxDirectMemorySize=256MEOFВнимание! При прохождении примера на macOS рекомендуется перейти в рабочую директорию и выполнить команду
find . -name ".DS_Store" -type f -delete. Эта команда удалит скрытые файлы.DS_Store, которые могут автоматически создаваться операционной системой в рабочей директории и ее дочерних директориях. Эти файлы помешают процессу миграции данных в базу данных Tarantool. -
Запустите кластер 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-demob. Убедитесь, что под Обработчика в состоянии
READY 1/1.
c. Убедитесь, что в журнале универсального обработчика отсутствуют ошибки подключения к Источнику и Приемнику (в списке выберите под с именем
cdc-pg-1-0-tdb2-1-0и нажмите клавишу L).
-
Проверьте, что данные о кластере Tarantool CDC появились на панели мониторинга в Grafana (обновите страницу мониторинга в браузере).
Для выхода из интерфейса K9s используйте комбинацию клавиш CTRL+C.
Процесс запуска постоянной нагрузки в текущем примере полностью соответствует процедуре запуска примера с передачей данных при помощи TQE.
Убедитесь, что панель мониторинга в Grafana отображает статистику передачи данных (обновите страницу мониторинга в браузере).

Процесс остановки стенда в текущем примере полностью соответствует процедуре остановки примера с передачей данных при помощи TQE.