Files
airflow-greenplum/docs/internal/pxf_bookings.md
T

12 KiB
Raw Blame History

PXF для bookings в учебном стенде (актуально)

Этот документ описывает текущую реализацию PXF в проекте: чтение данных из демо‑БД bookings (Postgres, сервис bookings-db) в Greenplum через JDBC.

1. Что должно работать

  • В Greenplum доступны внешние таблицы:
    • public.ext_bookings_bookings (создаётся make ddl-gp);
    • stg.bookings_ext (создаётся DAG bookings_stg_ddl).
  • PXF должен быть готов после каждого старта контейнера greenplum.

2. Почему мы делаем свой образ Greenplum

Изначально PXF‑скрипты/конфиги монтировались в контейнер как bind‑mount :ro. Базовый entrypoint образа Greenplum пытается делать chown файлов в /docker-entrypoint-initdb.d/, из‑за чего контейнер иногда падал с ошибкой:

chown: changing ownership ... Read-only file system

Снять :ro тоже нежелательно — можно получить проблемы с правами на файлах хоста (файл становится root, IDE перестаёт сохранять, появляются лишние изменения в git).

Решение для учебного стенда:

  • собрать свой образ Greenplum (Dockerfile.greenplum);
  • «вшить» в образ seed‑файлы и скрипты PXF;
  • на каждом старте контейнера идемпотентно докладывать файлы в PXF_BASE, который живёт на persistent volume.

3. Где что хранится

Внутри образа (immutable):

  • seed для PXF: /opt/pxf-seed/ (JDBCJAR и servers/bookings-db/jdbc-site.xml);
  • скрипты:
    • /opt/pxf-scripts/ensure_pxf_bookings.sh (подготовка PXF_BASE);
    • /start_greenplum_with_pxf.sh (startup wrapper).

На persistent volume (переживает рестарты):

  • PXF_BASE по умолчанию: ${GREENPLUM_DATA_DIRECTORY}/pxf → в нашем compose это /data/pxf на томе greenplum_data.

Важно: так как PXF_BASE лежит на томе, обновления seed‑файлов из нового образа не перезатирают файлы в PXF_BASE автоматически (это сделано намеренно, чтобы не ломать ручные правки студентов).

4. Что происходит при старте контейнера greenplum

  1. Docker запускает контейнер с базовым entrypoint образа и командой /start_greenplum_with_pxf.sh (она задана в Dockerfile.greenplum как CMD).

  2. /start_greenplum_with_pxf.sh выполняет подготовку PXF:

  • запускает ensure‑скрипт /opt/pxf-scripts/ensure_pxf_bookings.sh;
  • параллельно пытается выполнить CREATE EXTENSION IF NOT EXISTS pxf в базе ${GP_DB} (по умолчанию gp_dwh), когда Greenplum начинает принимать подключения.
  1. Затем управление передаётся оригинальному старту Greenplum: exec /start_gpdb.sh.

  2. Healthcheck сервиса greenplum ждёт и готовность Greenplum, и то, что PXF уже запущен (pxf cluster status). Это нужно, чтобы Airflow не стартовал раньше PXF.

5. Управляющие переменные окружения

Все переменные можно задать в .env (см. .env.example):

  • PXF_SEED_OVERWRITE=1 — принудительно перезаписать seed‑файлы из образа в PXF_BASE (обычно нужно после правок в каталоге pxf/).
  • PXF_SYNC_ON_START=1 — выполнять pxf cluster sync при старте контейнера (делает старт чуть дольше, но гарантирует актуальные конфиги на хостах кластера).

6. Быстрая ручная проверка

  1. Дождаться healthy у greenplum:

docker compose ps

  1. Проверить статус PXF (PXF CLI запускается только под пользователем gpadmin):

docker compose exec greenplum bash -lc "su - gpadmin -c '/usr/local/pxf/bin/pxf cluster status'"

  1. После применения DDL (make ddl-gp) проверить чтение через PXF:
  • make gp-psql
  • SELECT COUNT(*) FROM public.ext_bookings_bookings;

7. Типовые ошибки

  • protocol "pxf" does not exist
    • причина: не создано расширение pxf в базе Greenplum;
    • решение: перезапустить greenplum (скрипт сделает CREATE EXTENSION IF NOT EXISTS pxf) или выполнить вручную CREATE EXTENSION pxf;.
  • Connection refused к порту 5888
    • причина: PXF не поднялся/не успел подняться;
    • решение: проверить pxf cluster status, посмотреть логи PXF в /data/pxf/logs, перезапустить сервис greenplum.
  • PXF «не подхватывает» изменения конфигов
    • причина: файлы уже лежат в PXF_BASE на томе, а seed из образа по умолчанию не перетирает их;
    • решение: make build + restart greenplum + (при необходимости) PXF_SEED_OVERWRITE=1.

9. Известная проблема: protocol "pxf" does not exist на «холодном старте» (исправлено)

