Деплой и инфра
K8s objects: соберите самовосстанавливающийся сервис без простоя
Читать про reconciliation и readiness probe — не то же, что видеть, как раскат остаётся зелёным, пока за ним прогревается намеренно медленное приложение. Соберите реальный сервис, отправьте его в локальный кластер с правильными объектами и докажите — захваченным выводом — что он самовосстанавливается при потере узла и катит новый образ, не уронив ни одного запроса.
Превратите ментальную модель юнита в работающий набор манифестов: Deployment с правильными probes, Service, привязанный по label selector, вынесенный config через ConfigMap/Secret и грамотно подобранные requests и limits — затем продемонстрируйте самовосстановление и безошибочные раскаты под нагрузкой с доказательствами на каждом шаге.
Развернуть намеренно медленно прогревающийся HTTP-сервис (~20-30с старта) в локальном кластере Kubernetes (kind, minikube или k3d), используя только декларативные манифесты, и доказать, что он самовосстанавливается после потери пода и катит новый образ с нулём упавших запросов под устойчивой нагрузкой.
- Все ресурсы созданы из декларативного YAML через kubectl apply -f — без kubectl run, без императивных правок. Манифесты закоммичены.
- Захваченный раскат под нагрузкой с 0 упавших запросов, плюс тот же нагрузочный тест с удалённым readiness probe, показывающий ненулевые 5xx — доказывая, что именно проба гейтит трафик.
- Вывод kubectl get endpoints, показывающий, что Service отслеживает ровно подходящие поды, и демонстрация того, что масштабирование Deployment обновляет список endpoints автоматически.
- Доказательство самовосстановления: удалённый/вытесненный под, пересозданный ReplicaSet обратно до desired count, с захваченным событием контроллера или разницей в возрасте пода.
- Короткий разбор: в какой класс QoS попадает под и почему, что происходит на лимите CPU против лимита памяти и как аннотация с хешем ConfigMap форсирует раскат при изменении config.
- Добавьте PodDisruptionBudget и многоузловой kind-кластер, затем drain узла и покажите, что раскат/вытеснение уважает minAvailable, пока Service продолжает обслуживать.
- Добавьте Ingress перед ClusterIP Service (ingress-nginx) и маршрутизируйте по host/path, чтобы одна внешняя точка входа фронтила ворклоад вместо LoadBalancer на каждый Service.
- Намеренно вызовите и задокументируйте CrashLoopBackOff и OOMKill (слишком низкий лимит памяти), прочитайте причину выхода из kubectl describe и исправьте каждый, покрутив правильную ручку.
- Добавьте второй Deployment, чьи поды случайно делят label selector Service, понаблюдайте смешение трафика в endpoints, затем исправьте более специфичным селектором — делая различие владения и выбора конкретным.
Это цикл, который вы гоняете для каждого реального сервиса: объявите объекты в YAML, дайте контроллерам reconcile и самовосстанавливаться, гейтите трафик readiness probe (а медленный старт покройте startup), привяжите Service по метке без жёстких IP, вынесите config и форсируйте раскаты, хешируя его в аннотацию, и ограничьте под requests и limits, зная, что CPU троттлится, а память даёт OOMKill. Сделав это раз на игрушечном медленно прогревающемся сервисе, вы сделаете ревью продакшен-манифеста рефлекторным — вы заметите отсутствующий readiness probe и пропущенный лимит памяти с первого взгляда.