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

202 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 начинает принимать
подключения.
3) Затем управление передаётся оригинальному старту Greenplum: `exec /start_gpdb.sh`.
4) 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`
2) Проверить статус PXF (PXF CLI запускается только под пользователем `gpadmin`):
`docker compose exec greenplum bash -lc "su - gpadmin -c '/usr/local/pxf/bin/pxf cluster status'"`
3) После применения 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 уже запущен.