Crossplane v2. Часть 2. Composition: собственные API без написания контроллеров

Composition — система шаблонов Crossplane: XRD, Composition, XR и Functions. Собираем переиспользуемый S3-сервис (бакет + versioning + KMS-шифрование) через pipeline с function-patch-and-transform, связывая ресурсы через labels и selectors.
Опубликовано:

Оригинал: Crossplane v2 — Infrastructure as Code for Kubernetes Platform Teams Part 2 — Andy Welsh (tinfoilcipher), 14 октября 2025. Адаптивный перевод; все права на оригинал принадлежат автору. Примеры кода — в репозитории автора .

Продолжение Части 1. Тема — Composition, система шаблонов, которая позволяет платформенным командам создавать собственные Kubernetes-ресурсы без написания контроллеров.

Что уже есть после части 1

Composition: шаблоны на всех уровнях

Composition раскрывает выгоды «создания собственных Kubernetes custom resources без написания контроллеров». Четыре ключевых понятия:

Практический пример: S3-сервис

Соберём переиспользуемое предложение «S3-бакет», которое:

XRD

XRD заводит новый кастомный ресурс s3buckets.aws.platform.tinfoilcipher.com с kind S3Bucket. Обязательные входы — имя бакета, регион и KMS key ID; теги опциональны.

YAML
apiVersion: apiextensions.crossplane.io/v2
kind: CompositeResourceDefinition
metadata:
  name: s3buckets.aws.platform.tinfoilcipher.com
spec:
  group: aws.platform.tinfoilcipher.com
  names:
    kind: S3Bucket
    plural: s3buckets
  scope: Namespaced
  versions:
    - name: v1alpha1
      schema:
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object
              properties:
                parameters:
                  type: object
                  properties:
                    bucketName:
                      type: string
                    region:
                      type: string
                    versioning:
                      type: string
                    kmsKeyID:
                      type: number
                  required:
                    - bucketName
                    - region
                    - kmsKeyID
                tags:
                  type: object
                  additionalProperties:
                    type: string
              required:
                - parameters
Нажмите, чтобы развернуть и увидеть больше

Установка Function

Function patch-and-transform даёт динамический патчинг YAML-манифестов:

YAML
apiVersion: pkg.crossplane.io/v1
kind: Function
metadata:
  name: patch-and-transform
spec:
  package: xpkg.upbound.io/upbound/function-patch-and-transform:v0.9.0
Нажмите, чтобы развернуть и увидеть больше

Composition pipeline

Composition описывает три Managed Resources в pipeline:

YAML
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: s3bucket.aws.platform.tinfoilcipher.com
  labels:
    aws.platform.tinfoilcipher.com/composition: s3bucket
spec:
  compositeTypeRef:
    apiVersion: aws.platform.tinfoilcipher.com/v1alpha1
    kind: S3Bucket
  mode: Pipeline
  pipeline:
    - step: create-bucket
      functionRef:
        name: patch-and-transform
      input:
        apiVersion: pt.fn.crossplane.io/v1beta1
        kind: Resources
        resources:
          - name: s3-bucket
            base:
              apiVersion: s3.aws.m.upbound.io/v1beta1
              kind: Bucket
              spec:
                forProvider:
                  forceDestroy: false
                providerConfigRef:
                  kind: ClusterProviderConfig
                  name: aws-s3
            patches:
              - fromFieldPath: "spec.parameters.bucketName"
                toFieldPath: "metadata.name"
              - fromFieldPath: "spec.parameters.bucketName"
                toFieldPath: "metadata.labels['aws.platform.tinfoilcipher.com/bucket_name']"
              - fromFieldPath: "spec.parameters.region"
                toFieldPath: "spec.forProvider.region"
              - fromFieldPath: "spec.tags"
                toFieldPath: "spec.forProvider.tags"
          - name: s3-bucket-versioning
            base:
              apiVersion: s3.aws.m.upbound.io/v1beta1
              kind: BucketVersioning
              spec:
                providerConfigRef:
                  kind: ClusterProviderConfig
                  name: aws-s3
            patches:
              - fromFieldPath: "spec.parameters.region"
                toFieldPath: "spec.forProvider.region"
              - fromFieldPath: "spec.parameters.versioning"
                toFieldPath: "spec.forProvider.versioningConfiguration.status"
              - fromFieldPath: "spec.parameters.bucketName"
                toFieldPath: "metadata.labels['aws.platform.tinfoilcipher.com/bucket_name']"
              - fromFieldPath: "spec.parameters.bucketName"
                toFieldPath: "spec.forProvider.bucketSelector.matchLabels['aws.platform.tinfoilcipher.com/bucket_name']"
          - name: s3-bucket-encryption
            base:
              apiVersion: s3.aws.m.upbound.io/v1beta1
              kind: BucketServerSideEncryptionConfiguration
              spec:
                forProvider:
                  rule:
                    - applyServerSideEncryptionByDefault:
                        sseAlgorithm: aws:kms
                providerConfigRef:
                  kind: ClusterProviderConfig
                  name: aws-s3
            patches:
              - fromFieldPath: "spec.parameters.region"
                toFieldPath: "spec.forProvider.region"
              - fromFieldPath: "spec.parameters.bucketName"
                toFieldPath: "metadata.labels['aws.platform.tinfoilcipher.com/bucket_name']"
              - fromFieldPath: "spec.parameters.kmsKeyID"
                toFieldPath: "spec.forProvider.rule[0].applyServerSideEncryptionByDefault.kmsMasterKeyId"
              - fromFieldPath: "spec.parameters.bucketName"
                toFieldPath: "spec.forProvider.bucketSelector.matchLabels['aws.platform.tinfoilcipher.com/bucket_name']"
