Custom Resource Definitions (CRD) в Kubernetes: практическое руководство по созданию и управлению для DevOps | 2026 | AdminWiki
Timeweb Cloud — сервера, Kubernetes, S3, Terraform. Лучшие цены IaaS.
Попробовать

Custom Resource Definitions (CRD) в Kubernetes: практическое руководство по созданию и управлению для DevOps | 2026

01 апреля 2026 9 мин. чтения

Custom Resource Definitions (CRD) — это фундаментальный инструмент для расширения стандартного API Kubernetes под уникальные потребности вашей инфраструктуры. Вместо написания разрозненных скриптов для управления специфичными конфигурациями, вы создаете собственные типы ресурсов, которыми можно управлять через привычный kubectl, получая встроенную валидацию, стандартизированный интерфейс и глубокую интеграцию с экосистемой кластера. Это руководство, основанное на актуальных практиках 2026 года, предоставит вам готовые YAML-манифесты и пошаговые инструкции для быстрого внедрения CRD, что позволит автоматизировать рутинные операции и повысить уровень абстракции управления кластером.

Что такое Custom Resource Definitions и зачем они нужны DevOps-инженеру

Custom Resource Definitions (CRD) — это объекты Kubernetes, которые позволяют добавить в API кластера новые, пользовательские типы ресурсов (Custom Resources). Если стандартные ресурсы вроде Pod, Deployment или Service — это «встроенные типы данных» Kubernetes, то CRD позволяют вам определить свои собственные. Это не просто техническая возможность, а стратегический инструмент для DevOps-инженера, который стремится к стандартизации и автоматизации уникальных операций инфраструктуры: управления доменными конфигурациями приложений, специфичными сетевыми политиками, правилами бэкапа или мониторинга.

Основная ценность CRD заключается в замене кастомных скриптов и внешних систем конфигурации на нативную для Kubernetes модель декларативного управления. Вместо того чтобы писать скрипт, который по SSH подключается к серверам и редактирует конфиги, вы создаете ресурс AppConfig и применяете его через kubectl apply. Контроллер (например, Operator), следящий за такими ресурсами, автоматически приводит инфраструктуру к желаемому состоянию. Этот подход снижает количество ошибок, упрощает аудит изменений и позволяет использовать единую ролевую модель доступа (RBAC).

CRD vs кастомные скрипты: где выгода для вашей инфраструктуры

Чтобы понять практическую выгоду, сравним два подхода к автоматизации задачи «настройка кэша приложения».

Критерий Кастомный скрипт (Bash/Python) Custom Resource Definition (CRD)
Стандартизация интерфейса Уникальный синтаксис, флаги, конфиг-файлы. Требует изучения. Единый интерфейс kubectl (get, apply, describe). Интеграция с Kubernetes CLI.
Валидация конфигурации Ручные проверки в коде скрипта. Ошибки часто обнаруживаются только при выполнении. Встроенная валидация на основе OpenAPI v3 схемы. Ошибки в типах данных или обязательных полях блокируются на этапе kubectl apply.
Безопасность и доступ Отдельная система аутентификации и авторизации (ключи, пароли). Использование встроенной модели RBAC Kubernetes. Можно дать команде доступ только к CR типа AppCache.
Observability Логи пишутся в stdout/stderr или файлы. События не интегрированы с кластером. События (Events) Kubernetes, логи контроллера через kubectl logs, метрики и статус ресурса (kubectl describe).
Сложность поддержки Высокая. Каждый скрипт — это отдельная единица, требующая документирования, тестирования и обновления. Низкая. CRD — это часть декларативной модели кластера. Изменения в схеме версионируются и контролируются.

Простая аналогия: CRD — это как создать собственный тип документа (например, «Техническое задание») с утвержденным шаблоном, с которым умеет работать весь офис (Kubernetes API, CLI, UI). Кастомный скрипт — это рукописная инструкция на бумажке для одного сотрудника, которую нужно каждый раз перепроверять.

Практическое создание CRD: от манифеста до применения в кластере

Теперь перейдем к практике. Создание CRD начинается с YAML-манифеста, который описывает новую схему ресурса для API-сервера Kubernetes.

