еще баги и документирование сделанного
This commit is contained in:
@@ -409,6 +409,7 @@ load_bookings_to_stg = PostgresOperator(
|
||||
| Проблема | Решение |
|
||||
|----------|---------|
|
||||
| Airflow UI не открывается | Дождитесь сообщения `Listening at: http://0.0.0.0:8080` в логах (`make logs`) |
|
||||
| После `docker compose stop/start` Airflow UI не отвечает, а `airflow-webserver` в `Exited (1)` | Это обычно stale PID-файл Gunicorn (`/opt/airflow/airflow-webserver.pid`). Пересоздайте webserver: `docker compose up -d --force-recreate airflow-webserver` (или просто `make up`). |
|
||||
| Ошибка подключения к Greenplum | Убедитесь, что контейнер `greenplum` стал статусом `healthy` (проверьте `docker compose ps`) |
|
||||
| Не открывается порт 8080/5433/5434/5435 | Проверьте, что эти порты не заняты локальными сервисами; при необходимости остановите их или измените порты в `.env`/`docker-compose.yml` |
|
||||
| Нет файла в `./data` после запуска DAG | Проверьте логи задачи `generate_csv`, убедитесь, что `CSV_DIR` смонтирован в docker-compose |
|
||||
|
||||
+2
-2
@@ -43,8 +43,8 @@
|
||||
- при желании проверить данные: в `bookings-db` появился новый день, а в Greenplum в `stg.bookings` — строки с актуальным `batch_id` (см. пример запросов в разделе 5).
|
||||
|
||||
- (опционально, для менторов/разработчиков) Smoke-тест DAG через Airflow CLI без UI:
|
||||
- `docker compose -f docker-compose.yml exec gp_airflow_webserver airflow dags test bookings_to_gp_stage 2024-01-01` — прогоняет `bookings_to_gp_stage` целиком в «off-line» режиме;
|
||||
- `docker compose -f docker-compose.yml exec gp_airflow_webserver airflow dags trigger bookings_to_gp_stage` — создаёт реальный запуск DAG (логи и статус можно смотреть либо через UI, либо командой `airflow tasks list`/`airflow tasks logs` внутри контейнера).
|
||||
- `docker compose -f docker-compose.yml exec airflow-webserver airflow dags test bookings_to_gp_stage 2024-01-01` — прогоняет `bookings_to_gp_stage` целиком в «off-line» режиме;
|
||||
- `docker compose -f docker-compose.yml exec airflow-webserver airflow dags trigger bookings_to_gp_stage` — создаёт реальный запуск DAG (логи и статус можно смотреть либо через UI, либо командой `airflow tasks list`/`airflow tasks logs` внутри контейнера).
|
||||
|
||||
## 5. Проверка данных в Greenplum
|
||||
- `make gp-psql` — запустить psql в контейнере от имени `gpadmin`.
|
||||
|
||||
+1
-1
@@ -101,7 +101,7 @@ services:
|
||||
env_file: .env
|
||||
environment:
|
||||
<<: *airflow-env
|
||||
command: airflow webserver
|
||||
command: bash -lc "rm -f /opt/airflow/airflow-webserver.pid && exec airflow webserver"
|
||||
ports:
|
||||
- "8080:8080"
|
||||
volumes:
|
||||
|
||||
@@ -193,3 +193,9 @@
|
||||
(например, на подсеть 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 уже запущен.
|
||||
|
||||
@@ -1,14 +1,105 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Этот скрипт — "обёртка" над стандартным стартом Greenplum (exec /start_gpdb.sh),
|
||||
# которая добавляет устойчивый старт PXF для учебного стенда.
|
||||
#
|
||||
# Задачи скрипта (почему он нужен):
|
||||
# 1) Подготовить PXF_BASE на persistent volume (через ensure-скрипт).
|
||||
# 2) Обеспечить стабильную аутентификацию PXF → GPDB после `docker compose stop/start`
|
||||
# (не зависеть от «плавающего» IP контейнера в docker-сети).
|
||||
# 3) Гарантировать наличие расширения `pxf` в БД GPDB (иначе внешние таблицы падают с
|
||||
# `ERROR: protocol "pxf" does not exist`).
|
||||
#
|
||||
# Важно: это учебный стенд, поэтому мы сознательно выбираем простые и надёжные решения
|
||||
# (например, trust для samehost), а не «боевой» hardened security.
|
||||
|
||||
ensure_script="/opt/pxf-scripts/ensure_pxf_bookings.sh"
|
||||
|
||||
# PXF CLI использует libpq, без PGPASSWORD после stop/start возможна ошибка auth.
|
||||
# PXF CLI использует libpq и при `pxf cluster start` подключается к GPDB как к обычному Postgres.
|
||||
# После `docker compose stop/start` может внезапно потребоваться пароль (см. ensure_pg_hba_trust ниже),
|
||||
# поэтому экспортируем PGPASSWORD заранее: это уменьшает "флап" и делает поведение воспроизводимым.
|
||||
if [ -z "${PGPASSWORD:-}" ]; then
|
||||
export PGPASSWORD="${GREENPLUM_PASSWORD:-gpadmin}"
|
||||
fi
|
||||
|
||||
ensure_pg_hba_trust() {
|
||||
# После `docker compose stop/start` Docker может выдать контейнеру другой IP.
|
||||
# У базового образа Greenplum встречается trust-правило на конкретный /32 (старый IP),
|
||||
# и тогда аутентификация по TCP начинает идти через md5 → PXF падает на `28P01`.
|
||||
#
|
||||
# Решение: добавить правило `host all gpadmin samehost trust`, которое срабатывает для
|
||||
# подключений "с этого же контейнера" (PXF запускается рядом с master).
|
||||
# Это максимально простое и стабильное правило для учебного стенда.
|
||||
local gp_user="${GREENPLUM_USER:-gpadmin}"
|
||||
local data_dir="${GREENPLUM_DATA_DIRECTORY:-/data}"
|
||||
local attempts=60
|
||||
local pg_hba=""
|
||||
local trust_line="host all ${gp_user} samehost trust"
|
||||
|
||||
find_pg_hba() {
|
||||
local candidate
|
||||
for candidate in "${data_dir}/master"/*/pg_hba.conf; do
|
||||
if [ -f "${candidate}" ]; then
|
||||
echo "${candidate}"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
for _ in $(seq 1 "${attempts}"); do
|
||||
pg_hba="$(find_pg_hba || true)"
|
||||
if [ -n "${pg_hba}" ]; then
|
||||
break
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
|
||||
if [ -z "${pg_hba}" ]; then
|
||||
echo "WARN - pg_hba.conf не найден, пропускаем trust для ${gp_user}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if grep -Eq "^[[:space:]]*host[[:space:]]+all[[:space:]]+${gp_user}[[:space:]]+samehost[[:space:]]+trust" "${pg_hba}"; then
|
||||
echo "INFO - pg_hba.conf уже содержит trust для ${gp_user} samehost"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Вставляем trust-правило перед самым "общим" md5-правилом (0.0.0.0/0),
|
||||
# чтобы samehost гарантированно матчился раньше.
|
||||
awk -v trust_line="${trust_line}" '
|
||||
BEGIN { added = 0 }
|
||||
$0 ~ /^[[:space:]]*host[[:space:]]+all[[:space:]]+all[[:space:]]+0\.0\.0\.0\/0[[:space:]]+md5/ && added == 0 {
|
||||
print trust_line
|
||||
added = 1
|
||||
}
|
||||
{ print }
|
||||
END {
|
||||
if (added == 0) {
|
||||
print trust_line
|
||||
}
|
||||
}
|
||||
' "${pg_hba}" > "${pg_hba}.tmp" && mv "${pg_hba}.tmp" "${pg_hba}"
|
||||
|
||||
echo "INFO - pg_hba.conf: добавлен trust для ${gp_user} samehost"
|
||||
|
||||
local master_dir="${pg_hba%/pg_hba.conf}"
|
||||
# Если GPDB уже поднялся, достаточно reload, чтобы новое правило применилось без рестарта.
|
||||
if /usr/local/greenplum-db/bin/pg_ctl -D "${master_dir}" status >/dev/null 2>&1; then
|
||||
if ! /usr/local/greenplum-db/bin/pg_ctl -D "${master_dir}" reload >/dev/null 2>&1; then
|
||||
echo "WARN - не удалось перезагрузить pg_hba.conf (pg_ctl reload)"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
ensure_pxf_extension() {
|
||||
# В базовом /start_gpdb.sh создание `CREATE EXTENSION pxf` зависит от наличия
|
||||
# `${PXF_BASE}/conf/pxf-env.sh`. В нашем стенде pxf-env.sh может быть уже создан
|
||||
# ensure-скриптом (PXF_BASE на томе), и тогда /start_gpdb.sh пропускает extension.
|
||||
#
|
||||
# Чтобы внешние таблицы через PXF работали после любого рестарта, создаём extension сами,
|
||||
# но только когда GPDB начнёт принимать подключения (с ретраями).
|
||||
local gp_user="${GREENPLUM_USER:-gpadmin}"
|
||||
local gp_db="${GREENPLUM_DATABASE_NAME:-gp_dwh}"
|
||||
local gp_password="${GREENPLUM_PASSWORD:-gpadmin}"
|
||||
@@ -20,6 +111,7 @@ ensure_pxf_extension() {
|
||||
|
||||
extension_exists() {
|
||||
local result
|
||||
# Подключаемся к localhost: это "локальный" путь и на нём обычно уже есть trust.
|
||||
result=$(PGPASSWORD="${gp_password}" /usr/local/greenplum-db/bin/psql \
|
||||
-h 127.0.0.1 -p 5432 -U "${gp_user}" -d "${gp_db}" \
|
||||
-t -A -c "SELECT 1 FROM pg_extension WHERE extname='pxf';" 2>/dev/null || true)
|
||||
@@ -27,6 +119,7 @@ ensure_pxf_extension() {
|
||||
}
|
||||
|
||||
for attempt in $(seq 1 "${attempts}"); do
|
||||
# Ждём, пока master начнёт принимать подключения.
|
||||
if /usr/local/greenplum-db/bin/pg_isready \
|
||||
-h 127.0.0.1 -p 5432 -U "${gp_user}" -d "${gp_db}" >/dev/null 2>&1; then
|
||||
if extension_exists; then
|
||||
@@ -49,12 +142,20 @@ ensure_pxf_extension() {
|
||||
echo "WARN - Greenplum не готов или extension pxf не создано"
|
||||
}
|
||||
|
||||
# 1) Подготовка PXF_BASE (копирование seed, конфигов и т.д.).
|
||||
if [ -f "${ensure_script}" ]; then
|
||||
"${ensure_script}"
|
||||
else
|
||||
echo "WARN - не найден ensure-скрипт PXF: ${ensure_script}"
|
||||
fi
|
||||
|
||||
# 2) Дальше запускаем две "подстраховки" параллельно, чтобы не замедлять старт контейнера:
|
||||
# - правка pg_hba.conf (как только он появится на томе);
|
||||
# - создание extension pxf (как только GPDB начнёт отвечать).
|
||||
ensure_pg_hba_trust &
|
||||
|
||||
ensure_pxf_extension &
|
||||
|
||||
# 3) Стартуем GPDB "как обычно". Важно использовать exec, чтобы сигналы Docker
|
||||
# (stop/restart) корректно приходили в основной процесс entrypoint.
|
||||
exec /start_gpdb.sh
|
||||
|
||||
Reference in New Issue
Block a user