Нажмите, чтобы развернуть и увидеть больше

Зависимости через labels и selectors

Crossplane использует нативные Kubernetes labels и selectors для управления зависимостями между ресурсами внутри pipeline. Каждому Managed Resource при создании навешиваются лейблы, а нижестоящие ресурсы находят выходы предыдущих через selector. Это позволяет строить forward-зависимости, даже когда выход неизвестен до рантайма.

В примере бакету навешивается лейбл, а ресурсы versioning и encryption через селектор находят бакет по совпадению лейблов.

Создание Composite Resources (XR)

Когда XRD и Composition развёрнуты, тенанты создают XR для провижининга:

YAML
apiVersion: aws.platform.tinfoilcipher.com/v1alpha1
kind: S3Bucket
metadata:
  name: tinfoil-example-bucket-14-10-25-tenant-1
  namespace: tenant1
spec:
  parameters:
    bucketName: tinfoil-example-bucket-14-10-25-tenant-1
    region: eu-west-2
    versioning: Enabled
    kmsKeyID: 15abcf4-15c5-1fe6-afbd-584bcfe57168
  tags:
    environment: dev
    department: devops
Нажмите, чтобы развернуть и увидеть больше

Проверяем:

BASH
kubectl get s3bucket --all-namespaces
# NAME                                       SYNCED   READY   COMPOSITION                               AGE
# tinfoil-example-bucket-14-10-25-tenant-1   True     True    s3bucket.aws.platform.tinfoilcipher.com   2m03s
# tinfoil-example-bucket-14-10-25-tenant-2   True     True    s3bucket.aws.platform.tinfoilcipher.com   2m06s
Нажмите, чтобы развернуть и увидеть больше

Pipeline Composition выполняется асинхронно — обычно провижининг занимает пару минут.

Выбор Composition

При создании XR явной привязки к конкретной Composition нет — XRD сам находит доступные. При одной Composition на XRD выбор автоматический. Если Composition несколько, лучше указать её явно, чтобы избежать непредсказуемого поведения:

YAML
apiVersion: aws.platform.tinfoilcipher.com/v1alpha1
kind: S3Bucket
metadata:
  name: tinfoil-example-bucket-14-10-25-tenant-1
  namespace: tenant1
spec:
  crossplane:
    compositionRef:
      name: s3bucket.aws.platform.tinfoilcipher.com
Нажмите, чтобы развернуть и увидеть больше

Что ещё умеет Crossplane

За кадром осталось многое: запуск ресурсов по расписанию, исполнение кастомного кода, hardening workflow, передача данных между несколькими провайдерами и расширенная библиотека Functions.

Итог

Связка XRD + Composition + XR + Functions превращает Crossplane из «ещё одного способа создать бакет» в платформу самообслуживания: платформенная команда один раз описывает безопасный, преднастроенный сервис (бакет с обязательным KMS-шифрованием и тегами), а тенанты потребляют его простым YAML — не зная деталей AWS. Это и есть суть platform engineering, ради которой Crossplane создавался.

Начать поиск

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

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