Learning Platform
Глоссарий Troubleshooting
Урок 21.01 · 18 мин
Средний
CapstoneProductionBashsystemdAirflowDE-workflow

Capstone: production maintenance script для Airflow

Поздравляю — ты добрался до финального проекта курса. В предыдущих 18 модулях ты освоил Linux от первого ls до production-grade bash с set/trap/getopts/shellcheck/tmux/jq. Теперь — собрать всё вместе на реальной DE-задаче, какая встречается в первую неделю работы.

В этом capstone — четыре урока: обзор задачи и сценария (этот), архитектура скрипта (02), implementation walkthrough (03), и деплой через systemd (04). В сопровождающей лабе LAB-04 — пошаговый туториал, mock environment, reference solution и verify.sh для самопроверки.


Сценарий: Day-1 на новой работе

Ты вышел на работу как Junior Data Engineer. Понедельник, утро. Tech lead Alice пишет в Slack:

Hey, добро пожаловать! Первый ticket: AIRFLOW-1247.

Production Airflow worker падает примерно раз в 3 часа — disk full на /var/log/airflow. Каждый DAG run пишет logs (~50 MB), они не чистятся, на server только 500 GB. Через неделю — boom.

Напиши maintenance bash-script, который:

  1. Находит старые log-файлы (старше 7 дней по mtime) в /var/log/airflow/.
  2. Сжимает их через gzip (compression ratio для текстов ~10x — выиграем место).
  3. Опционально (через flag) переносит сжатые в S3-архив s3://acme-airflow-archive/.
  4. Удаляет оригиналы после успешного сжатия / upload.
  5. Шлёт Slack-нотификацию в #airflow-alerts с stats: сколько файлов обработано, сколько MB освобождено.
  6. Запускается daily через systemd timer в 03:00 (минимум traffic).

Production-grade: set -euo pipefail, trap cleanup, logging в journalctl/file, idempotent (можно запустить дважды без harm), --dry-run для preview.

До конца недели. Если что — пинг меня. Тестовое окружение есть в dev-airflow-01, на нём поиграйся сначала.

Это реалистичный ticket. Не игрушечная задача, а то, что регулярно появляется на production. Решение даст production-ready bash-deployment skills, которые junior может сразу применять на работе.


Что мы построим

Архитектура решения

Полный flow от cron-trigger до S3 upload и Slack notification.

systemd timerDaily в 03:00 с RandomizedDelaySec=10m для распределения нагрузки. Persistent=true чтобы catch-up при downtime
service unitoneshot тип, runs cleanup.sh с правильными env vars и user. Логи через journald
cleanup.shbash script с production preamble, getopts, trap, idempotency
find old logsfind /var/log/airflow -mtime +7 -name '*.log' -type f. -print0 + xargs -0 для NULL-terminated safety
gzipgzip -9 для максимального compression. Texts типа logs сжимаются в ~10x. Тестируем атомарность
S3 sync (optional)aws s3 sync для переноса в archive bucket. С --storage-class GLACIER для cost optimization
StatsCount of files, total bytes freed, errors. Структурированный output
Slackcurl POST на incoming webhook. Best-effort (не валим скрипт если Slack недоступен)
journalctlСтруктурированные logs в systemd journal. journalctl -u airflow-log-cleanup -f для tail

Полный workflow:

  1. 03:00 — systemd timer срабатывает.
  2. Запускается service unit, который вызывает /opt/airflow/bin/cleanup.sh.
  3. Скрипт находит файлы старше 7 дней, gzip’ит, опционально кладёт в S3.
  4. Слэк-нотификация с метриками.
  5. Логи всего пути — в journald, видны через journalctl -u airflow-log-cleanup.

Требования к скрипту (acceptance criteria)

Tech lead Alice не сказала это explicitly, но опытный Junior понимает, что production-grade значит:

Robustness

  1. #!/bin/bash shebang + set -euo pipefail + IFS=$'\n\t' preamble.
  2. trap cleanup EXIT для гарантированного cleanup tmpdir/lockfile.
  3. flock или подобный механизм против overlapping runs.
  4. Atomic operations (write-then-rename для output, не partial).
  5. Graceful handling сигналов (SIGTERM от systemd, SIGINT от Ctrl-C).

