Модуль 32. Kubernetes API и автоматизация
Цель: сделать так, чтобы любые изменения в кластере были прозрачны, воспроизводимы и обратимы — от разовой операцией kubectl до собственных контроллеров и IaC.
Результат:
- Понимание модели API (ресурсы, версии, CRD, watch/листинг, оптимистичная конкуренция).
- Набор приёмов kubectl power-user (server-side apply, dry-run, diff, jsonpath, плагins).
- Каркас для кода на Go (client-go/controller-runtime) и Python (kubernetes-client/kubernetes-asyncio).
- Роли Terraform (инфраструктура/Helm/Kubernetes provider) и Ansible (сценарное управление и day-2).
- Паттерны автоматизации: GitOps → контроллеры → плейбуки/скрипты; безопасность, тесты и анти-паттерны.
Ментальная модель Kubernetes API
- Ресурсы: Pods, Deployments, StatefulSets, ... + CRD (расширения от операторов).
- Версии: v1, apps/v1, batch/v1, у CRD — свои group/version/kind.
-
Семантика:
- List/Watch: API отдаёт снимок состояния + поток событий (add/update/delete).
- Optimistic concurrency: поля metadata.resourceVersion/generation защищают от гонок.
- Finalizers: «крючки» на удаление, чтобы корректно прибрать внешние ресурсы.
- Admission/Policies: запросы проходят через Validating/Mutating Webhook’и (Kyverno/Gatekeeper и т. п.). Любая автоматизация должна уметь объяснить своим манифестам эти проверки (иначе — Denied).
kubectl: быстрые и безопасные практики
База, которая экономит часы
- Контексты и алиасы: kubectl config use-context, kubens/kubectx (через krew).
- Только декларативно: kubectl apply --server-side -f ... (SSA — сервер ведёт «владение полями», меньше конфликтов).
-
Перед выкладкой:
- --dry-run=server — прогон через admission/валидации,
- kubectl diff -f — покажет, что именно изменится.
- Поиск и выборки: label/field selectors (-l team=bi, --field-selector=status.phase=Pending), -o jsonpath=... с jq.
- Съёмка состояния: kubectl get ... -o yaml > artifact/… — сохраняйте как артефакт в PR.
Анти-паттерны
- «В проде поправлю kubectl edit» — мимо GitOps.
- apply больших деревьев «вслепую» — без dry-run/diff.
- Хранить kubeconfig в открытом виде — только через секрет-хранилище.
Программирование под API: Go vs Python
Когда нужен код, а не манифест
- Событийная логика (реакция на изменения), согласование внешних систем (DNS, облака, ACL), reconcile-циклы («контроллеры»).
- Массовая миграция объектов с проверками, генерация ресурсов «по каталогу».
Go / client-go (рекомендуем для контроллеров)
- Плюсы: скорость, экосистема, controller-runtime (информеры, кэш, очереди, лидер-элекция).
- Паттерн: Reconciler наблюдает за ресурсом → приводит фактическое состояние к желаемому, обрабатывает idempotent.
Мини-эскиз (идея без деталей):
// reconcile(obj) -> ensure child resources exist; update Status; requeue on transient errors // используйте informer cache, ownerReferences, finalizers, rate-limiter в workqueue
Практические акценты:
- Informer/Lister вместо «голых» list/watch (кэш снижает нагрузку на apiserver).
- OwnerReferences + Garbage Collector — автоматическая уборка дочерних ресурсов.
- LeaderElection — чтобы не бегал сразу «два контроллера».
Python / kubernetes-client
- Хорош для утилит/скриптов, миграций, glue-кода; для контроллеров — возможно, но прод-паттерн чаще на Go.
- Плюсы: быстро «склеить» с BI-стеком (dbt/Airflow/каталоги), море библиотек.
- Вариант kubernetes-asyncio — если нужен неблокирующий watch.
Крошечные фрагменты (ориентиры):
Python: список подов с label-фильтром
from kubernetes import client, config
config.load_kube_config() # или load_incluster_config()
v1 = client.CoreV1Api()
pods = v1.list_namespaced_pod("bi", label_selector="app=superset").items
print([p.metadata.name for p in pods])
Server-side apply (Python)
from kubernetes import client, config config.load_kube_config() api = client.AppsV1Api() dep = client.V1Deployment( # ... заполняем объект ... ) api.patch_namespaced_deployment( name="svc", namespace="bi", body=dep, field_manager="automation", force=True) # SSA
Подводные камни:
- Уважайте rate-limits API (batch прогоны — с паузами/экспоненциальным backoff).
- Обрабатывайте 410 Gone (устарела resourceVersion) — переподключать watch.
- Не храните секреты в коде/логах (используйте SA + RBAC минимум).
Terraform в экосистеме k8s
Где Terraform силён
- Инфраструктура кластера (облако, сети, узлы, storage).
- Деплой Helm-чартов и Kubernetes-ресурсов, если это «каркас платформы» (Ingress-контроллер, оператор, Argo CD).
- Автосоздание Namespace/Quota/LimitRange/NetworkPolicy по конвенциям.
Важные практики
- Разделите ответственность: Terraform — инфраструктура и «скелет»; приложения — через GitOps (Argo/Flux).
- State: удалённый бекенд + блокировка (S3+Dynamo/Consul/GCS); слежение за секретами в tfstate (mask/префиксы).
- Кластер-дрейф: не мешайте Terraform и GitOps управлять одним объектом. Вводите labels/annotations «owner» и охват каждой системы.
Фрагменты (идея):
# helm_release для оператора
resource "helm_release" "nginx" {
name = "ingress-nginx"
repository = "https://kubernetes.github.io/ingress-nginx"
chart = "ingress-nginx"
version = "x.y.z"
namespace = "ingress"
}
# kubernetes_namespace для командного ns
resource "kubernetes_namespace" "team_bi" {
metadata { name = "team-bi" }
}
Анти-паттерн: «снести и поставить заново» (terraform destroy) для прод-ресурсов c PV — высокий риск потери данных.
Ansible: сценарии и day-2 операции
Где уместен:
- bootstrap/upgrade кластеров на kubeadm/裸вм, ротация сертификатов.
- Операционные плейбуки: cordon/drain/uncordon нод, перемещение воркеров, точечные патчи, сбор логов.
- k8s-модуль (коллекции kubernetes.core, community.kubernetes) — применять манифесты, читать объекты, ждать условий.
Скетч:
- hosts: masters
tasks:
- name: Cordon node
command: kubectl cordon {{ inventory_hostname }}
- name: Drain (без прерывания PDB)
command: kubectl drain {{ inventory_hostname }} --ignore-daemonsets --delete-emptydir-data --disable-eviction
Практика:
- Все playbooks — идемпотентны, с check-mode.
- Учет PDB, приоритетов, окон изменений.
- Секреты — через Ansible Vault или внешнее хранилище.
Как «складывать» автоматизацию в систему
- GitOps первичен для приложений и политик.
- Terraform — подложка/infrastructure-as-code и «скелет» кластера.
- Контроллеры (Go) — всё, что должно жить «рядом с событиями кластера» и самоисцеляться.
- Ansible/Python — аккуратные «швейцарские ножи» для day-2, миграций, массовых правок.
- Политики (Kyverno/Gatekeeper) — «ворота» качества для любого источника изменений.
-
Тесты:
- локально в kind/k3d;
- для контроллеров — envtest/fake-client;
- для Terraform — Terratest/plan-политики;
- линтеры: kubeconform, helm lint, OPA/Conftest.
Риски и анти-паттерны
|
Риск |
Проявление |
Как избегать |
|---|---|---|
|
Двойное владение ресурсом |
Terraform и Argo меняют один объект |
Чётко разделить «зоны ответственности», label owner |
|
Imperative правки в проде |
Drift с Git, внезапные регрессы |
Только через PR/GitOps; break-glass — задокументирован и краток |
|
Потеря данных с IaC |
destroy/prune снёс PV/CR с данными |
Retain для критичных PV, защитные правила, план-ревью |
|
Непойманные ошибки API |
Скрипт молча «проскочил» deny |
Всегда --dry-run=server, дифф, алерты на отказ admission |
|
Watch/Rate-limit шторм |
Случайно DDoS’им apiserver |
Информеры/кэш, экспоненциальный backoff, лимит параллелизма |
|
Конфликт SSA-владения |
Ошибки «field manager conflict» |
Один менеджер на ресурс/поле, не смешивать разные источники |
|
Утечки секретов |
kubeconfig/tokens в репо/логах |
Secret-хранилище, короткие токены, SA+RBAC минимум |
|
Версионный снос |
CRD/апи удалили — «падение» пайплайна |
Матрица совместимости, прогон --dry-run=server на Staging |
Практика (лабораторка 1–2 дня)
- kubectl-гигиена: настроить контексты, krew-плагины (ctx, ns, neat, tree), научиться diff/--dry-run=server.
- SSA-поток: перевести один сервис на server-side apply, зафиксировать field-manager, решить конфликт.
- Python-утилита: пройти по всем NetworkPolicy и добавить метку compliance=checked (через SSA).
- Controller-скелет (Go): CR «TenantNamespace» → reconcile создаёт Namespace+Quota+LimitRange, выставляет ownerRef.
- Terraform + Helm: через helm_release поставить Ingress-контроллер, kubernetes_namespace завести ns для команды; остальное — через Argo.
- Ansible day-2: playbook «cordon→drain→upgrade kubelet→uncordon» с проверками PDB.
- Политики: Kyverno «запрет :latest» + проверка на Staging --dry-run=server.
Чек-лист «готово к продакшену»
- Все изменения через Git (GitOps/PR), break-glass — редкий и оформленный процесс.
- kubectl apply --server-side, dry-run=server, diff — обязательны к применению.
- Контроллеры (если есть) с LeaderElection, rate-limit очередью, ownerRefs/finalizers, метриками.
- Terraform — только «каркас» и облако; не управляет тем же, что и Argo/Flux. State — защищён, lock — включён.
- Ansible-плейбуки идемпотентны и учитывают PDB/приоритеты.
- Секреты — через Vault/ESO/CSI; SA+RBAC минимум; kubeconfig не хранится в явном виде.
- Тестовый контур (kind/k3d), линтеры манифестов, план-ревью в CI.
- Документы: runbook’и «конфликт SSA», «deny admission», «rollback CRD/версия API».
Вопрос-ответ
В: Что выбрать для приложений: Terraform, kubectl, Helm или GitOps?
О: Для приложений — GitOps (Argo/Flux) + Helm/Kustomize. Terraform — для инфры и платформенных компонентов. kubectl — инструмент локальной проверки/расследований, а не «канал прод-изменений».
В: Когда писать свой контроллер, а не скрипт?
О: Когда логика событийная и постоянная (нужно «следить и приводить в порядок»). Скрипт — разовая миграция. Контроллер — долгоживущий reconcile.
В: Go или Python для автоматизации?
О: Контроллеры — Go (controller-runtime). Утилиты, glue с BI-стеком — часто Python. Для Python-контроллеров используйте kubernetes-asyncio, но прод-шаблон всё-таки Go.
В: Как не конфликтовать между SSA и Helm?
О: Либо всё управляет Helm (и GitOps держит values), либо SSA — но не одновременно над одним полем. Включайте fieldManager, следите за «владением» полей.
В: Чем отличается --dry-run=client и --dry-run=server?
О: Client — только локальный синтаксис. Server — проходит admission/валидации кластера (им и пользуемся).
В: Можно ли Terraform’ом управлять CRD-ресурсами операторов?
О: Можно, но лучше — через Helm/Argo: CRD часто эволюционируют, и GitOps лучше справляется с порядком CRD→CR и обновлениями.
В: Как работать с несколькими кластерами одновременно?
О: Мультикластер — раздельные контексты/бэкенды стейта, метки cluster=<id>, GitOps разделяет каталоги/приложения. Не смешивайте объекты из разных кластеров в одном «источнике правды».
В: Как тестировать контроллеры?
О: envtest (поднимает API без «живого» кластера), fake-client для unit-тестов; e2e — в kind с минимальными фикстурами.
Kubernetes API даёт единый «язык» для людей и машин. kubectl — для проверки и отладки, GitOps — для жизненного цикла приложений, Terraform — для инфраструктуры, Ansible — для управляемых сценариев, контроллеры — для «живых» правил и самоисцеления. Соберите это в систему, добавьте проверки/политики и тесты — и автоматизация перестанет быть «набором скриптов», а станет надёжным производственным конвейером.