Разбираем YAML-манифест CRD по полочкам: group, names, scope и версионирование

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

  • apiVersion & kind: Для CRD всегда используйте apiextensions.k8s.io/v1 и CustomResourceDefinition.
  • metadata.name: Имя CRD формируется как <plural>.<group>. Например, appcaches.cache.example.com.
  • spec.group: Доменное имя вашей группы API, например, cache.example.com. Оно должно быть уникальным в рамках кластера.
  • spec.names: Словарь с именами ресурса.
    • kind: Имя типа ресурса в CamelCase (например, AppCache). Оно будет использоваться в YAML-файлах Custom Resources.
    • plural: Имя во множественном числе для использования в API и командах (kubectl get appcaches). Обычно это kind в нижнем регистре с добавлением 's'.
    • singular: Имя в единственном числе (опционально, для псевдонимов).
    • shortNames: Короткие алиасы для kubectl (например, ac).
  • spec.scope: Определяет область видимости ресурса. Namespaced — ресурс создается внутри namespace (как Pod). Cluster — глобальный ресурс для всего кластера (как Node). Выбор зависит от логики вашего ресурса.
  • spec.versions: Список версий API, которые поддерживает этот CRD. Каждая версия содержит:
    • name: Например, v1alpha1, v1beta1, v1.
    • served: true — API-сервер обслуживает запросы к этой версии.
    • storage: true только для одной версии — данные в etcd хранятся в этом формате.
    • schema: Блок openAPIV3Schema для валидации структуры Custom Resource.

Пример: создаем CRD 'AppCache' для управления конфигурацией кэша

Рассмотрим полный рабочий пример CRD для управления конфигурацией кэша приложения.

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  # Имя CRD формируется как plural.group
  name: appcaches.cache.example.com
spec:
  # Группа API
  group: cache.example.com
  names:
    # Kind, который будет использоваться в манифестах Custom Resources
    kind: AppCache
    # Множественное число для команд (kubectl get appcaches)
    plural: appcaches
    singular: appcache
    # Короткая alias-команда (kubectl get ac)
    shortNames:
    - ac
  # Ресурс создается внутри namespace
  scope: Namespaced
  versions:
    - name: v1
      served: true  # Эта версия обслуживается API
      storage: true # Данные хранятся в этой версии
      schema:
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object
              properties:
                # Поле spec.backend - строка с выбором из списка
                backend:
                  type: string
                  enum: [redis, memcached, local]
                # Поле spec.sizeInMB - целое число с минимальным значением
                sizeInMB:
                  type: integer
                  minimum: 10
                # Поле spec.ttlSeconds - целое число
                ttlSeconds:
                  type: integer
              required: # Обязательные поля в spec
                - backend
                - sizeInMB
            status: # Поле status заполняется контроллером
              type: object
              properties:
                conditions:
                  type: array
                  items:
                    type: object
                lastSynced:
                  type: string
                  format: date-time

Чтобы применить этот CRD в кластере, сохраните манифест в файл appcache-crd.yaml и выполните команду:

kubectl apply -f appcache-crd.yaml

Убедитесь, что CRD создан успешно:

kubectl get crd appcaches.cache.example.com
# NAME                          CREATED AT
# appcaches.cache.example.com   2026-04-01T10:00:00Z

Создание и управление Custom Resources: работаем с данными через kubectl

После регистрации CRD в кластере вы можете создавать экземпляры Custom Resources (CR). Создадим ресурс AppCache на основе нашей схемы.

apiVersion: cache.example.com/v1
kind: AppCache
metadata:
  name: frontend-cache
  namespace: default
spec:
  backend: redis
  sizeInMB: 512
  ttlSeconds: 3600

Примените манифест: kubectl apply -f frontend-cache.yaml. Теперь вы можете управлять этим ресурсом через стандартные команды kubectl:

  • kubectl get appcaches или kubectl get ac — список всех AppCache.
  • kubectl describe ac frontend-cache — детальная информация, включая статус.
  • kubectl edit ac frontend-cache — редактирование ресурса прямо в кластере.
  • kubectl delete ac frontend-cache — удаление ресурса.

Как kubectl использует схему CRD для валидации ваших данных

Одно из ключевых преимуществ CRD — встроенная валидация. API-сервер проверяет YAML Custom Resource на соответствие OpenAPI-схеме до того, как принять его. Например, если в манифесте указать строку вместо числа для sizeInMB:

spec:
  sizeInMB: "large" # ОШИБКА: ожидается integer

Команда kubectl apply завершится с ошибкой:

The CustomResourceDefinition "appcaches.cache.example.com" is invalid:
spec.sizeInMB: Invalid value: "string": spec.sizeInMB in body must be of type integer

Это предотвращает попадание некорректных конфигураций в кластер и экономит время на отладке. Валидация обязательных полей (required), типов данных и даже пользовательских правил (через enum или pattern) работает «из коробки».

Типичные ошибки при работе с CRD и как их избежать