Observability

  1. Structured logging: timestamp + level + message.
  2. Лог в /var/log/airflow-log-cleanup.log ИЛИ via journald (для systemd).
  3. Slack-нотификация с метриками (success/failure, files processed, bytes freed).
  4. Exit codes имеют смысл: 0 success, 1 generic error, 2 lock held by another instance.

Usability

  1. --help / -h — usage message.
  2. --dry-run / -d — preview без actual changes.
  3. --retention-days N / -r N — настраиваемый retention (default 7).
  4. --log-dir DIR — настраиваемый путь к логам Airflow.
  5. --slack-webhook URL или ENV var SLACK_WEBHOOK.
  6. --s3-bucket BUCKET — опциональный S3 archive.

Maintainability

  1. shellcheck clean (no warnings).
  2. Idempotent: run два раза подряд = единственный effect первого.
  3. Тесты через bats для unit-функций.
  4. Документация в комментариях скрипта или README.md.

Deployment

  1. systemd service unit (oneshot).
  2. systemd timer unit (OnCalendar=daily 03:00, RandomizedDelaySec=10m, Persistent=true).
  3. Установлено в /etc/systemd/system/, enabled через systemctl enable --now.
  4. Verification: systemctl list-timers, journalctl -u ... -f.

DE-skills, которые ты применишь

Этот capstone tests знание из всех модулей:

Skills mapping
M01-04Filesystem navigation, ls/find, операции с файлами. Базис для find -mtime, mv, rm
M05Permissions: chmod 755 для скрипта, корректный user/group в systemd unit
M06-08grep/awk/sed для парсинга логов, pipes/redirection для output контроля
M09Processes/jobs: понимание signals (SIGTERM от systemd), trap-обработка
M11curl для Slack webhook, ssh для verification на remote
M12gzip/tar для compression — core workflow
M13disk/filesystems: проверка disk usage, понимание atomic rename
M14systemd: service unit + timer unit, journalctl, status
M15Cron vs systemd timers — почему timers preferred сейчас
M16-17Bash scripting: getopts, trap, arrays, set -euo pipefail, shellcheck, bats
M18Modern tools: jq для парсинга responses (опционально), tmux для debugging на remote

Что получит junior в результате

После завершения capstone и LAB-04:

  1. Production-ready bash skill — умеешь писать скрипты, которые не падают silent, имеют CLI, тесты, и нормально деплоятся.
  2. Понимание systemd — service + timer, journalctl, status checks.
  3. DE pattern repertoireset -euo pipefail, trap cleanup EXIT, flock, find -mtime, gzip + atomic rename, slack webhook curl.
  4. CI-разрешённый код — shellcheck PASS, bats тесты есть, README.md документирует use.
  5. Что-то в портфолио — реальный production-script с правильной архитектурой. Можно показать на интервью.

Структура capstone

Этот capstone разбит на 4 урока (с lab отдельно):

  • Урок 01 (этот) — обзор, scenario, acceptance criteria.
  • Урок 02 — design: architecture, файл структуры, helper functions, idempotency.
  • Урок 03 — implementation walkthrough: код step-by-step, объяснение каждой строки.
  • Урок 04 — deploy with systemd: service + timer units, enable, verify через journalctl.

LAB-04 — практика: пошаговый туториал на 60-90 минут с mock environment.


Airflow через Docker Compose: контейнерная альтернатива CronJob в Kubernetes: cloud-native scheduled tasks

Что не входит в scope

Чтобы capstone был выполним за разумное время, мы не охватываем:

  • AWS IAM / credentials configuration (предполагается, что у AWS CLI уже есть creds).
  • Slack workspace setup и incoming webhook creation (предполагается, что URL есть).
  • Multi-server orchestration (это Ansible/Terraform — отдельные курсы).
  • High-availability cluster setup для Airflow (zookeeper, postgres replica) — это DevOps.
  • Реальный monitoring stack (Prometheus, Grafana) — продвинутый DE.

Эти темы — следующий уровень. В нашем scope: one server, one cleanup script, one timer.


Перед тем как начать

Окружение

Запасись:

  1. Linux машина (Ubuntu 24.04 или Debian 13) — можно VM, WSL2, или server. На macOS bash 3.2 не подойдёт, нужен bash 4+.

  2. Tools installed:

