Привет, Я DocuDroid!
Оценка ИИ поиска
Спасибо за оценку нашего ИИ поиска!
Мы будем признательны, если вы поделитесь своими впечатлениями, чтобы мы могли улучшить наш ИИ поиск для вас и других читателей.
GitHub

PL/Container

Андрей Аксенов
Contents

Расширение языка PL/Container в Greengage DB позволяет создавать и запускать пользовательские функции на PL/Python и PL/R внутри Docker-контейнеров. PL/Container снижает риски безопасности, ограничивая доступ к сегмент-хостам Greengage DB. В этой статье описывается, как установить, настроить и использовать PL/Container.

Обзор PL/Container

Расширение языка PL/Container позволяет безопасно создавать и запускать пользовательские функции, написанные на PL/Python или PL/R, внутри Docker-контейнеров. Docker предоставляет механизм упаковки и выполнения приложений в слабо изолированной среде, называемой контейнером. Для получения дополнительной информации о Docker смотрите документацию на https://www.docker.com.

Запуск пользовательских функций внутри Docker-контейнеров обеспечивает следующие преимущества:

  • Выполнение функции происходит в отдельной среде, что отделяет пользовательскую обработку данных от основной обработки запроса. Операторы SQL, такие как Scan и Filter, выполняются на стороне исполнителя запросов (Query Executor, QE), тогда как сложная обработка данных выполняется внутри контейнера.

  • Пользовательский код полностью изолирован от операционной системы и файловой системы хоста, что предотвращает угрозы безопасности.

  • Функции не могут подключаться к СУБД, если контейнер настроен с ограниченным или отсутствующим доступом к сети, что обеспечивает безопасность данных.

Последовательность выполнения функции PL/Container

Рассмотрим запрос, который выбирает данные из таблиц на всех сегментах Greengage DB и обрабатывает их с помощью функции PL/Container:

  1. При первом вызове функции на сегменте исполнитель запроса на мастер-хосте запускает контейнер на этом сегмент-хосте.

  2. Затем исполнитель запросов взаимодействует с запущенным контейнером, чтобы выполнить функцию и получить результаты.

  3. (Опционально) Контейнер может выполнить вызов SPI (Server Programming Interface) — внутренний SQL-запрос, выполняемый контейнером для получения дополнительных данных из БД — и вернуть полученные данные исполнителю запросов.

  4. Контейнер остается в состоянии ожидания, прослушивает сокет и не потребляет ресурсы CPU. Память, потребляемая PL/Container, в основном определяется объемом данных, кешированных в глобальных словарях.

  5. Когда сессия Greengage DB, запустившая контейнер, завершается, соединение с контейнером закрывается, и контейнер автоматически останавливается.

Предварительные требования

Для демонстрации настройки и использования PL/Container используется инициализированный и запущенный кластер с четырьмя хостами:

  • mdw — мастер-хост.

  • smdw — резервный мастер-хост.

  • sdw1 и sdw2 — сегмент-хосты.

В данном демонстрационном окружении административный пользователь Greengage DB (gpadmin) имеет привилегии sudo, хотя они не требуются для корректной работы СУБД. Информацию об инициализации СУБД смотрите в статье Инициализация СУБД.

Настройка Docker

Для работы PL/Container требуется установка Docker на всех хостах кластера Greengage DB. Ниже приведены инструкции по установке и настройке Docker на Ubuntu 22.04.

Установка и запуск Docker

Выполните следующие шаги на каждом хосте Greengage DB:

  1. Войдите под пользователем gpadmin.

    $ sudo su - gpadmin
  2. Обновите все программные пакеты, установленные в системе:

    $ sudo apt-get update
  3. Установите пакеты, необходимые для Docker:

    $ sudo apt-get install ca-certificates curl
  4. Добавьте GPG-ключ для Docker-репозитория:

    $ sudo install -m 0755 -d /etc/apt/keyrings
    $ sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
    $ sudo chmod a+r /etc/apt/keyrings/docker.asc
  5. Добавьте Docker-репозиторий:

    $ echo \
    "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
    $(. /etc/os-release && echo "jammy") stable" | \
    sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
  6. Обновите индекс пакетов, чтобы включить репозиторий Docker:

    $ sudo apt-get update
  7. Установите Docker Engine и связанные компоненты:

    $ sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
  8. Запустите сервис Docker:

    $ sudo systemctl start docker
  9. Включите автозапуск Docker при загрузке системы:

    $ sudo systemctl enable docker