Даже с готовыми примерами можно столкнуться с проблемами. Вот список частых ошибок и способы их диагностики.

  1. Ошибки синтаксиса OpenAPI схемы.
    • Симптом: kubectl apply для CRD завершается с ошибкой валидации схемы.
    • Причина: Неправильно указанный тип (string вместо integer), опечатка в имени поля в required.
    • Решение: Воспользуйтесь онлайн-валидатором JSON Schema или проверьте манифест на соответствие документации Kubernetes.
  2. Проблемы с версионированием.
    • Симптом: Нельзя создать Custom Resource, хотя CRD существует.
    • Причина: В CRD не указана версия served: true или в YAML Custom Resource указана несуществующая версия.
    • Решение: Убедитесь, что в spec.versions CRD есть версия с served: true, а в Custom Resource в apiVersion указана именно она (например, cache.example.com/v1).
  3. Конфликты имен.
    • Симптом: Невозможно создать CRD с ошибкой already exists.
    • Причина: CRD с таким же <plural>.<group> уже зарегистрирован в кластере.
    • Решение: Проверьте существующие CRD: kubectl get crd. Используйте уникальное имя группы.
  4. Отсутствие прав RBAC.
    • Симптом: Ошибка Forbidden при создании CRD или Custom Resource.
    • Причина: У пользователя или ServiceAccount нет соответствующих разрешений в ClusterRole.
    • Решение: Убедитесь, что Role/ClusterRole включает права на ресурсы customresourcedefinitions (для CRD) или appcaches (для CR).

Диагностика проблем: как читать ошибки API-сервера и kubectl

Если CRD создан, но Custom Resources не работают, начните диагностику с проверки статуса CRD:

kubectl describe crd appcaches.cache.example.com

В выводе обратите внимание на секцию Status.Conditions. Убедитесь, что есть условие Type: Established со статусом True. Пока CRD не перешел в статус Established, API-сервер не будет обрабатывать запросы к этому ресурсу.

Для глубокой диагностики можно изучить логи kube-apiserver:

kubectl logs -n kube-system deployment/kube-apiserver | grep -A5 -B5 "appcaches.cache.example.com"

Это поможет выявить проблемы с обработкой схемы или внутренние ошибки API.

CRD в 2026 году: актуальные практики и сценарии применения

Подходы к работе с CRD эволюционируют. В 2026 году актуальны следующие лучшие практики:

  • Структурная схема (Structural Schema): Всегда определяйте openAPIV3Schema. Это не только валидация, но и гарантия совместимости будущих версий Kubernetes.
  • Вебхуки для сложной логики: Для валидации, которая не укладывается в статическую схему (например, «поле A должно быть больше поля B»), используйте Admission Webhooks. Это позволяет реализовать любую бизнес-логику проверки.
  • Стратегия версионирования: Придерживайтесь принципа «одна хранимая версия» (storage: true только для одной версии). Переход между версиями (например, с v1beta1 на v1) планируйте с использованием конверсионных вебхуков для бесшовного преобразования данных.

Практические сценарии применения CRD для DevOps:

  1. Автоматизация Stateful-приложений: CRD для описания конфигурации кластеров баз данных (количество реплик, версия, параметры тюнинга). Контроллер на основе этих CR создает StatefulSet, ConfigMap и Service.
  2. Доменные сетевые политики: CRD типа MicroserviceNetworkPolicy, где в spec описываются правила взаимодействия между микросервисами по их логическим именам. Контроллер генерирует стандартные NetworkPolicy Kubernetes.
  3. Ресурсы мониторинга и бэкапа: CRD для декларативного задания правил бэкапа определенного PVC или порогов оповещений для кастомных метрик приложения.

От CRD к Kubernetes Operators: следующий шаг в автоматизации

CRD — это только половина уравнения. Сам по себе Custom Resource — это пассивные данные. Чтобы автоматизировать реакцию на их создание или изменение, нужен контроллер. Kubernetes Operator — это паттерн, который объединяет CRD (определение желаемого состояния) и контроллер (логику приведения системы к этому состоянию).

Контроллер Operator'а в бесконечном цикле наблюдает за Custom Resources определенного типа, сравнивает их spec с реальным состоянием кластера и выполняет действия для устранения расхождений. Например, Operator для базы данных на основе CR DatabaseCluster может автоматически создавать PersistentVolumeClaims, настраивать репликацию, управлять резервным копированием и выполнять обновления.

Таким образом, грамотно спроектированный CRD — это первый и ключевой шаг к построению полноценного Operator, который переносит операционные знания (как управлять сложным приложением) в код, работающий внутри кластера. Если вы хотите глубже погрузиться в основы контейнеризации, которые лежат в основе Kubernetes и Operator'ов, рекомендуем ознакомиться с нашим практическим руководством по Docker для системных администраторов и DevOps.

Поделиться:
Сохранить гайд? В закладки браузера