Что такое API Aggregation Layer и зачем его использовать
Kubernetes предоставляет мощный набор API‑ресурсов, однако в реальных проектах часто возникает необходимость добавить собственные сущности и бизнес‑логики. Вместо создания полностью отдельного кластера или внедрения кастомных контроллеров, можно «подключить» свой API‑сервер к основному kube-apiserver через слой агрегации (API Aggregation Layer). Это позволяет обращаться к пользовательским ресурсам так же, как к штатным объектам (pods, services), использовать единый UI и сохранять единый процесс аутентификации и авторизации.
Архитектурные особенности агрегации
- APIService – объект Kubernetes, описывающий внешний API‑сервер. В нём указываются версии группы, путь к сервису и параметры TLS.
- Aggregated API Server – отдельный процесс, реализующий набор REST‑эндпоинтов, совместимых с
apimachinery. Он регистрирует свои ресурсы вetcdчерезkube-apiserver, но хранит только метаданные; реальное состояние управляется внутри сервера. - Discovery –
kube-apiserverавтоматически добавляет агрегированные группы в список доступных API, поэтому клиенты (kubectl, UI) видят их без дополнительных настроек.
Шаг 1: Создание скелета собственного API‑сервера
Самый простой способ – воспользоваться kubebuilder или operator-sdk. Оба инструмента генерируют проект со встроенной поддержкой controller-runtime, что упрощает работу с клиентом Kubernetes и автоматическую генерацию CRD.
kubebuilder init --domain=example.com --repo=github.com/example/platform-api
kubebuilder create api --group=platform --version=v1 --kind=SyncState
После генерации появятся файлы:
api/v1/syncstate_types.go– определение структуры ресурса.controllers/syncstate_controller.go– контроллер, отвечающий за синхронизацию.
Шаг 2: Реализация логики синхронизации состояния
В типичном сценарии платформа должна поддерживать согласованность между внешней системой (например, CI/CD) и объектами Kubernetes. В контроллере реализуем цикл:
- Чтение внешних данных – HTTP‑клиент к API сторонней системы.
- Сравнение с текущим объектом – проверка полей
SpecиStatus. - Обновление
Status– если статус в кластере устарел, вызываемclient.Status().Update. - Обратная запись – при необходимости отправляем изменения обратно во внешнюю систему.
func (r *SyncStateReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
var ss platformv1.SyncState
if err := r.Get(ctx, req.NamespacedName, &ss); err != nil {
return ctrl.Result{}, client.IgnoreNotFound(err)
}
external, err := fetchExternalState(ss.Spec.ExternalID)
if err != nil {
return ctrl.Result{RequeueAfter: time.Minute}, err
}
if ss.Status.State != external.State {
ss.Status.State = external.State
if err := r.Status().Update(ctx, &ss); err != nil {
return ctrl.Result{}, err
}
}
return ctrl.Result{}, nil
}
Шаг 3: Регистрация API‑сервера в кластере
После сборки Docker‑образа и публикации его в реестр, создаём Deployment и Service:
apiVersion: apps/v1
kind: Deployment
metadata:
name: platform-api
spec:
replicas: 2
selector:
matchLabels:
app: platform-api
template:
metadata:
labels:
app: platform-api
spec:
containers:
- name: api
image: registry.example.com/platform-api:v1.0.0
ports:
- containerPort: 8443
---
apiVersion: v1
kind: Service
metadata:
name: platform-api
spec:
selector:
app: platform-api
ports:
- port: 443
targetPort: 8443
Далее создаём объект APIService:
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
name: v1.platform.example.com
spec:
service:
name: platform-api
namespace: default
group: platform.example.com
version: v1
caBundle: <base64‑encoded‑CA‑cert>
insecureSkipTLSVerify: false
caBundle содержит сертификат, которым подписан TLS‑сервер API. После применения APIService Kubernetes автоматически включит новую группу в эндпоинты kubectl api-resources.
Шаг 4: Настройка RBAC и разрешений
Для доступа к агрегированному API необходимо предоставить права как пользователям, так и сервисным аккаунтам. Пример ClusterRole и ClusterRoleBinding:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: platform-api-reader
rules:
- apiGroups: ["platform.example.com"]
resources: ["syncstates"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: platform-api-read-binding
subjects:
- kind: User
name: alice
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: platform-api-reader
apiGroup: rbac.authorization.k8s.io
Таким образом, пользователь alice сможет просматривать ресурсы SyncState через обычный kubectl.
Лучшие практики при работе с агрегированными API
- Версионирование API – используйте отдельные группы (
v1alpha1,v1beta1,v1) и поддерживайте обратную совместимость. - Неблокирующая обработка – контроллеры должны быстро возвращать результат и использовать
RequeueAfterдля периодических проверок, чтобы не перегружатьkube-apiserver. - Тестирование в изоляции – создавайте отдельный namespace и мини‑кластер (
kind), где проверяете регистрациюAPIServiceи работу CRD. - Мониторинг – экспонируйте метрики через Prometheus (
/metricsendpoint) и следите за латентностью запросов к внешним системам.
Потенциальные подводные камни
- TLS‑конфигурация – неправильный
caBundleприводит к тому, чтоkube-apiserverоткажет в соединении с агрегированным сервером. - Конфликт имен – группы и версии должны быть уникальными в кластере; дублирование вызовет ошибки регистрации.
- Синхронные запросы – если API‑сервер обращается к медленному внешнему сервису, это может затормозить
kubectl‑операции, поэтому используйте кэширование или асинхронные задачи. - Обновление CRD – изменения схемы ресурса требуют пересоздания
APIServiceи могут вызвать временный недоступ к новым полям.
Использование API Aggregation Layer открывает путь к построению полностью кастомизированных платформ поверх Kubernetes, позволяя объединить собственные бизнес‑модели с нативными возможностями оркестрации. Правильная архитектура, автоматизированные CI/CD пайплайны и строгие политики безопасности обеспечат стабильную работу расширенного кластера и упростят дальнейшее развитие инфраструктуры.