Предоставление gpadmin доступа к Docker

После установки Docker необходимо настроить права доступа, чтобы пользователь gpadmin мог управлять Docker-образами и контейнерами:

  1. Добавьте пользователя gpadmin в группу docker:

    $ sudo usermod -aG docker gpadmin
  2. Выйдите из текущей сессии и войдите снова под пользователем gpadmin, чтобы изменения в группах вступили в силу.

  3. Проверьте доступность Docker, выполнив команду:

    $ docker ps

    Если Docker настроен корректно, команда отобразит пустой список запущенных контейнеров.

Перезапуск кластера

После настройки Docker перезапустите СУБД Greengage, чтобы применить изменения и обеспечить доступ к Docker:

$ gpstop -r

Установка PL/Container

PL/Container должен быть установлен на всех хостах кластера Greengage DB.

Сборка PL/Container из исходного кода

Выполните следующие действия на каждом хосте кластера Greengage DB, войдя в систему под пользователем gpadmin:

  1. Клонируйте репозиторий plcontainer:

    $ git clone https://github.com/arenadata/plcontainer.git
  2. Перейдите в каталог plcontainer:

    $ cd plcontainer
  3. Переключитесь на необходимый тег релиза, чтобы собрать указанную версию, например:

    $ git checkout 2.4.0
  4. Создайте каталог build и перейдите в него:

    $ mkdir build && cd build
  5. Настройте сборку с помощью cmake, указав путь к исполняемому файлу pg_config:

    $ cmake .. -DPG_CONFIG=/usr/local/gpdb/bin/pg_config
  6. Скомпилируйте PL/Container с помощью make:

    $ make -j$(nproc)
  7. Выполните make install, чтобы установить PL/Container в каталоги Greengage DB:

    $ make -j$(nproc) install

    Пример вывода после установки:

    -- Installing: /usr/local/gpdb/lib/postgresql/plcontainer.so
    -- Installing: /usr/local/gpdb/share/postgresql/extension/plcontainer--1.0.0.sql
    -- Installing: /usr/local/gpdb/share/postgresql/extension/plcontainer.control
    -- Installing: /usr/local/gpdb/share/postgresql/plcontainer/plcontainer_configuration.xml
    -- Installing: /usr/local/gpdb/bin/plcontainer
    -- Installing: /usr/local/gpdb/bin/plcontainer_clients/py3client.sh
    -- Installing: /usr/local/gpdb/bin/plcontainer_clients/pyclient.sh
    -- Installing: /usr/local/gpdb/bin/plcontainer_clients/rclient.sh

Управление Docker-образами PL/Container

Подготовка Docker-образов по умолчанию

Выполните следующие действия на мастер-хосте, чтобы собрать Docker-образы PL/Container по умолчанию:

  1. Перейдите в каталог plcontainer/build:

    $ cd ~/plcontainer/build/
  2. Соберите Docker-образы по умолчанию:

    $ make images_artifact

    Этот шаг генерирует Docker-образы, необходимые для окружений PL/Python и PL/R.

  3. Выведите список Docker-образов, чтобы проверить их создание:

    $ docker image ls

    Результат должен выглядеть так:

    IMAGE                    ID             DISK USAGE   CONTENT SIZE   EXTRA
    python27.ubuntu:latest   0112f2a648c0        982MB          291MB
    python39.alpine:latest   5fc35ccbcd5f        397MB          100MB
    r.alpine:latest          2dceb4e0251b        753MB          203MB
  4. Проверьте созданные файлы Docker-образов:

    $ ls -1 plcontainer-*.tar.gz

    Вывод должен содержать следующие файлы:

    plcontainer-python2-image-2.4.0-gp6.tar.gz
    plcontainer-python3-image-2.4.0-gp6.tar.gz
    plcontainer-r-image-2.4.0-gp6.tar.gz

