8.9 KiB
PXF для bookings в учебном стенде (актуально)
Этот документ описывает текущую реализацию PXF в проекте: чтение данных из демо‑БД
bookings (Postgres, сервис bookings-db) в Greenplum через JDBC.
1. Что должно работать
- В Greenplum доступны внешние таблицы:
public.ext_bookings_bookings(создаётсяmake ddl-gp);stg.bookings_ext(создаётся DAGbookings_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/(JDBC‑JAR и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
-
Docker запускает контейнер с базовым entrypoint образа и командой
/start_greenplum_with_pxf.sh(она задана вDockerfile.greenplumкакCMD). -
/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 начинает принимать подключения.
-
Затем управление передаётся оригинальному старту Greenplum:
exec /start_gpdb.sh. -
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. Быстрая ручная проверка
- Дождаться
healthyуgreenplum:
docker compose ps
- Проверить статус PXF (PXF CLI запускается только под пользователем
gpadmin):
docker compose exec greenplum bash -lc "su - gpadmin -c '/usr/local/pxf/bin/pxf cluster status'"
- После применения DDL (
make ddl-gp) проверить чтение через PXF:
make gp-psqlSELECT 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+ restartgreenplum+ (при необходимости)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 “уже настроенным” и
пропускает создание расширения.
Отдельно /start_greenplum_with_pxf.sh пытается выполнить CREATE EXTENSION IF NOT EXISTS pxf
в фоне, но это может “не попасть” в окно готовности базы (гонка при старте), поэтому после старта:
- PXF может быть “running” (
pxf cluster status), но protocol pxfв базе ещё не создан.
Как проверить
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'';\"'"
Если команда ничего не вернула — расширение не создано.
Временный workaround (ручной)
-
Создать расширение:
docker compose exec greenplum bash -lc "su - gpadmin -c '/usr/local/greenplum-db/bin/psql -d gp_dwh -c \"CREATE EXTENSION IF NOT EXISTS pxf;\"'" -
Повторить DDL:
make ddl-gp
Что чинить в коде (идея фикса)
Сделать создание расширения pxf независимым от наличия pxf-env.sh:
- либо убрать/изменить условие в
/start_gpdb.sh(в образе), - либо перестать копировать
pxf-env.shв ensure‑скрипте и дать базовому скрипту создать его, - либо сделать retry‑логику
CREATE EXTENSION pxfнадёжной (повторять попытки и проверять результат).
8. Связанные файлы
Dockerfile.greenplumdocker-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: свой образ»)