Crossplane v2. Часть 1. Основы: control plane, провайдеры и Managed Resources

Что такое Crossplane и зачем он расширяет Kubernetes до control plane. Установка через Helm, безопасная интеграция с AWS через IRSA/OIDC (DeploymentRuntimeConfig, Provider, ProviderConfig) и создание первых Managed Resources — S3-бакетов из YAML.
Опубликовано:

Оригинал: 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:

BASH
helm repo add crossplane-stable https://charts.crossplane.io/stable
helm repo update
helm install crossplane -n crossplane-system crossplane-stable/crossplane --create-namespace
Нажмите, чтобы развернуть и увидеть больше

Ждём готовности подов:

BASH
kubectl get pods -n crossplane-system -w
Нажмите, чтобы развернуть и увидеть больше
PLAINTEXT
NAME                                         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).

Три ключевых понятия правильной интеграции с публичным облаком:

Манифесты:

YAML
# 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: aws
Нажмите, чтобы развернуть и увидеть больше
BASH
kubectl apply -f 01-provider.yaml
Нажмите, чтобы развернуть и увидеть больше

Проверяем установку провайдера:

BASH
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:$TAGImage URI для пакетов в releases
xpkg.crossplane.io/crossplane-contrib/$PACKAGE_NAME/$TAGImage URI, рекомендованный в доках
xpkg.upbound.io/crossplane-contrib/$PACKAGE_NAME/$TAGImage URI для пакетов до v1.2

Использование xpkg.crossplane.io соответствует рекомендациям документации. Полный список провайдеров и функций со схемами — на marketplace.upbound.io (похоже на Terraform Registry).

⚠️ Не задокументировано: смешивание источников устанавливает провайдеры, но ломает встроенный RBAC-manager для Service Account провайдеров необычным образом. Придерживайтесь одного источника.

Где живут провайдеры

Провайдеры всегда деплоятся в тот же namespace, что и Crossplane (по умолчанию crossplane-system). Можно создать несколько провайдеров, но развести их по разным namespace нельзя.

Когда провайдер разворачивается и тянет пакет, поднимаются поды, исполняющие его задачи. Смотреть провайдеры можно без указания namespace:

BASH
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:

BASH
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 бывает двух видов:

Оба хорошо работают в мультитенантных средах, где несколько тенантов делят один кластер с namespace-ограниченными правами. В примере — ClusterProviderConfig (namespaced-вариант есть в репозитории автора).

Сначала создаём namespace для тенантов:

YAML
# 02-namespaces.yaml

apiVersion: v1
kind: Namespace
metadata:
  name: tenant1
---
apiVersion: v1
kind: Namespace
metadata:
  name: tenant2
Нажмите, чтобы развернуть и увидеть больше
BASH
kubectl apply -f 02-namespaces.yaml
Нажмите, чтобы развернуть и увидеть больше

Создаём единый ClusterProviderConfig:

YAML
# 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]
Нажмите, чтобы развернуть и увидеть больше
BASH
kubectl apply -f 03-providerconfig.yaml
Нажмите, чтобы развернуть и увидеть больше

После этого провайдер начинает следить за запросами на ресурсы через поддерживаемые ProviderConfig.

Managed Resources

Инфраструктура готова — можно создавать Managed Resources в namespace. Спецификация у каждого ресурса своя, но общие поля схемы такие:

ПолеНазначениеОпционально
forProviderВходные параметры Managed ResourceНет
initProviderПереопределение дефолтов провайдераДа
providerConfigRefКакой ProviderConfig используетсяНет
managementPoliciesПолитики управления CrossplaneДа
writeConnectionSecretToRefSecret для возвращаемых данных ресурсаДа

Манифест создаёт два S3-бакета — по одному на тенанта:

YAML
# 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: aws
Нажмите, чтобы развернуть и увидеть больше
BASH
kubectl apply -f 04-resources.yaml
Нажмите, чтобы развернуть и увидеть больше

Через несколько секунд бакеты появляются в AWS:

BASH
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
Нажмите, чтобы развернуть и увидеть больше

Что дальше

Это только основы. Создание одного S3-бакета выглядит как много работы ради малого, но Crossplane нацелен на масштабную автоматизацию и управление жизненным циклом ресурсов больших платформ, а не на единичные ресурсы. Фундамент должен быть прочным и масштабируемым до того, как вы создадите первый ресурс.

В следующей части — как раскрыть потенциал кастомизации Crossplane: строим собственные CRD и pre-templated сервисы через Composition.

Начать поиск

Введите ключевые слова для поиска статей

↑↓
ESC
⌘K Горячая клавиша