Установка образов на хосты кластера

После сборки Docker-образов используйте утилиту plcontainer для их установки на все хосты кластера Greengage DB, чтобы PL/Container мог использовать эти образы для выполнения функций:

  1. Установите образ Python 3 на все хосты кластера с помощью plcontainer image-add:

    $ plcontainer image-add -f plcontainer-python3-image-2.4.0-gp6.tar.gz

    Эта команда копирует файл образа на все хосты и загружает его в Docker. Вывод команды должен выглядеть следующим образом:

    20251112:13:37:10:047201 plcontainer:mdw:gpadmin-[INFO]:-Checking whether docker is installed on all hosts...
    20251112:13:37:11:047201 plcontainer:mdw:gpadmin-[INFO]:-Distributing image file plcontainer-python3-image-2.4.0-gp6.tar.gz to all hosts...
    20251112:13:37:12:047201 plcontainer:mdw:gpadmin-[INFO]:-Loading image on all hosts...
    20251112:13:37:17:047201 plcontainer:mdw:gpadmin-[INFO]:-Removing temporary image files on all hosts...
  2. Аналогично установите образ R:

    $ plcontainer image-add -f plcontainer-r-image-2.4.0-gp6.tar.gz

    Эта команда устанавливает образ окружения R на все хосты кластера.

  3. (Опционально) Чтобы удалить ненужный образ, используйте plcontainer image-delete:

    $ plcontainer image-delete -i python27.ubuntu:latest
  4. Выведите список всех установленных образов для проверки:

    $ plcontainer image-list

    Результат может выглядеть следующим образом:

    IMAGE                    ID             DISK USAGE   CONTENT SIZE   EXTRA
    python39.alpine:latest   5fc35ccbcd5f        397MB          100MB
    r.alpine:latest          2dceb4e0251b        753MB          203MB

Управление конфигурациями выполнения PL/Container

PL/Container использует конфигурации выполнения для сопоставления Docker-образов с языковыми средами:

  1. Проверьте существующие конфигурации выполнения:

    $ plcontainer runtime-show

    Ожидаемый результат:

    PL/Container Runtime Configuration:
    No runtime or no specified runtime was found.
  2. Добавьте конфигурацию для Python 3:

    $ plcontainer runtime-add -r plc_python_shared -i python39.alpine:latest -l python3

    Эта команда добавляет новую конфигурацию выполнения и копирует обновленный файл конфигурации на все хосты кластера. Ожидаемый результат:

    20251112:13:49:29:050540 plcontainer:mdw:gpadmin-[INFO]:-Distributing file plcontainer_configuration.xml to all locations...
    20251112:13:49:30:050540 plcontainer:mdw:gpadmin-[INFO]:-Configuration has changed. Run "select * from plcontainer_refresh_config" in open sessions. New sessions will get new configuration automatically.
  3. Добавьте конфигурацию выполнения для R:

    $ plcontainer runtime-add -r plc_r_shared -i r.alpine:latest -l r
  4. Проверьте конфигурации выполнения снова:

    $ plcontainer runtime-show

    Результат должен выглядеть следующим образом:

    PL/Container Runtime Configuration:
    ---------------------------------------------------------
      Runtime ID: plc_python_shared
      Linked Docker Image: python39.alpine:latest
      Runtime Setting(s):
      Shared Directory:
      ---- Shared Directory From HOST '/usr/local/gpdb/bin/plcontainer_clients' to Container '/clientdir', access mode is 'ro'
    ---------------------------------------------------------
    
    ---------------------------------------------------------
      Runtime ID: plc_r_shared
      Linked Docker Image: r.alpine:latest
      Runtime Setting(s):
      Shared Directory:
      ---- Shared Directory From HOST '/usr/local/gpdb/bin/plcontainer_clients' to Container '/clientdir', access mode is 'ro'
    ---------------------------------------------------------

Команды runtime-* утилиты plcontainer также позволяют заменять конфигурации выполнения, редактировать файл plcontainer_configuration.xml с помощью указанного редактора, проверять соответствие конфигурации выполнения на сегментах с мастер-хостом и выполнять другие сопутствующие задачи.

