en
Feedback
rzv Data Engineering

rzv Data Engineering

Open in Telegram

Авторский канал о том, как я понимаю инжиниринг данных. Объясняю термины, best practice, делюсь описанием рабочих задачек. См закрепы Рассчитан на новичков в DE и инженеров до Senior. Чат: t.me/+jtQ1tjvNUtwzN2My По вопросам: @razvodov_de_mentor

Show more
2 995
Subscribers
No data24 hours
-17 days
+2430 days
Posts Archive
Ловите новости по учебным стендам 🔸 На неделе планирую релиз шардированного Clickhouse 2х2. В нём расскажу про основы перено
+1
Ловите новости по учебным стендам 🔸 На неделе планирую релиз шардированного 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" :)

Первый лабораторный стенд уходит в релиз! https://rzvde.pro/labs До 24 августа включительно действует цена "бета-теста" в 1900р, затем будет 2500р. Буду дорабатывать на основе вашего фидбэка и мониторить, как платформа ведёт себя под нагрузкой. Я за последние пару недель больше 80 часов вложил в "уже почти готовые материалы", инфру и выдачу доступов, поэтому думаю что уже сейчас результат хороший. Но буду на связи :) Надеюсь, что материалы и практика смогут соответствовать ожиданиям и помогут разобраться в актуальных вам темах) Продуктивной учёбы!

В какие темы и технологии было бы интересно погрузиться с практикой? Пиши в комментариях, буду выбирать популярные идеи и формировать бэклог)

В общем, по поводу розыгрыша билета на конференцию и обсуждения под удалённым постом с рекламой: Нечасто провожу эти розыгрыши, и досадно что именно в этот раз довольно крупно накосячил со своей стороны. Как было по порядку: • В комментариях в конкурсе приняли участие два человека - Даниил и Сергей. • Я провёл розыгрыш, в котором победителем рандом выбрал Сергея, написал ему об этом под постом - но потом обнаружил, что не поставил OBS на запись. • Подумал, что доказательство всё-таки нужно, записал ещё один раз, где рандом выбрал Даниила. • Написал Даниилу об этом, и решил подчистить прошлое сообщение, где победитель - Сергей. • Сергей указал мне на эту несправедливость в комментах, и потом я пытался объясниться, но услышать друг друга не получилось. • Даниил пошёл навстречу и отказался от своего билета, чтобы в итоге он достался Сергею. Я написал организатору конференции, в понедельник будем договариваться на то, чтобы по билету досталось обоим участникам. Признаю, что поступил очень по-детски, поленившись пару раз крутануть барабан и заново сделать записи, чтобы первоначальный победитель был запечатлён на видео. Сергей честно победил в этом случайном отборе в первый раз. И приз был достаточно серьёзный, стоило подготовиться лучше. Или стоило хотя бы объяснить ситуацию на том же видео, и "покрутить этот барабан" на записи, пока снова не покажется Сергей. Решил "сэкономить" пару минут, в итоге потратил час времени, нервы людей, и теперь напрягаю людей договариваться о новом билете. Я косяк. Не делайте так) Приношу извинения за неразбериху и потрёпанные нервы p.s. Релиз mini-Lakehouse Lab откладывается до понедельника

Заканчиваю полировать, завтра с утра можно будет пробовать) За эту неделю получилось вылечить многие баги и несостыковки, доб
+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.

Как записи конференций помогли мне быстрее стать сеньором Читай пост до конца — участвуй в розыгрыше билета на онлайн-участие
+1
Как записи конференций помогли мне быстрее стать сеньором Читай пост до конца — участвуй в розыгрыше билета на онлайн-участие в конференции SmartData2026! 🔸Мне нравится формат видео-эссе и докладов по играм и кино, поэтому года три назад я решил поискать что-то по своей профессии на youtube. Решил пройтись по Clickhouse, так как технология была на слуху, и всё чаще появлялась в вакансиях и на проектах. Наткнулся на записи SmartData, в которых большинство докладов как раз по теме Data engineering - и понеслось) Дальше я просто включал записи фоном, как подкасты. Пока делаешь какие-то задачи по быту, едешь по городу или просто выполняешь рутинные задачи на работе. 🔸 Вначале я не особо заметил пользу, ну слушал и слушал. Но потом это очень помогло на технических собеседованиях. Когда заходил разговор о сложной задаче, я вспоминал историю из доклада и приводил её как пример. Взять то же масштабирование связки кластеров Kafka & Clickhouse. Срабатывало это двумя путями: • Иногда собеседующий узнавал выступление, и между нами возникало ощущение общего контекста. И тогда мы могли уйти в обсуждение выступления или того, что ещё вместе смотрели. Так быстрее выстраивался более теплый коннект с потенциальным руководителем. • Иногда упоминания каких-то деталей было достаточно для подтверждения, что в теме я разобрался достаточно глубоко. Чужие достижения при этом присваивать не обязательно, достаточно было сказать, что я знаю про такую особенность и понимаю механизм. И вот уже осенью 2023 я впервые устроился в роли Senior DE :) 🔸Сами доклады дали мне конкретику, которую тяжело собрать по обрывкам статей. Например, вот доклады которые мне запомнились: • об особенностях (не)идемпотентной записи в разные движки таблиц, откуда может взяться перекос данных по шардам и партициямо внутренней работе разреженных индексов и вставке в MergeTreeо том, как на Clickhouse строили DWH, и с какими проблемами столкнулись 🔸С теплотой рекомендую посетить конференцию SmartData в этом году всем заинтересованным. Также у подписчиков моего канала есть уникальная возможность приобрести билет со скидкой 15% по промокоду: RzvDe ❕Пришли в комментарии свою историю, когда доклады конференций помогли тебе на собеседованиях или в работе. Случайным образом выберу победителя и подарю билет на онлайн-участие 23–24 сентября Реклама. ООО «Джуг Ру Груп». ИНН 7801341446

