Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/yandex-cloud-examples/yc-yq-airflow-etl
Yandex query. Pipeline охлаждения данных с использованием федерации источников.
https://github.com/yandex-cloud-examples/yc-yq-airflow-etl
airflow yandex-cloud yandexcloud yq
Last synced: about 14 hours ago
JSON representation
Yandex query. Pipeline охлаждения данных с использованием федерации источников.
- Host: GitHub
- URL: https://github.com/yandex-cloud-examples/yc-yq-airflow-etl
- Owner: yandex-cloud-examples
- License: apache-2.0
- Created: 2024-06-11T12:56:51.000Z (5 months ago)
- Default Branch: main
- Last Pushed: 2024-06-11T13:33:48.000Z (5 months ago)
- Last Synced: 2024-06-11T15:04:15.242Z (5 months ago)
- Topics: airflow, yandex-cloud, yandexcloud, yq
- Language: HCL
- Homepage:
- Size: 1.37 MB
- Stars: 0
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Yandex query. Pipeline охлаждения данных с использованием федерации источников
В данном решении будет представлен вариант решения задачи "охлаждения" данных с использованием Yandex Query и Managed Service for Apache Airflow
- будут созданы необходимые ресурсы
- База данных Managed PostgreSQL c секционированной таблицей платежей
- Object Storage для хранения "холодных" данных
- представлен пример Airflow DAG для
- экспорта данных из PostgreSQL в Object Storage
- верификации экспортированных данных с использованием федеративного SQL запроса## Инфраструктура
Инфраструктура создается с помощью Terraform configuration. Для этого
- получить IAM токен
```sh
export TF_VAR_yc_token=$(yc iam create-token)
```- Применить Terraform Configuration
```sh
cd src/tf
terraform init
terraform apply
```Примечание: по возможности исполняйте предыдущую команду в окружении с установленным пакетом postgresql-client и установленным по [инструкции](https://yandex.cloud/ru/docs/managed-postgresql/operations/connect#get-ssl-cert) сертификатом. При выполнении этих условий все необходимые действия с Managed PostgreSQL выполняться автоматически. В противном случае после создания базы и пользователя Вам будет необходимо выполнить [SQL сценарий](src/sql/db_init.sql) над созданной базой вручную.
В результате выполнения Terraform будут созданы
- сеть и подсеть.
- Managed PostgreSQL с базой и секционированной таблицей "платежей" и данными за четыре года - 2020-2024. Подробнее см. [db_init.sql](src/sql/db_init.sql)
- два Object Storage bucket-а: один для Airflow DAGs, другой для данных, которые мы будем сохранять.
- сервисный аккаунт со статическим и авторизованным ключами доступа.После создания ресурсов нужно дополнительно дать доступ к Managed PostgreSQL из Yandex Query (на момент написания этого решения данный атрибут не поддержан в Terraform provider).
![Рисунок 1](img/YQ2PGAccess.png "Соединение с Managed PostgreSQL")## Managed Service for Apache Airflow
На текущий момент нет возможности автоматизировать создание и настройку Managed Service for Apache Airflow. Поэтому ниже идет последовательность, которую необходимо выполнить для создания сервиса через консоль.Создать Managed Service for Apache Airflow со следующими настройками
![Рисунок 2](img/airflow_config1.png "Настройки доступа")
![Рисунок 3](img/airflow_config2.png "Хранилище DAG файлов")
Здесь для заполнения полей использовать значения полученные при выполнении командИдентификатор ключа -
```sh
terraform output access_key
```
Секретный ключ
```sh
terraform output secret_key
```
Остальные настройки заполнить на свое усмотрение, либо оставить значения по умолчанию.После того, как сервис будет создан, зайти в консоль администрирования Apache Airflow
- создать три новых соединения- Admin-> Connections-> Add new record
c параметрамиConnection Id = yc-airflow-sa
Connection Type = Yandex Cloud
Service account auth JSON = содержимое файла src/tf/auth_key.json
Public SSH key = содержимое поля private_key файла src/tf/auth_key.json,
- Admin-> Connections-> Add new record
c параметрами
![Рисунок 4](img/AirflowConnection2.png "Airflow AWS Connection")
Connection Id = aws_default
Connection Type = Amazon Web Services
AWS Access Key ID = Access key полученный выше при создании статического ключа доступа
AWS Secret Access Key = Secret key полученный выше при создании статического ключа доступа
Extra =
```json
{
"endpoint_url": "https://storage.yandexcloud.net/",
"region_name": "ru-central1"
}```и
- Admin-> Connections-> Add new record
c параметрами![Рисунок 5](img/PGConnection.png "PostgreSQL Connection")
Connection Id = pg
Connection Type = Postgres
Host = FQDN хоста PosgreSQL, созданного из Terraform ConfigurationDatabase = Login = имя пользователя из Terraform Configuration
Password = пароль пользователя из Terraform ConfigurationPort = 6432
- и две новых переменных
- Admin-> Variables-> Add new record
c параметрами![Рисунок 6](img/AirflowVar1.png "PostgreSQL Connection")
Key = YC_DP_FOLDER_ID
Val =
где FOLDER_ID это идентификатор каталога в Yandex Cloudи
- Admin-> Variables-> Add new record
c параметрами![Рисунок 6](img/AirflowVar2.png "PostgreSQL Connection")
Key = EXP_DATE
Val = 2020-01-01 - дата для первого экспорта данных## Yandex Query
Создадим два подключения
- подключение к Object Storage, где будут лежать "холодные" данные
![Рисунок 6](img/YQObjectStorageConnection.png "Соединение с Object Storage")- подключение к Managed PostgreSQL, откуда данные будем забирать
![Рисунок 7](img/YQPGConnection.png "Соединение с Managed PostgreSQL")
здесь в качестве пользователя и пароля нужно указать данные, которые использовались в Terraform Configurationи одну привязку
![Рисунок 8](img/YQLink1.png "Привязка Object Storage 1")
![Рисунок 9](img/YQLink2.png "Привязка Object Storage 2")
![Рисунок 10](img/YQLink3.png "Привязка Object Storage 3")
![Рисунок 11](img/YQLink4.png "Привязка Object Storage =4")## Apache Airflow. Запуск DAG
И теперь можно пробовать запустить наш DAG. Он должен присутствовать в списке DAG-ов под именем YQ_DEMO.
![Рисунок 12](img/DAGList.png "Список DAG-ов")Коротко о сути графа обработки:
![Рисунок 13](img/DAG_chart.png "DAG")
- на первом этапе должно произойти удаление всех объектов Object Storage bucket с префиксами payment_year=<год из переменной EXP_DATE>. Это делается на случай повторного экспорта
```python
object_keys = s3_hook.list_keys(bucket_name=bucket_name, prefix='etl/payment_year={var}'.format(var = exp_start_date.year))
s3_hook.delete_objects(bucket=bucket_name, keys=object_keys)
```- на втором этапе - загрузка данных из PostgreSQL в Object Storage с использованием Yandex Query.
```python
yq_load_task = YQExecuteQueryOperator(
task_id = 'yq_load_task',
folder_id = Variable.get('YC_DP_FOLDER_ID'),
yandex_conn_id = ycSA_connection.conn_id,
sql = '''
$s = (select unwrap(p.id) as id, p.doc_num, p.accdt, p.acckt, p.amount, cast(p.payment_date as datetime) as payment_date, descr, p.state
from `pg-finance`.payments p
where cast(p.payment_date as datetime) >= date('{var1}') and
cast(p.payment_date as datetime) < date('{var2}')
);
insert into etl_object_storage
(id, doc_num, accdt, acckt, amount, payment_date, descr, state, payment_year)
select id, doc_num, accdt, acckt, amount, payment_date, descr, state, unwrap(cast(DateTime::GetYear(payment_date) as UInt32)) from $s;
'''.format(var1 = exp_start_date.strftime('%Y-%m-%d'), var2 = exp_end_date.strftime('%Y-%m-%d')),
dag = yq_demo_dag
)
```- третий этап: сверка данных. Для сверки мы тоже используем федеративный запрос Yandex Query, сравнивая данные в разных источниках
```python
yq_check_diff_task = YQExecuteQueryOperator(
task_id = 'yq_check_diff_task',
folder_id = Variable.get('YC_DP_FOLDER_ID'),
yandex_conn_id = ycSA_connection.conn_id,
sql = '''
$s = (select unwrap(p.id) as id, p.doc_num, p.accdt, p.acckt, p.amount, cast(p.payment_date as datetime) as payment_date, descr, p.state
from `pg-finance`.payments p
where cast(p.payment_date as datetime) >= date('{var1}') and
cast(p.payment_date as datetime) < date('{var2}')
);
$d = (select p.id as id, p.doc_num, p.accdt, p.acckt, p.amount, p.payment_date, descr, p.state
from etl_object_storage p
where p.payment_date >= date('{var1}') and
p.payment_date < date('{var2}')
);
select count(1) from $s s exclusion join $d d on s.id = d.id and s.doc_num = d.doc_num
and s.accdt = d.accdt and s.acckt = d.acckt and s.amount = d.amount and s.state = d.state;
'''.format(var1 = exp_start_date.strftime('%Y-%m-%d'), var2 = exp_end_date.strftime('%Y-%m-%d')),
dag = yq_demo_dag
)
```- дальше проще - проверяем результат сверки (нулевое количество строк соединения exclusion join), удаляем перенесенные разделы и меняем переменную EXP_DATE для следующего экспорта. Подробнее см. код [src/py/yq_dag.py](src/py/yq_dag.py)
Если все создано и настроено верно, то в результате успешного запуска DAG должен выглядеть примерно так
![Рисунок 14](img/DAG_chart_success.png "Успешный запуск")## Что в итоге
- С помощью Yandex Query и Managed Service for Apache Airflow мы построили pipeline автоматизации частичного переноса данных из реляционной базы в Object Storage.
- При этом качество переноса верифицируется федеративным YQL запросом.
- Федерация источников позволяет и далее работать с разделенными данными из Yandex Query![Рисунок 15](img/YQ_Federation_Query.png "Union all")
Текст запроса
```sql
$a =
select id, cast(payment_date as datetime) as pdate, 'pg' as src from `pg-finance`.payments
union all
select id, payment_date as pdate, 's3' as src from etl_object_storage;select dyear, src, count(1) from $a
group by DateTime::GetYear(pdate) as dyear, src order by dyear;
```