Установка расширения PL/Container

Перед использованием пользовательских функций PL/Container необходимо установить расширение plcontainer в каждой базе данных, которая будет его использовать:

  1. Создайте новую базу данных:

    $ createdb marketplace
  2. Подключитесь к базе данных:

    $ psql marketplace
  3. Установите расширение PL/Container:

    CREATE EXTENSION plcontainer;

    Ожидаемый вывод:

    CREATE EXTENSION
ПРИМЕЧАНИЕ

Если использование PL/Container в базе данных больше не требуется, вы можете удалить расширение с помощью команды DROP EXTENSION. Укажите опцию CASCADE, чтобы автоматически удалить все зависимые объекты, включая функции, созданные с использованием PL/Container.

Разработка функций PL/Container

Когда расширение PL/Container установлено, язык plcontainer можно использовать в определениях функций. Пользовательская функция PL/Container должна содержать:

  • Первая строка: # container: <ID> — указывает конфигурацию выполнения, которая будет использоваться. <ID> соответствует записи Runtime ID в конфигурации выполнения и определяет фактический язык программирования (Python или R), используемый функцией.

  • Атрибут LANGUAGE plcontainer — указывает, что это функция PL/Container.

Создание Python-функции

Создайте функцию на Python с использованием PL/Container:

CREATE FUNCTION greet_from_python()
    RETURNS TEXT
AS
$$
# container: plc_python_shared
return 'Hello from Python!'
$$ LANGUAGE plcontainer;

Выполните созданную функцию:

SELECT greet_from_python();

Результат должен выглядеть так:

 greet_from_python
--------------------
 Hello from Python!
(1 row)

Создание R-функции

Вы также можете создать функцию на R с использованием PL/Container:

CREATE FUNCTION greet_from_r()
    RETURNS TEXT
AS
$$
# container: plc_r_shared
return("Hi from R!")
$$ LANGUAGE plcontainer;

Выполните функцию:

SELECT greet_from_r();

Результат должен выглядеть следующим образом:

 greet_from_r
--------------
 Hi from R!
(1 row)

Создание функции с SPI (plpy)

CREATE TABLE customers
(
    customer_id   SERIAL PRIMARY KEY,
    first_name    VARCHAR(25),
    last_name     VARCHAR(25),
    email         VARCHAR(25)
)
    DISTRIBUTED REPLICATED;
INSERT INTO customers (first_name, last_name, email)
VALUES ('Andrew', 'Fuller', 'andrew@example.com'),
       ('Michael', 'Suyama', 'michael@testmail.com'),
       ('Robert', 'King', 'robert@demo.org');

Создайте функцию PL/Container, которая выполняет SPI-запрос из контейнера с помощью plpy.execute(). Функция получает запись о клиенте по идентификатору и возвращает ее в текстовом формате. Сначала запрос подготавливается через plpy.prepare(), а затем выполняется с использованием списка параметров:

CREATE FUNCTION get_customer_by_id(p_id INT)
RETURNS TEXT
AS
$$
# container: plc_python_shared

plan = plpy.prepare(
    """
    SELECT customer_id, first_name, last_name, email
    FROM customers
    WHERE customer_id = $1
    """,
    ["int"]
)

rows = plpy.execute(plan, [p_id])

if not rows:
    return f"No customer with id={p_id}"

r = rows[0]
return f"{r['customer_id']}: {r['first_name']} {r['last_name']} <{r['email']}>"
$$ LANGUAGE plcontainer;

Выполните функцию:

SELECT get_customer_by_id(2);

Результат должен выглядеть следующим образом:

            get_customer_by_id
------------------------------------------
 2: Michael Suyama <michael@testmail.com>
(1 row)

Для получения информации о методах plpy смотрите соответствующий раздел в документации PostgreSQL: Database Access.

Ограничения функций PL/Container