Опыт миграции небольшого стека с 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. Поделитесь в комментах, если есть удачный опыт переноса проектов на кубер, кроме случаев когда это кластеры на десятки ВМ. Я с интересом почитаю)

Опыт миграции небольшого стека с 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 они описываются опциональными полями внутри одного сервиса.

Опыт миграции небольшого стека с 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: 8080

Опыт миграции небольшого стека с 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 строк

photo content

Анонс новых учебных стендов по DE Я стремлюсь найти такие способы обучения технологиям, которые помогают разобраться и понять
+1
Анонс новых учебных стендов по DE Я стремлюсь найти такие способы обучения технологиям, которые помогают разобраться и понять материал. Сейчас работаю над интерактивными стендами в стиле kodekloud, но для дата инженеров. Это такие лабы на 3-5 часов, где можно знакомиться с технологиями через практику. Пользователь на платформе сможет создавать конфиги, запускать команды в терминале, обращаться к СУБД через SQL клиент, заходить на UI сервисов и тд. Опыт приближен к техническому взаимодействию с системой, как это бывает на работе. Планирую в августе зарелизить первый стенд по Lakehouse: Trino + Iceberg + S3 - ждите новостей) Закладываю опыт работы в американском стартапе, где ещё в 2024 удалось поработать с Lakehouse

Вопрос на подумать-порассуждать. Что делать, если меняется первичный ключ? Например, ты строишь CRM систему на основе телеграмма. И в качестве колонки, которая "однозначно определяет аккаунт", выбираешь телеграм никнейм. Запускаешь систему в прод, всё хорошо работает какое-то время. А потом ты узнаёшь, что некоторые клиенты поменяли свой телеграм никнейм. То есть теперь есть две разных строчки, которые на самом деле один клиент.

sticker.webp0.35 KB

Как BI-аналитики воспринимают оптимизацию таблиц в СУБД под тяжёлые запросы https://rzvde.pro/clickhouse_query_optimization_demo и такой пересчёт происходит при каждом обращении к СУБД, например Clickhouse: • выбор другого отчётного периода • фильтрация по конкретным значением • изменение полей агрегации (симуляция, реальная база не пострадала)

Почему AI-агенты ошибаются, даже если у них есть доступ ко всем данным? 🤖 Многие компании уже экспериментируют с AI-агентами
Почему 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-агентов. 🔗 Регистрация по ссылке

Дата инженерный опыт работы с кубером 3/3 🔸 Выбор Executor под задачу Появляется выбор между CeleryExecutor и KubernetesExec
Дата инженерный опыт работы с кубером 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/3 🔸 Где лежат логи и как до них добраться Под в кубере это атомарная единица деплоя.
Дата инженерный опыт работы с кубером 2/3 🔸 Где лежат логи и как до них добраться Под в кубере это атомарная единица деплоя. Под с задачей живёт ровно столько, сколько идёт её отработка, а после завершения исчезает вместе со своей файловой системой и локальными логами. Поэтому логи приходится выносить наружу, чаще всего в S3/MinIO или в систему агрегации логов вроде Loki или ElasticSearch. Логи подтягиваются в интерфейс Airflow из удалённого хранилища, и визуально всё работает как обычно. Однако, если нужно обработать логи программно или провести “глобальный поиск”, для этого нужно перейти во внешнюю систему, а не подключаться по ssh к виртуальной машине как раньше. 🔸 Связь кубера с внешним миром через ingress и egress K8s описывает сети, и без настройки сетей приложение будет существовать “в вакууме”, недоступное для подключения извне и общения с “внешним миром”. Для сегодняшней статьи важны два термина: ingress, входящий трафик, и исходящий egress. А для DE это про подключение к источникам и приёмникам данных. Чтобы DAG достучался до внешней базы или внешнего API, поду нужен исходящий доступ, а его часто ограничивают сетевые политики типа “запрещено всё, что явно не разрешено”. В этом случае задача падает, и причину стоит искать в закрытом (не настроенном) egress. С обратной стороны, доступ пользователей к веб-интерфейсу Airflow открывают через ресурс Ingress вместе с контроллером, доменом и сертификатом. Ещё одна частая причина сбоев возникает, когда исходящий адрес кластера не добавлен в список разрешённых на стороне источника, и тогда соединение отклоняется ещё до того, как дойдёт до данных. В общем, куча сетевых заморочек)

Дата инженерный опыт работы с кубером 1/3 Я не буду вам сейчас долго писать про архитектуру или масштабируемость - это всё не
Дата инженерный опыт работы с кубером 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