Оригинал: Crossplane v2 — Infrastructure as Code for Kubernetes Platform Teams Part 1 — Andy Welsh (tinfoilcipher), 8 октября 2025. Адаптивный перевод; все права на оригинал принадлежат автору. Примеры кода — в репозитории автора .
Что такое Crossplane: control plane повсюду
Официально Crossplane описывают так: «Cloud-Native фреймворк для платформенной инженерии. Создавайте платформы как облачные провайдеры. Стройте собственные API и сервисы через control plane. Расширяйте Kubernetes для управления любыми ресурсами где угодно».
Control plane — понятие из сетевой маршрутизации, которое лет десять назад переняли разработчики cloud-native систем. В облаке control plane — это софт (обычно платформа с API), который управляет бэкенд-системами. Пользователь шлёт запрос в API control plane, а тот выполняет действия от его имени.
Crossplane создаёт дополнительные control plane внутри Kubernetes — как слой оркестрации облачных ресурсов. Он позволяет заводить кастомные ресурсы, шаблоны и workflow, отдаваемые потребителям в виде обычных Kubernetes CRD. То есть команды разработки создают и управляют облачными ресурсами через те же YAML-манифесты, что и всё остальное в Kubernetes — без изучения DSL Terraform, CloudFormation или ARM Templates.
⚠️ Важно не путать: у самого Kubernetes уже есть свой control plane (в старой терминологии — master-ноды). Control plane от Crossplane — это другое. Crossplane и его managed-ресурсы исполняются на data plane Kubernetes, как обычные рабочие нагрузки.
Установка
Ставится через Helm, рекомендуется в namespace crossplane-system:
helm repo add crossplane-stable https://charts.crossplane.io/stable
helm repo update
helm install crossplane -n crossplane-system crossplane-stable/crossplane --create-namespaceЖдём готовности подов:
kubectl get pods -n crossplane-system -wNAME READY STATUS RESTARTS AGE
crossplane-691bd74f88-9wabx 1/1 Running 0 2m
crossplane-rbac-manager-7bbf7153f4-8fjab 1/1 Running 0 2mБезопасная интеграция с облаком
Чтобы provisioning работал, Crossplane нужен способ общаться с API облачного провайдера. В примере — AWS.
В документации часто показывают статические ключи — это большая дыра в безопасности. Правильный путь — IRSA (IAM Roles for Service Accounts) поверх OIDC. Настройка самой роли выходит за рамки статьи (хорошо описана в документации AWS).
Три ключевых понятия правильной интеграции с публичным облаком:
- DeploymentRuntimeConfig — задаёт IRSA-роль и конфигурацию окружения;
- Provider — скачивает плагины Crossplane (пакеты
xpkg) под конкретный API облака, используя учётку из DeploymentRuntimeConfig; - ProviderConfig — интерфейс, через который Managed Resources шлют запросы в Provider; бывает namespaced или cluster-wide.
Манифесты:
# 01-provider.yaml
apiVersion: pkg.crossplane.io/v1beta1
kind: DeploymentRuntimeConfig
metadata:
name: aws
spec:
serviceAccountTemplate:
metadata:
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/crossplane-example-role
---
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: provider-aws-s3
spec:
package: xpkg.upbound.io/upbound/provider-aws-s3:v2.1.0
runtimeConfigRef:
name: awskubectl apply -f 01-provider.yamlПроверяем установку провайдера:
kubectl get provider
# NAME INSTALLED HEALTHY PACKAGE AGE
# provider-aws-s3 True True xpkg.upbound.io/upbound/provider-aws-s3:v2.1.0 15mПакеты и где их искать
Provider требует URI пакета для скачивания плагина API. По источникам плагинов в интернете много противоречивой инфы — она менялась со временем. Актуальная сводка:
| URL/URI | Назначение |
|---|---|
https://github.com/orgs/crossplane-contrib/packages | Официальные релизы пакетов Crossplane с документацией |
https://marketplace.upbound.io/ | Спецификации пакетов и их CRD |
ghcr.io/crossplane-contrib/$PACKAGE_NAME:$TAG | Image URI для пакетов в releases |
xpkg.crossplane.io/crossplane-contrib/$PACKAGE_NAME/$TAG | Image URI, рекомендованный в доках |
xpkg.upbound.io/crossplane-contrib/$PACKAGE_NAME/$TAG | Image URI для пакетов до v1.2 |
Использование xpkg.crossplane.io соответствует рекомендациям документации. Полный список провайдеров и функций со схемами — на marketplace.upbound.io
(похоже на Terraform Registry).
⚠️ Не задокументировано: смешивание источников устанавливает провайдеры, но ломает встроенный RBAC-manager для Service Account провайдеров необычным образом. Придерживайтесь одного источника.
Где живут провайдеры
Провайдеры всегда деплоятся в тот же namespace, что и Crossplane (по умолчанию crossplane-system). Можно создать несколько провайдеров, но развести их по разным namespace нельзя.
Когда провайдер разворачивается и тянет пакет, поднимаются поды, исполняющие его задачи. Смотреть провайдеры можно без указания namespace:
kubectl get provider
# NAME INSTALLED HEALTHY PACKAGE AGE
# provider-aws-s3 True True xpkg.upbound.io/upbound/provider-aws-s3:v2.1.0 20mПоды-исполнители — в namespace crossplane-system:
kubectl get po -n crossplane-system
# NAME READY STATUS RESTARTS AGE
# crossplane-69ff884f88-9whvg 1/1 Running 0 15m
# provider-aws-s3-b8661e4aa4e9-12c59dedd1-625dg 1/1 Running 0 21mВ логах пода provider-aws-s3 видны вызовы к AWS S3 API.
Cluster-wide или namespaced ProviderConfig
ProviderConfig бывает двух видов:
- ClusterProviderConfig — доступен всем тенантам кластера из любого namespace;
- ProviderConfig (несколько штук) — доступен только внутри своего namespace.
Оба хорошо работают в мультитенантных средах, где несколько тенантов делят один кластер с namespace-ограниченными правами. В примере — ClusterProviderConfig (namespaced-вариант есть в репозитории автора).
Сначала создаём namespace для тенантов:
# 02-namespaces.yaml
apiVersion: v1
kind: Namespace
metadata:
name: tenant1
---
apiVersion: v1
kind: Namespace
metadata:
name: tenant2kubectl apply -f 02-namespaces.yamlСоздаём единый ClusterProviderConfig:
# 03-providerconfig.yaml
apiVersion: aws.m.upbound.io/v1beta1
kind: ClusterProviderConfig
metadata:
name: aws
spec:
credentials:
source: IRSA
endpoint:
url:
type: Dynamic
dynamic:
host: amazonaws.com
protocol: https
services: [s3]kubectl apply -f 03-providerconfig.yamlПосле этого провайдер начинает следить за запросами на ресурсы через поддерживаемые ProviderConfig.
Managed Resources
Инфраструктура готова — можно создавать Managed Resources в namespace. Спецификация у каждого ресурса своя, но общие поля схемы такие:
| Поле | Назначение | Опционально |
|---|---|---|
forProvider | Входные параметры Managed Resource | Нет |
initProvider | Переопределение дефолтов провайдера | Да |
providerConfigRef | Какой ProviderConfig используется | Нет |
managementPolicies | Политики управления Crossplane | Да |
writeConnectionSecretToRef | Secret для возвращаемых данных ресурса | Да |
Манифест создаёт два S3-бакета — по одному на тенанта:
# 04-resources.yaml
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
metadata:
name: tinfoil-example-bucket-08-10-25-tenant-1
namespace: tenant1
spec:
forProvider:
forceDestroy: true
region: eu-west-2
providerConfigRef:
kind: ClusterProviderConfig
name: aws
---
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
metadata:
name: tinfoil-example-bucket-08-10-25-tenant-2
namespace: tenant2
spec:
forProvider:
forceDestroy: true
region: eu-west-2
providerConfigRef:
kind: ClusterProviderConfig
name: awskubectl apply -f 04-resources.yamlЧерез несколько секунд бакеты появляются в AWS:
kubectl get buckets.s3.aws.m.upbound.io --all-namespaces
# NAMESPACE NAME SYNCED READY EXTERNAL-NAME AGE
# tenant1 tinfoil-example-bucket-08-10-25-tenant-1 True True tinfoil-example-bucket-08-10-25-tenant-1 41s
# tenant2 tinfoil-example-bucket-08-10-25-tenant-2 True True tinfoil-example-bucket-08-10-25-tenant-2 43s- Synced: True — Crossplane успешно свёл желаемое состояние с фактическим в AWS;
- Ready: True — ресурс создан/изменён в AWS и готов к использованию.
Что дальше
Это только основы. Создание одного S3-бакета выглядит как много работы ради малого, но Crossplane нацелен на масштабную автоматизацию и управление жизненным циклом ресурсов больших платформ, а не на единичные ресурсы. Фундамент должен быть прочным и масштабируемым до того, как вы создадите первый ресурс.
В следующей части — как раскрыть потенциал кастомизации Crossplane: строим собственные CRD и pre-templated сервисы через Composition.