rzv Data Engineering
Open in Telegram
Авторский канал о том, как я понимаю инжиниринг данных. Объясняю термины, best practice, делюсь описанием рабочих задачек. См закрепы Рассчитан на новичков в DE и инженеров до Senior. Чат: t.me/+jtQ1tjvNUtwzN2My По вопросам: @razvodov_de_mentor
Show more2 995
Subscribers
No data24 hours
-17 days
+2430 days
Posts Archive
2 995
Ловите новости по учебным стендам
🔸 На неделе планирую релиз шардированного Clickhouse 2х2. В нём расскажу про основы переноса таблиц с моно-кластера на шардированный CH с точки зрения дата инженера. Покажу на практике работу шардов и реплик. В нескольких задачах раскрою материализованные представления и проекции. Ну и маленько по витринам пройдёмся. Всё будет на той же платформе "материалы слева - СУБД клиент и UI справа".
На учёную степень по клику или навыки уровня DBA не претендую. Приглашаю ознакомиться тех DE, у кого не было опыта с Clickhouse в принципе или с его кластерной версией)
🔸 Потом скорее всего будет мини-Hadoop с "плановыми поломками" одной дата ноды каждые полчаса. Подумал, что надо устойчивые системы показывать в стрессовых ситуациях) Для тех, кто планирует работать в больших банках или других компаниях с петабайтными хранилищами.
🔸 Понемногу работаю над Streaming / Flink, видел спрос под одним из прошлых постов. Займёт сколько-то времени, пока не обещаю даты. Возможно, замахнусь на сравнение Kafka Streams, Flink, Spark Structure Streaming. Ищу экспертов, чтобы проконсультироваться по паре вопросов, пишите в личку)
🔸 И ещё закинул в бэклог с пяток тем, которые считаю актуальными, и вроде как есть что по ним рассказать:
• "CI/CD для DE" - Концепция CI/CD, рабочие окружения, code & DDL & Data sync
• "Моделирование данных" - Сравнение Inmon, Kimball, Data vault 2.0, One big table
• "Data quality" - Data issue alerts, dbt tests, great expectations, write-audit-publish pattern
• "Change data capture" - Live data + Debezium + Kafka + S3
Пишите в комментах, что ждёте больше всего. Может, чего-то ещё не хватает в бэклоге?
Ну а пока всех жду на стенде по "Lakehouse" :)
2 995
Первый лабораторный стенд уходит в релиз!
https://rzvde.pro/labs
До 24 августа включительно действует цена "бета-теста" в 1900р, затем будет 2500р.
Буду дорабатывать на основе вашего фидбэка и мониторить, как платформа ведёт себя под нагрузкой.
Я за последние пару недель больше 80 часов вложил в "уже почти готовые материалы", инфру и выдачу доступов, поэтому думаю что уже сейчас результат хороший. Но буду на связи :)
Надеюсь, что материалы и практика смогут соответствовать ожиданиям и помогут разобраться в актуальных вам темах)
Продуктивной учёбы!
2 995
В какие темы и технологии было бы интересно погрузиться с практикой? Пиши в комментариях, буду выбирать популярные идеи и формировать бэклог)
2 995
В общем, по поводу розыгрыша билета на конференцию и обсуждения под удалённым постом с рекламой:
Нечасто провожу эти розыгрыши, и досадно что именно в этот раз довольно крупно накосячил со своей стороны.
Как было по порядку:
• В комментариях в конкурсе приняли участие два человека - Даниил и Сергей.
• Я провёл розыгрыш, в котором победителем рандом выбрал Сергея, написал ему об этом под постом - но потом обнаружил, что не поставил OBS на запись.
• Подумал, что доказательство всё-таки нужно, записал ещё один раз, где рандом выбрал Даниила.
• Написал Даниилу об этом, и решил подчистить прошлое сообщение, где победитель - Сергей.
• Сергей указал мне на эту несправедливость в комментах, и потом я пытался объясниться, но услышать друг друга не получилось.
• Даниил пошёл навстречу и отказался от своего билета, чтобы в итоге он достался Сергею.
Я написал организатору конференции, в понедельник будем договариваться на то, чтобы по билету досталось обоим участникам.
Признаю, что поступил очень по-детски, поленившись пару раз крутануть барабан и заново сделать записи, чтобы первоначальный победитель был запечатлён на видео.
Сергей честно победил в этом случайном отборе в первый раз. И приз был достаточно серьёзный, стоило подготовиться лучше.
Или стоило хотя бы объяснить ситуацию на том же видео, и "покрутить этот барабан" на записи, пока снова не покажется Сергей.
Решил "сэкономить" пару минут, в итоге потратил час времени, нервы людей, и теперь напрягаю людей договариваться о новом билете.
Я косяк. Не делайте так)
Приношу извинения за неразбериху и потрёпанные нервы
p.s. Релиз mini-Lakehouse Lab откладывается до понедельника
2 995
+4
Заканчиваю полировать, завтра с утра можно будет пробовать)
За эту неделю получилось вылечить многие баги и несостыковки, добавить полезные фичи, улучшить Quality of Life, значительно расширить покрытие лабы. Но наверняка что-то ещё осталось из проблем, будем тестировать вместе) Поэтому цена до 22.08 сохраняется, потом подниму до 2500р. А стоит оно того или нет - решать вам.
Описание стенда "мини-Lakehouse" и ещё несколько скриншотов:
В этом материале описана концепция Lakehouse, показаны многие возможности Iceberg, проведено сравнение с DWH на базе Greenplum. Вы загрузите и обработаете сырые данные на 10 миллионов строк, создадите таблицы Silver слоя и витрины Gold слоя. Стенд содержит нужную теорию для выполнения практики. Работа с реальной инфраструктурой ведётся через SQL запросы и Linux terminal, Trino UI и MinIO web console. Также есть шаги: - создание S3 бакета в MinIO - настройка Trino каталога для загрузки в этот бакет Содержание: 1. Введение 2. Подключение и разведка 3. Концепции: Trino, Iceberg, Lakehouse 4. Сырые данные — слой Hive 5. Управляемый слой — Iceberg 6. Time travel 7. Schema evolution 8. Partition evolution 9. Row-level операции и MERGE 10. Метаданные Iceberg 11. Обслуживание 12. Витрины (marts) 13. Аналитика 14. Очистка Доступ выдаётся на 30 дней. Материалы можно сохранить в PDF.
2 995
Как записи конференций помогли мне быстрее стать сеньором
Читай пост до конца — участвуй в розыгрыше билета на онлайн-участие в конференции SmartData2026!
🔸Мне нравится формат видео-эссе и докладов по играм и кино, поэтому года три назад я решил поискать что-то по своей профессии на youtube. Решил пройтись по Clickhouse, так как технология была на слуху, и всё чаще появлялась в вакансиях и на проектах. Наткнулся на записи SmartData, в которых большинство докладов как раз по теме Data engineering - и понеслось)
Дальше я просто включал записи фоном, как подкасты. Пока делаешь какие-то задачи по быту, едешь по городу или просто выполняешь рутинные задачи на работе.
🔸 Вначале я не особо заметил пользу, ну слушал и слушал. Но потом это очень помогло на технических собеседованиях. Когда заходил разговор о сложной задаче, я вспоминал историю из доклада и приводил её как пример. Взять то же масштабирование связки кластеров Kafka & Clickhouse. Срабатывало это двумя путями:
• Иногда собеседующий узнавал выступление, и между нами возникало ощущение общего контекста. И тогда мы могли уйти в обсуждение выступления или того, что ещё вместе смотрели. Так быстрее выстраивался более теплый коннект с потенциальным руководителем.
• Иногда упоминания каких-то деталей было достаточно для подтверждения, что в теме я разобрался достаточно глубоко. Чужие достижения при этом присваивать не обязательно, достаточно было сказать, что я знаю про такую особенность и понимаю механизм.
И вот уже осенью 2023 я впервые устроился в роли Senior DE :)
🔸Сами доклады дали мне конкретику, которую тяжело собрать по обрывкам статей. Например, вот доклады которые мне запомнились:
• об особенностях (не)идемпотентной записи в разные движки таблиц, откуда может взяться перекос данных по шардам и партициям
• о внутренней работе разреженных индексов и вставке в MergeTree
• о том, как на Clickhouse строили DWH, и с какими проблемами столкнулись
🔸С теплотой рекомендую посетить конференцию SmartData в этом году всем заинтересованным. Также у подписчиков моего канала есть уникальная возможность приобрести билет со скидкой 15% по промокоду:
RzvDe
❕Пришли в комментарии свою историю, когда доклады конференций помогли тебе на собеседованиях или в работе.
Случайным образом выберу победителя и подарю билет на онлайн-участие 23–24 сентября
Реклама. ООО «Джуг Ру Груп». ИНН 7801341446
2 995
Опыт миграции небольшого стека с Docker compose на Kubernetes 4/4
🔸 Что это даёт, по крайней мере для меня
Прежде всего - интеграцию с готовой платформой для "прогерских лабораторных работ", где k8s-манифесты это пререквизит
Возможность горизонтального масштабирования за пределы одной ВМ на будущее
Более удобный способ из одного контейнера управлять состоянием другого, например для сервиса выдачи доступов (в docker-compose стеке есть
bind-mount /var/run/docker.sock, но идёт вместе с уязвимостью в виде root права на запуск любых контейнеров)
🔸Выводы
Для собственных проектов пока всё ещё не вижу смысла в k8s, как ни пытаюсь разглядеть. Всё в конечном итоге запускается на виртуальных машинах, за которые платишь. Даже в managed сервисе вроде "yandex cloud managed k8s" идёт отдельная аренда за месяц CPU/RAM/disk конкретных ВМ.
Пока продолжаю всей душой любить Docker compose.
Поделитесь в комментах, если есть удачный опыт переноса проектов на кубер, кроме случаев когда это кластеры на десятки ВМ. Я с интересом почитаю)2 995
Опыт миграции небольшого стека с Docker compose на Kubernetes 3/4
Отдельно — Ingress:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: trino
spec:
rules:
- host: trino.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: trino
port:
number: 8080
И отдельно — 2 ConfigMap вместо папки ./trino/etc:
apiVersion: v1
kind: ConfigMap
metadata:
name: trino-etc
data:
config.properties: |
coordinator=true
node-scheduler.include-coordinator=true
http-server.http.port=8080
discovery.uri=http://localhost:8080
jvm.config: |
-server
-Xmx2G
-XX:+ExitOnOutOfMemoryError
node.properties: |
node.environment=lab
node.id=trino-lab-1
...
Итого на стороне k8s: 6 объектов (Deployment, Secret, Service, Ingress, 2 ConfigMap), около 230 строк.
150 против 230, 2+7 файлов с описанием инфры против 6 объектов. В k8s нужно больше конфигурации на тот же набор параметров, потому что в k8s эти параметры обязательны и оформлены отдельными объектами. В Docker compose они описываются опциональными полями внутри одного сервиса.2 995
Опыт миграции небольшого стека с Docker compose на Kubernetes 2/4
Что стало на k8s
🔸 Во-первых, сколько абстракций добавилось:
- Deployment — чтобы кластер сам следил за нужным состоянием пода
- Secret — API-объект с RBAC-управлением доступами на чтение и живой ротацией без передеплоя
- Service — чтобы у пода был стабильный сетевой адрес: свой внутренний IP он теряет при каждом пересоздании
- Ingress — чтобы к сервису можно было подключиться снаружи; по умолчанию кластер находится в полностью изолированном окружении "без окон и дверей"
- ConfigMap — набор key-value пар параметров
🔸 Во-вторых, какие строчки конфига во что превратились:
- image / container_name -> Deployment, containers[].image — без изменений
- depends_on -> нативного аналога нет, приходится писать небольшой initContainer, который сам проверяет, что сервис-зависимость запущен и можно стартовать текущий
- сеть по имени контейнера -> Service — обязательный отдельный объект, потому что у пода нет постоянного IP; адресация теперь по label-селектору, т.к. подов по умолчанию больше одного
- открытые ports -> Service.ports + Ingress — тот же объём работы, что раньше делал nginx вне compose, просто
теперь это объект кластера, а не отдельный конфиг на хосте
- restart: healthcheck -> readinessProbe / livenessProbe с тем же смыслом
- environment -> Secret
- лимиты ресурсов железа -> resources.requests/limits — выглядит похоже, влияет на выбор планировщика "куда размещать новый под при масштабировании"
- отдельные .config, .properties для Trino -> универсальные ConfigMap key-value файлы
Для запуска использую облегчённую версию k3s на одной ВМ.
Deployment:
apiVersion: apps/v1 kind: Deployment metadata: name: trino spec: replicas: 1 selector: matchLabels: app: trino template: metadata: labels: app: trino spec: initContainers: - name: wait-for-hive-metastore image: busybox:1.36 command: ["sh", "-c", "until nc -z hive-metastore 9083; do sleep 2; done"] containers: - name: trino image: trinodb/trino:483 env: - name: AWS_ACCESS_KEY_ID valueFrom: secretKeyRef: name: minio-credentials key: access-key - name: AWS_SECRET_ACCESS_KEY valueFrom: secretKeyRef: name: minio-credentials key: secret-key ports: - containerPort: 8080 resources: requests: cpu: 250m memory: 2Gi limits: memory: 3Gi readinessProbe: httpGet: path: /v1/info port: 8080 initialDelaySeconds: 15 livenessProbe: tcpSocket: port: 8080 initialDelaySeconds: 30 volumeMounts: - name: trino-etc mountPath: /etc/trino/config.properties subPath: config.properties - name: trino-etc mountPath: /etc/trino/jvm.config subPath: jvm.config - name: trino-catalog mountPath: /etc/trino/catalog/iceberg.properties subPath: iceberg.properties volumes: - name: trino-etc configMap: name: trino-etc - name: trino-catalog configMap: name: trino-catalogОн ссылается на Secret через secretKeyRef, значит нужен и такой объект:
apiVersion: v1 kind: Secret metadata: name: minio-credentials type: Opaque stringData: access-key: <access-key> secret-key: <secret-key>Дальше — Service:
apiVersion: v1
kind: Service
metadata:
name: trino
spec:
selector:
app: trino
ports:
- port: 8080
targetPort: 80802 995
Опыт миграции небольшого стека с Docker compose на Kubernetes 1/4
В посте попробую разобраться, в чём k8s может быть лучше чем Docker compose для инфры небольшого проекта. Пост больше по DataOps, но вам вроде такое иногда заходит. Вначале отладил сервис и "лабу" для своих менти на привычном окружении, теперь оборачиваю в "коробку" и готовлюсь открывать доступ для многих. Заодно решил потренироваться в переносе сервиса на kubernetes. Это те же контейнеры, должно быть несложно, правда?)
🔸 Было
Вот весь блок
trino: из compose, как есть:
trino:
image: trinodb/trino:483
container_name: trino
restart: unless-stopped
volumes:
- ./trino/etc:/etc/trino:ro
ports:
- "8085:8080"
environment:
AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID:-}
AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY:-}
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/v1/info"]
interval: 15s
timeout: 5s
retries: 3
start_period: 30s
deploy:
resources:
limits:
memory: 3g
reservations:
cpus: "0.25"
memory: 2g
depends_on:
hive-metastore:
condition: service_healthy
networks:
- trino-network
- main
А чтобы к нему можно было подключиться снаружи по доменному имени и по HTTPS — добавляем nginx на хосте, вне этого docker-compose.yml:
server { listen 80; server_name trino.example.com; location /.well-known/acme-challenge/ { root /var/www/certbot; } location / { return 301 https://$host$request_uri; } } server { listen 443 ssl; server_name trino.example.com; ssl_certificate /etc/letsencrypt/live/trino.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/trino.example.com/privkey.pem; location / { set $upstream_trino trino:8080; proxy_pass http://$upstream_trino; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }Итого: - docker compose: 30 строк - /trino/etc конфиги: 91 строка, 7 файлов формата .config и .properties (по 1 под каждый из 3х каталогов + 4 общих на кластер) - nginx: 29 строк
2 995
+1
Анонс новых учебных стендов по DE
Я стремлюсь найти такие способы обучения технологиям, которые помогают разобраться и понять материал.
Сейчас работаю над интерактивными стендами в стиле kodekloud, но для дата инженеров. Это такие лабы на 3-5 часов, где можно знакомиться с технологиями через практику.
Пользователь на платформе сможет создавать конфиги, запускать команды в терминале, обращаться к СУБД через SQL клиент, заходить на UI сервисов и тд. Опыт приближен к техническому взаимодействию с системой, как это бывает на работе.
Планирую в августе зарелизить первый стенд по Lakehouse: Trino + Iceberg + S3 - ждите новостей)
Закладываю опыт работы в американском стартапе, где ещё в 2024 удалось поработать с Lakehouse
2 995
Вопрос на подумать-порассуждать.
Что делать, если меняется первичный ключ?
Например, ты строишь CRM систему на основе телеграмма. И в качестве колонки, которая "однозначно определяет аккаунт", выбираешь телеграм никнейм. Запускаешь систему в прод, всё хорошо работает какое-то время.
А потом ты узнаёшь, что некоторые клиенты поменяли свой телеграм никнейм. То есть теперь есть две разных строчки, которые на самом деле один клиент.
2 995
Как BI-аналитики воспринимают оптимизацию таблиц в СУБД под тяжёлые запросы
https://rzvde.pro/clickhouse_query_optimization_demo
и такой пересчёт происходит при каждом обращении к СУБД, например Clickhouse:
• выбор другого отчётного периода
• фильтрация по конкретным значением
• изменение полей агрегации
(симуляция, реальная база не пострадала)
2 995
Почему AI-агенты ошибаются, даже если у них есть доступ ко всем данным? 🤖
Многие компании уже экспериментируют с AI-агентами для поиска информации, аналитики и работы с корпоративными знаниями. Однако на практике доступ к данным еще не гарантирует качественный результат.
Причина часто кроется не в самой модели, а в архитектуре данных: отсутствует семантический слой, бизнес-логика не формализована, а данные не готовы к работе с ИИ.
📆 23 июня в 11:00 мск компания Lasmart приглашает на бесплатный вебинар «Почему 90% данных не готовы к работе с ИИ: архитектурный фундамент AI-агентов».
👨💻 Спикер: Павел Хамрин — руководитель AI-направления Lasmart. Более 10 лет занимается внедрением аналитических решений, DWH и BI-систем, развивает практики применения AI в аналитике и работе с данными.
В программе вебинара:
— почему прямого доступа к данным недостаточно для AI-агентов;
— откуда берутся «галлюцинации» при работе с корпоративными данными;
— зачем нужен семантический слой;
— какие компоненты включает AI-Ready архитектура;
— как подготовить DWH, BI и корпоративные данные к работе с ИИ;
— практическая дорожная карта внедрения и масштабирования AI-агентов.
Вебинар будет полезен CTO, CIO, CDO, руководителям AI-проектов, Head of BI, Head of Analytics, архитекторам данных и специалистам, отвечающим за развитие корпоративной аналитики.
🎁 Бонус участникам — персональный разбор стека данных и рекомендации по подготовке архитектуры для запуска AI-агентов.
🔗 Регистрация по ссылке
2 995
Дата инженерный опыт работы с кубером 3/3
🔸 Выбор Executor под задачу
Появляется выбор между CeleryExecutor и KubernetesExecutor. CeleryExecutor держит постоянный пул воркеров, которые ждут работу из очереди через брокер вроде Redis. Воркеры всегда “прогреты”, поэтому задача стартует почти сразу, и это выгодно при большом числе коротких частых операций. Плата за такой режим в том, что воркеры занимают ресурсы даже в простое.
KubernetesExecutor поднимает отдельный под под каждую задачу и удаляет его после завершения. Старт такого пода занимает секунд 40, поскольку нужно подтянуть образ и дождаться планировщика, и полезная работа начинает выполняться далеко не сразу. Зато задача получает изоляцию, возможность занять ограниченные ресурсы под тяжёлую операцию и высвободить по выполнении.
p.s. существует комбинированный CeleryKubernetesExecutor, который распределяет задачи по очередям. А на уровне тасок выбирается тип оператора KubernetesPodOperator для k8s / любой другой для Celery. Или можно указать в любом task через параметр
executor.
🔸 Упаковка python-кода в образ
В кубере единицей запуска служит контейнерный образ, поэтому python-скрипт обработки данных сначала превращают в образ через Dockerfile. В этом файле наследуют базовый образ через FROM, нужные библиотеки и сам код, дальше образ собирают, отправляют в реестр (н. gitlab container registry) и ссылаются на него из задачи, например через KubernetesPodOperator.
Вместо установки пакетов на общие воркеры, теперь инженер описывает окружение в Dockerfile и обновляет образ. Такой подход даёт все плюсы использования Docker контейнеров вроде изоляции окружения и воспроизведения запусков. Но при этом добавляется работа по обслуживанию всех этих процессов, значительно усложняется CI/CD.2 995
Дата инженерный опыт работы с кубером 2/3
🔸 Где лежат логи и как до них добраться
Под в кубере это атомарная единица деплоя. Под с задачей живёт ровно столько, сколько идёт её отработка, а после завершения исчезает вместе со своей файловой системой и локальными логами. Поэтому логи приходится выносить наружу, чаще всего в S3/MinIO или в систему агрегации логов вроде Loki или ElasticSearch. Логи подтягиваются в интерфейс Airflow из удалённого хранилища, и визуально всё работает как обычно. Однако, если нужно обработать логи программно или провести “глобальный поиск”, для этого нужно перейти во внешнюю систему, а не подключаться по ssh к виртуальной машине как раньше.
🔸 Связь кубера с внешним миром через ingress и egress
K8s описывает сети, и без настройки сетей приложение будет существовать “в вакууме”, недоступное для подключения извне и общения с “внешним миром”. Для сегодняшней статьи важны два термина: ingress, входящий трафик, и исходящий egress. А для DE это про подключение к источникам и приёмникам данных.
Чтобы DAG достучался до внешней базы или внешнего API, поду нужен исходящий доступ, а его часто ограничивают сетевые политики типа “запрещено всё, что явно не разрешено”. В этом случае задача падает, и причину стоит искать в закрытом (не настроенном) egress. С обратной стороны, доступ пользователей к веб-интерфейсу Airflow открывают через ресурс Ingress вместе с контроллером, доменом и сертификатом. Ещё одна частая причина сбоев возникает, когда исходящий адрес кластера не добавлен в список разрешённых на стороне источника, и тогда соединение отклоняется ещё до того, как дойдёт до данных. В общем, куча сетевых заморочек)
2 995
Дата инженерный опыт работы с кубером 1/3
Я не буду вам сейчас долго писать про архитектуру или масштабируемость - это всё непонятным языком уже описали до меня. Покажу с точки зрения дата инженера на примере работы с Airflow.
🔸 Kubernetes (k8s, кубер) - это инфраструктурная платформа для развёртывания сервисов и описания их ресурсов через код. То есть где-то в гит репозитории лежит набор файликов, которые обрабатываются кубером и превращаются во всевозможные сервисы, сети, параметры серверных приложений и тд. Например, все компоненты Airflow:
• webserver
• scheduler
• workers
• executor
• trigerrer
• metadata base (postgres)
🔸 Но что это значит для пользователя сервиса, то есть для дата инженера? Разберу четыре темы:
1. расположение логов и доступ к ним
2. ingress/egress - подключение к источникам и таргетам
3. выбор Executor между Celery и Kubernetes для разных задач
4. python скрипты для обработки данных заворачивают в Dockerfile