Учитывайте следующие ограничения при создании и использовании функций PL/Container:

  • Домены Greengage DB не поддерживаются.

  • Многомерные массивы не поддерживаются.

  • При отладке пользовательских функций не отображается стек вызовов Python и R.

  • Методы nrows() и status() у plpy.execute() не поддерживаются.

  • Функция PL/Python plpy.SPIError() не поддерживается.

  • Выполнение команды SAVEPOINT через plpy.execute() не поддерживается.

  • Триггеры не поддерживаются.

  • Параметры OUT не поддерживаются.

  • Тип dict в Python не может быть возвращен из пользовательской функции PL/Python. Чтобы вернуть данные, представленные в dict, преобразуйте их в пользовательский тип данных Greengage DB.

ПРИМЕЧАНИЕ

Модуль Python предоставляет глобальные словари GD и SD, которые сохраняют данные между вызовами функций. GD используется для обмена данными между всеми функциями, выполняющимися в одном контейнере, а SD хранит данные между повторными вызовами одной и той же функции. Доступ к данным возможен только в рамках одной сессии, пока контейнер работает на сегменте или мастере. При отсутствии активности в сессии Greengage DB может завершить процессы сегментов, что приводит к остановке контейнеров и очистке данных, сохраненных в GD и SD.

Просмотр и обновление конфигураций выполнения в SQL

Файл конфигурации PL/Container загружается один раз — при первом вызове функции PL/Container в рамках сессии Greengage DB. Вы можете принудительно перечитать файл конфигурации, выполнив команду SELECT для представления plcontainer_refresh_config в рамках текущей сессии. Например, следующая команда инициирует повторное чтение файла конфигурации:

SELECT * FROM plcontainer_refresh_config;

Команда запускает функцию PL/Container, которая обновляет конфигурацию на мастере и сегментах и возвращает статус обновления:

 gp_segment_id | plcontainer_refresh_local_config
---------------+----------------------------------
             2 | ok
             3 | ok
             1 | ok
             0 | ok
            -1 | ok
(5 rows)

Вы также можете вывести все конфигурации в текущей сессии, выполнив команду SELECT для представления plcontainer_show_config:

SELECT * FROM plcontainer_show_config;

Функция plcontainer_containers_summary() отображает информацию о запущенных в данный момент Docker-контейнерах:

SELECT * FROM plcontainer_containers_summary();

Результат может выглядеть так:

 SEGMENT_ID |                           CONTAINER_ID                           |    UP_TIME    |  OWNER  | MEMORY_USAGE(KB)
------------+------------------------------------------------------------------+---------------+---------+------------------
 -1         | ab12497d6f0be12e4c93744b0981a812f89574f9add80fc80783e450b729bb68 | Up 19 seconds | gpadmin | 96596
 -1         | 92a15903672ae38d41e407e2cca96dc094c217b6c0776562b341b33429b97af8 | Up 29 seconds | gpadmin | 9608
(2 rows)

Если функцию plcontainer_containers_summary() выполняет пользователь без прав суперпользователя, отображается информация только о контейнерах, созданных этим пользователем. Если функцию выполняет суперпользователь, выводится информация обо всех контейнерах, созданных пользователями СУБД.

Greengage DB запускает Docker-контейнеры для выполнения функций PL/Container и повторно использует их при последующих вызовах. Когда исполнитель запросов неактивен определенное время, он завершает работу, а его контейнеры автоматически удаляются. Время простоя контролируется параметром gp_vmem_idle_resource_timeout, который можно настроить для улучшения повторного использования контейнеров и снижения накладных расходов на их запуск.

ПРИМЕЧАНИЕ

Изменение значения параметра gp_vmem_idle_resource_timeout может повлиять на общую производительность кластера из-за особенностей управления ресурсами. Помимо Docker-контейнеров, этот параметр также управляет освобождением других ресурсов СУБД.

Управление ресурсами PL/Container