sudo apt install bash gzip tar findutils coreutils curl jq systemd shellcheck bats
# Опционально для S3:
sudo apt install awscli
  1. Permissions: должен быть sudo (для systemd unit deployment).

  2. Test env: создашь mock /var/log/airflow/ в lab, не нужно реального Airflow.

  3. Slack webhook (опционально для real testing): https://api.slack.com/messaging/webhooks. Без неё используй echo-fallback.

Подход

  1. Не копируй reference solution сразу. Попробуй сам по acceptance criteria. Споткнулся — посмотри урок 02 (design), потом 03 (implementation). Reference только когда застрял.

  2. Используй shellcheck с самого начала — сэкономишь часы дебага.

  3. Test step-by-step. Сначала find — работает. Потом gzip. Потом S3 (с —dry-run). Потом slack. Потом интеграция. Не пиши весь скрипт и потом дебагай.

  4. Test on mock data. Lab даст setup.sh который создаст реалистичную /var/log/airflow/ с старыми и новыми файлами.


  • Урок 02 (design) — следующий: architecture деталь.
  • LAB-04 — labs/LAB-04-capstone-airflow-log-cleanup/README.md.
  • Модуль 17 (advanced bash)set -euo pipefail, trap, getopts.
  • Модуль 14 (systemd) — service units.
  • Модуль 15 (cron) — timers vs cron.

Попробуй сам

  1. Прочитай ticket несколько раз. Запиши на бумаге своё понимание acceptance criteria.

  2. Открой labs/LAB-04-capstone-airflow-log-cleanup/README.md — там детальные шаги.

  3. Запусти labs/LAB-04-.../mock-environment/setup.sh — увидишь, что приготовлено.

  4. Создай файл cleanup.sh и начни с минимума:

#!/bin/bash
set -euo pipefail
IFS=$'\n\t'

LOG_DIR="${1:-/var/log/airflow}"
RETENTION_DAYS=7

find "$LOG_DIR" -name '*.log' -mtime +$RETENTION_DAYS -type f

Запусти. Видишь список старых файлов? Хорошо, дальше — урок 02.

  1. Заплани час каждый день на этой неделе. К пятнице будет рабочий деплой.

Проверка знанийKnowledge check
Tech lead дала тебе ticket: написать maintenance bash-script для cleanup старых логов с deployment через systemd. Опиши порядок шагов: с чего начать, какие требования к production-grade нужно учитывать, и почему 'просто работающий' скрипт не достаточен?
ОтветAnswer
Порядок: 1) **Прочитать acceptance criteria** дважды, выписать на бумаге. 2) **Setup mock environment** для безопасной разработки (не на real production). 3) **Минимальный happy path**: find старые файлы -> gzip -> удалить. Проверить на mock. 4) **Добавить production preamble**: set -euo pipefail; IFS=\$'\n\t'. Без этого silent failures убьют скрипт. 5) **Trap cleanup EXIT**: гарантия что tmpdir/lockfile не leak. 6) **Lock**: flock против overlapping runs (если cron каждый день, а скрипт длится >24ч — конфликт). 7) **CLI**: getopts для --dry-run, --retention-days, --log-dir. Минимум --dry-run для preview перед production. 8) **Idempotency**: запуск дважды = эффект первого. Уже сжатые файлы (.gz) не пробуем сжимать снова. 9) **Logging**: structured timestamp+level+msg в journalctl/file. Без logs дебаг невозможен. 10) **Slack notification**: best-effort (curl с || true), чтобы Slack down не валил скрипт. 11) **shellcheck**: clean — ловит 90% классов багов. 12) **systemd service+timer**: deployment с RandomizedDelaySec, Persistent=true для catchup. Почему 'просто работает' недостаточно: production runs 365 раз в год, и в 1% случаев (3-4 раза) — edge cases (network down, disk full mid-process, signal mid-gzip). Без preamble/trap/atomicity — каждый такой случай = manual intervention, потеря данных, или silent corruption. Production = не "работает в happy path", а "не разваливается в unhappy path".

Проверьте понимание

Результат: 0 из 0
Концептуальный
Вопрос 1 из 5. В чём суть capstone-задачи?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 4