Раньше (воспроизводилось в ./scripts/e2e_smoke.sh) при первом make ddl-gp можно было получить:

ERROR: protocol "pxf" does not exist

Почему так происходило

В базовом /start_gpdb.sh из образа Greenplum создание расширения pxf связано с проверкой файла ${PXF_BASE}/conf/pxf-env.sh:

  • если pxf-env.sh отсутствует, скрипт выполняет pxf cluster prepare/register и затем CREATE EXTENSION IF NOT EXISTS pxf;
  • если pxf-env.sh уже существует, этот блок пропускается, и расширение может не появиться.

При этом наш ensure‑скрипт pxf/init/10_pxf_bookings.sh копировал pxf-env.sh в ${PXF_BASE} ещё до запуска Greenplum, из‑за чего базовый скрипт считал PXF “уже настроенным” и пропускал создание расширения.

Что изменили

  • создание extension pxf вынесено в start_greenplum_with_pxf.sh и обёрнуто ретраями;
  • pxf-env.sh по‑прежнему копируется в PXF_BASE, чтобы /start_gpdb.sh не пытался выполнять pxf cluster prepare на непустом PXF_BASE;
  • healthcheck greenplum ждёт не только PXF, но и наличие extension pxf.
  • добавлен экспорт PGPASSWORD для pxf cluster start, чтобы docker compose stop/start не ломал запуск из‑за password authentication failed для gpadmin.

Если ошибка всё ещё возникает

  1. Пересоберите образ и перезапустите контейнер greenplum: make build && make down && make up

  2. Проверьте наличие extension: docker compose exec greenplum bash -lc "su - gpadmin -c '/usr/local/greenplum-db/bin/psql -d gp_dwh -t -A -c \"SELECT extname FROM pg_extension WHERE extname = ''pxf'';\"'"

8. Связанные файлы

  • Dockerfile.greenplum
  • docker-compose.yml (сервис greenplum: build, hostname, env, healthcheck)
  • pxf/init/10_pxf_bookings.sh (ensure‑логика)
  • pxf/init/start_greenplum_with_pxf.sh (старт контейнера)
  • README.md (раздел «Greenplum + PXF: свой образ»)

10. Известная проблема: после docker compose stop/start Greenplum может упасть (auth для PXF)

Симптом

После docker compose stop, затем docker compose start контейнер greenplum иногда уходит в Exited (1). В логах видно, что GPDB поднялся, но упал на старте PXF:

  • INFO - pxf cluster start
  • ERROR: Could not connect to GPDB
  • FATAL: password authentication failed for user "gpadmin"

Текущее понимание причины (почему это “иногда”)

  1. При старте GPDB образ woblerr/greenplum генерирует/дописывает pg_hba.conf на persistent volume.
  2. В pg_hba.conf присутствует trust‑правило для конкретного IP контейнера в docker‑сети (пример из диагностики: host all gpadmin 172.21.0.2/32 trust).
  3. После docker compose stop/start Docker может выдать контейнеру другой IP (например, 172.21.0.3). Тогда trust‑правило больше не подходит, и подключение начинает идти по md5.
  4. pxf cluster start подключается к GPDB по TCP на host=gpdbsne (hostname контейнера), то есть попадает именно в pg_hba.conf (а не в localauth).
  5. В результате при “не совпавшем IP” получаем md5 + пароль (возможно пустой/не тот) → падение на 28P01.

Эта проблема выглядит флапающей, потому что IP после stop/start иногда совпадает с захардкоженным trust‑/32, а иногда нет.

Как подтвердить при следующем воспроизведении

  1. Посмотреть логи greenplum: docker compose logs --tail=200 greenplum

  2. Найти реальный IP клиента в master‑логах GPDB (на томе): Password does not match ... обычно содержит адрес вида 172.21.0.X.

  3. Сравнить его с trust‑строкой в pg_hba.conf на томе: /data/master/gpseg-1/pg_hba.conf

Если IP в ошибке (например, 172.21.0.3) не совпадает с trust‑/32 (например, 172.21.0.2/32) — это почти наверняка корень падения.

Что с этим делать дальше (варианты решения, без реализации здесь)

Основная цель — убрать зависимость от “случайного IP после stop/start”:

  • заставить pxf cluster start подключаться к GPDB через 127.0.0.1 (тогда работает существующий trust на localhost);
  • или перестать добавлять в pg_hba.conf trust на конкретный 172.21.0.2/32 и заменить на более стабильное правило (например, на подсеть docker‑сети или на samehost);
  • или закрепить IP контейнера в compose (static IP), чтобы он не “плавал”;
  • или отказаться от stop/start в пользу сценария, который не меняет сетевое окружение (но это хуже для UX студентов).

Что реализовано

  • В pxf/init/start_greenplum_with_pxf.sh добавлен шаг, который на каждом старте обеспечивает в pg_hba.conf trust‑правило host all gpadmin samehost trust (вставка перед host all all 0.0.0.0/0 md5), и делает pg_ctl reload, если GPDB уже запущен.