Docker-контейнеры PL/Container используют CPU и память совместно с процессами СУБД на тех же хостах. По умолчанию Greengage DB не отслеживает ресурсы, потребляемые запущенными экземплярами PL/Container. Чтобы нагрузка контейнеров не сказывалась на производительности кластера, вы можете управлять ресурсами PL/Container на двух уровнях:

  • На уровне контейнера — установите лимиты CPU и памяти для каждого контейнера с помощью параметров memory_mb и cpu_share в конфигурации выполнения PL/Container. Эти ограничения применяются к каждому экземпляру контейнера для данной конфигурации выполнения.

  • На уровне среды выполнения — установите общий объем CPU и памяти, используемый всеми контейнерами данной среды, с помощью ресурсных групп. Назначение ресурсной группы накладывает ее ограничения на все контейнеры указанной среды. Если ресурсная группа не настроена, контейнеры ограничиваются только системными ресурсами и могут конкурировать с процессами Greengage DB за CPU и память.

Управление ресурсами PL/Container с помощью ресурсных групп

Вы можете использовать ресурсные группы для контроля общего потребления CPU и памяти средами выполнения PL/Container. Для внешних компонентов, таких как PL/Container, ресурсные группы используют контрольные группы Linux (cgroups) для применения этих ограничений. Ресурсная группа, назначенная конкретной среде выполнения PL/Container, распространяет свои лимиты CPU и памяти на все контейнеры, создаваемые этой средой.

При создании ресурсной группы для PL/Container необходимо задать MEMORY_AUDITOR=cgroup и CONCURRENCY=0, а также указать требуемые лимиты CPU и памяти. Например, следующая команда создает ресурсную группу с именем rg_plcontainer:

CREATE RESOURCE GROUP rg_plcontainer WITH (
    CPUSET = '1;1',
    MEMORY_LIMIT = 20,
    CONCURRENCY = 0,
    MEMORY_AUDITOR = cgroup
    );

После создания группы выполните запрос к представлению gp_toolkit.gp_resgroup_config, чтобы получить ее идентификатор:

SELECT * FROM gp_toolkit.gp_resgroup_config;

Пример вывода:

 groupid |   groupname    | concurrency | cpu_rate_limit | memory_limit | memory_shared_quota | memory_spill_ratio | memory_auditor | cpuset
---------+----------------+-------------+----------------+--------------+---------------------+--------------------+----------------+--------
    6437 | default_group  | 20          | 30             | 0            | 80                  | 0                  | vmtracker      | -1
    6438 | admin_group    | 10          | 10             | 10           | 80                  | 0                  | vmtracker      | -1
   24993 | rg_plcontainer | 0           | -1             | 20           | 80                  | 0                  | cgroup         | 1;1
(3 rows)

Используйте значение groupid при назначении ресурсной группы среде выполнения PL/Container. Его можно указать с помощью параметра -s resource_group_id=<rg_groupid> в командах plcontainer runtime-add (новая среда выполнения) или plcontainer runtime-replace (существующая среда выполнения), например:

$ plcontainer runtime-add -r plc_python_shared -i python39.alpine:latest -l python3 -s resource_group_id=24993

Логирование PL/Container

Чтобы включить логирование PL/Container для конкретной среды выполнения, установите атрибут use_container_logging в конфигурации данной среды. По умолчанию логирование отключено.

Когда логирование контейнеров включено, уровень логов регулируется параметром log_min_messages. Этот параметр влияет как на вывод логов PL/Container, так и на общие системные логи СУБД. Обратите внимание на следующие моменты:

  • Логи PL/Container содержат сообщения, создаваемые функциями, выполняющимися внутри Docker-контейнера. По умолчанию эти логи перенаправляются в системную службу журналирования. В системах Red Hat или CentOS логи отправляются в службу journald.

  • Для тестирования или отладки функций PL/Container вы можете временно изменить уровень детализации логов в текущей сессии с помощью команды SET. В этом примере используется уровень логирования debug1:

    SET log_min_messages = 'debug1';
ПРИМЕЧАНИЕ

Параметр log_min_messages управляет логированием как сервера Greengage DB, так и PL/Container. Повышение уровня логирования может повлиять на общую производительность кластера, даже если функции PL/Container не выполняются.

Настройка образа PL/Container

В этом разделе описывается, как создать, проверить и развернуть пользовательский образ Docker для PL/Container.

Загрузка базового образа

Перед созданием пользовательского образа загрузите базовые образы по умолчанию, как описано в разделе Подготовка Docker-образов по умолчанию.

