Оригинал: CNPG Recipe 23 — Managing extensions with ImageVolume in CloudNativePG — 1 декабря 2025.
То, о чём писали в «Иммутабельном будущем расширений» ещё в марте 2025 — теперь полностью работает. PostgreSQL 18 + Kubernetes 1.33 (ImageVolume) + CloudNativePG 1.27 позволяют поставлять расширения отдельными лёгкими OCI-образами, монтируя их в минимальный operand-образ Postgres без пересборки кастомного Docker-image.
«Прощайте, времена, когда расширения Postgres приходилось паковать в основной operand-образ.»
Предусловия
- Kubernetes 1.33+ с включённым feature gate
ImageVolume. - PostgreSQL 18 — нужен
extension_control_path. - CloudNativePG последней stable-версии.
На локальном
kind-кластере feature gate надо включить явно при создании кластера.
Стартуем с минимальным CNPG-кластером
Базовый minimal-образ PostgreSQL 18 — 260 МБ (ровно core, без расширений, см. статью про PG 18).
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: angus
spec:
imageName: ghcr.io/cloudnative-pg/postgresql:18-minimal-trixie
instances: 1
storage:
size: 1GiПодключаем pgvector отдельным образом
Главная фишка — новый блок postgresql.extensions. Вместо переключения на тяжёлый кастомный образ — монтируем отдельный extension-образ. Образ pgvector весит всего 613 КБ.
Манифест
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: angus
spec:
imageName: ghcr.io/cloudnative-pg/postgresql:18-minimal-trixie
instances: 1
storage:
size: 1Gi
postgresql:
extensions:
- name: pgvector
image:
reference: ghcr.io/cloudnative-pg/pgvector:0.8.1-18-trixie
---
apiVersion: postgresql.cnpg.io/v1
kind: Database
metadata:
name: angus-app
spec:
name: app
owner: app
cluster:
name: angus
extensions:
- name: vector
version: '0.8.1'Проверка
Что лежит в смонтированном volume:
kubectl exec -ti angus-1 -c postgres -- ls /extensions/Ожидаем:
pgvectorЧто в БД:
kubectl cnpg psql angus -- app -c '\dx' List of installed extensions
Name | Version | Default version | Schema | Description
---------+---------+-----------------+----------+------------------------------------------------------
plpgsql | 1.0 | 1.0 | pg_catalog | PL/pgSQL procedural language
vector | 0.8.1 | 0.8.1 | public | vector data type and ivfflat and hnsw access methods
(2 rows)Что мы здесь сделали
Три ключевых вещи:
- Регистрация на уровне кластера. Блок
postgresql.extensionsссылается на конкретный extension-образ с скомпилированными бинарями. - Монтирование через ImageVolume. Оператор сам монтирует содержимое extension-образа в файловую систему Postgres-пода (read-only) — и подкручивает PostgreSQL 18-овский
extension_control_path. - Декларативная активация. Ресурс
Database.spec.extensionsотвечает заCREATE EXTENSION. Полеversionпозволяет оператору рулить апгрейд-путями (ALTER EXTENSION ... UPDATE TO ...).
Сравните с обычным деплоем pgvector через ресурс Database (без отдельного образа) — Рецепт 18.
Несколько сложных расширений: PostGIS
Настоящая сила подхода видна на сложных расширениях вроде PostGIS, которому нужны companion-расширения и shared library dependencies.
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: angus
spec:
imageName: ghcr.io/cloudnative-pg/postgresql:18-minimal-trixie
instances: 1
storage:
size: 1Gi
postgresql:
extensions:
- name: pgvector
image:
reference: ghcr.io/cloudnative-pg/pgvector:0.8.1-18-trixie
- name: postgis
image:
reference: ghcr.io/cloudnative-pg/postgis-extension:3.6.1-18-trixie
ld_library_path:
- system
---
apiVersion: postgresql.cnpg.io/v1
kind: Database
metadata:
name: angus-app
spec:
name: app
owner: app
cluster:
name: angus
extensions:
- name: vector
version: '0.8.1'
- name: postgis
version: '3.6.1'
- name: postgis_raster
- name: postgis_sfcgal
- name: fuzzystrmatch
- name: address_standardizer
- name: address_standardizer_data_us
- name: postgis_tiger_geocoder
- name: postgis_topologyКонфигурация ld_library_path важна: PostGIS требует правильного пути для динамического линкера.
Что в итоге
Подход с ImageVolume в CloudNativePG 1.27+ даёт:
- Decoupling. Core-образ Postgres и extension-образы апгрейдятся независимо. Это удобно и пользователям, и мейнтейнерам CloudNativePG.
- Динамическое подключение. Расширения добавляются в живой кластер без предварительного планирования.
- Маленькие образы. Базовый
imageNameостаётся минимальным, безопасным и простым (260 МБ для PG 18). - Консистентность. Оператор сам разруливает сложные mounting-сценарии и зависимости — без кастомных Dockerfile’ов и регресса между кластерами.
Репозиторий postgres-extensions-containers
занимается стандартизацией создания extension-образов. Цель — расширять список поддерживаемых расширений через сообщество, превращая его участников в extension-мейнтейнеров.
См. также:
- «Иммутабельное будущее расширений» — анонс концепции в марте 2025.
- Рецепт 18 — pgvector через ресурс
Databaseбез ImageVolume (для до-PG-18 кластеров). - PostgreSQL 18 в Kubernetes — релиз PG 18 и
extension_control_path.