Создание нового образа

Создайте Dockerfile для вашего пользовательского образа:

$ vi Dockerfile

Пример Dockerfile, который добавляет NumPy:

FROM python39.alpine
RUN pip install numpy==2.0.2

Сохраните файл и запустите сборку образа:

$ docker build -t python39_with_numpy.alpine:latest .

Проверка совместимости PL/Container с новым образом

Запустите клиент PL/Container для Python внутри нового образа, чтобы проверить совместимость:

$ docker run -it --rm \
  -v $(readlink -f /usr/local/gpdb/bin/plcontainer_clients):/clientdir \
  python39_with_numpy.alpine:latest \
  /clientdir/py3client.sh

Пример вывода:

plcontainer log: pythonclient, unknown, unknown, -1, WARNING: USE_CONTAINER_NETWORK is not set, use default value "no".
plcontainer log: pythonclient, unknown, unknown, -1, ERROR: Cannot bind the addr: No such file or directory

Если вы видите ошибки, начинающиеся с plcontainer log, это означает, что образ совместим с клиентом PL/Container. Эти ошибки ожидаемы при запуске клиента вне базы данных и подтверждают, что контейнер успешно запускает клиентское окружение.

Сохранение образа в архив

Экспортируйте образ в tar-файл для установки на всех хостах кластера:

$ docker save python39_with_numpy.alpine:latest | gzip > python39_with_numpy.alpine.tar.gz

Итоговый файл — python39_with_numpy.alpine.tar.gz.

Установка образа на хосты кластера

Используйте plcontainer image-add, чтобы развернуть образ на всех хостах кластера:

$ plcontainer image-add -f python39_with_numpy.alpine.tar.gz

Пример вывода:

20251113:06:59:51:061170 plcontainer:mdw:gpadmin-[INFO]:-Checking whether docker is installed on all hosts...
20251113:06:59:51:061170 plcontainer:mdw:gpadmin-[INFO]:-Distributing image file python39_with_numpy.alpine.tar.gz to all hosts...
20251113:06:59:52:061170 plcontainer:mdw:gpadmin-[INFO]:-Loading image on all hosts...
20251113:06:59:59:061170 plcontainer:mdw:gpadmin-[INFO]:-Removing temporary image files on all hosts...

Создание конфигурации выполнения

Создайте конфигурацию выполнения PL/Container, которая использует созданный образ:

$ plcontainer runtime-add -r plc_python_numpy -i python39_with_numpy.alpine:latest -l python3

Пример вывода:

20251113:07:00:47:061541 plcontainer:mdw:gpadmin-[INFO]:-Distributing file plcontainer_configuration.xml to all locations...
20251113:07:00:47:061541 plcontainer:mdw:gpadmin-[INFO]:-Configuration has changed. Run "select * from plcontainer_refresh_config" in open sessions. New sessions will get new configuration automatically.

Проверьте конфигурацию выполнения:

$ plcontainer runtime-show -r plc_python_numpy

Результат должен выглядеть так:

PL/Container Runtime Configuration:
---------------------------------------------------------
  Runtime ID: plc_python_numpy
  Linked Docker Image: python39_with_numpy.alpine:latest
  Runtime Setting(s):
  Shared Directory:
  ---- Shared Directory From HOST '/usr/local/gpdb/bin/plcontainer_clients' to Container '/clientdir', access mode is 'ro'
---------------------------------------------------------

Создание функции

Подключитесь к базе данных:

$ psql marketplace

Создайте функцию PL/Container, которая использует NumPy:

CREATE OR REPLACE FUNCTION get_array_shape(arr TEXT)
    RETURNS TEXT
AS
$$
# container: plc_python_numpy
import numpy as np
import ast
input_array = np.array(ast.literal_eval(arr))
return f"Array shape: {input_array.shape}"
$$ LANGUAGE plcontainer;

Запустите функцию:

SELECT get_array_shape('[[1,2,3],[4,5,6]]');

Результат должен выглядеть следующим образом:

   get_array_shape
---------------------
 Array shape: (2, 3)
(1 row)