DevOpsCI/CDKubernetesInfrastructureSecurity
Почему ваш CI/CD выглядит правильно, но всё равно ломается по пятницам: 3 скрытые ошибки Kubernetes
Три реальные ошибки конфигурации CI/CD и Kubernetes, которые выглядят нормально, но приводят к инцидентам в production. Практические фиксы с примерами кода для компаний из Молдовы, Румынии и ЕС.
W
WebDirect TeamУ вас настроен CI/CD pipeline. Тесты проходят. Линтеры молчат. Деплой автоматический. И всё равно — в пятницу вечером что-то падает, клиенты пишут, а вы разбираете инцидент вместо ужина. Знакомо? Дело не в том, что у вас «плохой» DevOps. Дело в нескольких неочевидных ошибках конфигурации, которые выглядят нормально на бумаге, но убивают стабильность в production.Если пятница опаснее вторника — у вас системная проблема, а не плохой тайминг. Надёжный pipeline не знает, какой день недели. В этой статье разбираем три реальные ошибки, которые мы встречаем у клиентов из Молдовы, Румынии и ЕС при аудите инфраструктуры — с кодом, объяснением и конкретными фиксами.Ошибка #1 — Resource limits не заданы: ваши поды едят всё подрядКогда разработчик создаёт Kubernetes deployment без
resources.requests и resources.limits, планировщик не знает, сколько ресурсов нужно поду. Он размещает его «куда влезет». При пиковой нагрузке один сервис занимает всю доступную память на ноде — начинается «соседский ад»: другие поды получают OOMKill или throttling без видимой причины. Стоимость ошибки: cascading failure → несколько сервисов недоступны одновременно.Неправильная конфигурация выглядит так: deployment без указания resources, планировщик гадает. Правильный подход — явно задать requests (гарантированный минимум) и limits (максимум разрешённый). Например: 256Mi памяти и 250m CPU как requests, 512Mi памяти и 500m CPU как limits.Практический фикс: запустите kubectl top pods в staging под реальной нагрузкой. Возьмите p95 потребления как requests, p99 + 30% как limits. Настройте LimitRange на namespace — поды без явных limits получат разумные дефолты, не «всё что есть».Ошибка #2 — Деплой без readinessProbe: деплой «успешен», сервис недоступенKubernetes по умолчанию считает под «готовым», как только запустился контейнер. Для простого Hello World — нормально. Для реального приложения, которому нужно 20–60 секунд на инициализацию — катастрофа. RollingUpdate отправляет трафик на новый под раньше, чем тот готов его принять. Пользователи получают ошибки. CI/CD рапортует «деплой успешен» — потому что технически поды запустились. Стоимость ошибки: 2–10 минут downtime при каждом деплое × N деплоев в день.Endpoint /health/ready должен возвращать 200 только когда приложение реально готово: подключено к БД, прогрет кэш, загружены конфиги. livenessProbe проверяет, жив ли процесс, и перезапускает контейнер при необходимости. Типичная ошибка — использовать один и тот же эндпоинт для обоих probe. Это приводит к перезапуску здоровых подов, которые просто медленно инициализируются.Практический фикс: добавьте в CI автоматический rollback — если поды не становятся Ready за N секунд, деплой откатывается. Настройте отдельные probes с подходящими задержками. Большинству приложений полезен initialDelaySeconds в 10–30 секунд перед началом readiness checks.Ошибка #3 — Тег `latest` в production: каждый деплой непредсказуемТег latest — не версия. Это «дай мне что угодно актуальное на момент pull». Каждый раз, когда Kubernetes пересоздаёт под, он может получить другой образ, чем был при последнем деплое. Когда upstream обновит base image и ваша зависимость перестанет работать с новой версией OpenSSL — вы получите production incidentes от кода, который не меняли. Стоимость ошибки: непредсказуемые regressions + security-уязвимости в неконтролируемых base images.Картина ясна: image: myapp:latest — разные поды запускают разный код (опасно). Тег вроде image: myapp:v1.4 можно переписать (рискованно). А image: myapp:1.4.2-abc1234 с Git SHA + semver — воспроизводимо и прослеживаемо (хорошо). Для абсолютной гарантии используйте digest: image: myapp@sha256:a1b2c3... — гарантирует одинаковый образ каждый раз.Практический фикс: в CI pipeline тегируйте образы с Git SHA (TAG=$(git rev-parse --short HEAD)). В deployment.yaml пропишите конкретную версию. Установите imagePullPolicy: IfNotPresent. Настройте политику в Admission Controller или OPA — автоматически отклонять деплои с тегом latest. Займёт час, но навсегда уберёт целый класс инцидентов.Кроме большой тройки: ещё тихие убийцы инфраструктурыВашей инфраструктуре также угрожают: отсутствие PodDisruptionBudget (обновления нод убивают все реплики одновременно), секреты в ConfigMap вместо Kubernetes Secrets (утечка при kubectl describe), нет HorizontalPodAutoscaler (платите за idle ресурсы или падаете при пиковой нагрузке), нет кеширования слоёв Docker в CI (15 минут build вместо 3 минут), отсутствие network policies (любой скомпрометированный под говорит с любым сервисом в кластере).30-минутная диагностика: чеклист проверкиЗапустите команды: kubectl get pods -A -o json | jq '.items[] | select(.spec.containers[].resources.limits == null) | .metadata.name' для поиска подов без resource limits. Проверьте поды без readinessProbe. Ищите образы с тегом :latest с помощью grep ':latest'. Убедитесь: у всех подов есть resources.requests и resources.limits, настроены отдельные readinessProbe и livenessProbe, нигде нет тега latest, настроен PodDisruptionBudget для критичных сервисов, и деплой откатывается если поды не стали Ready за N секунд.FAQ: частые вопросыМожно ли использовать одинаковые значения для requests и limits? Технически да — это даёт QoS-класс Guaranteed. Но если приложение имеет законные пики потребления, оно будет throttled даже при достаточных ресурсах кластера. Используйте разные значения. Как часто пересматривать resource limits? После каждого значительного изменения в приложении и раз в квартал для всей инфраструктуры. Используйте Vertical Pod Autoscaler в режиме recommend для автоматических рекомендаций. Что делать, если legacy-сервис не имеет health endpoint? Используйте exec-probe для проверки через команду внутри контейнера, или tcpSocket-probe для проверки доступности порта. Это лучше, чем ничего. Актуально ли для малого бизнеса в Молдове и Румынии? Да. Эти ошибки критичны даже для кластеров с 3–5 сервисами. Стоимость часа downtime для e-commerce в Молдове или Румынии значительно превышает стоимость правильной настройки с первого раза.ВыводыТри ошибки выше — не экзотика. Мы встречаем их регулярно при аудите инфраструктуры компаний из Молдовы, Румынии и ЕС, независимо от размера команды и стека. Хорошая новость: каждая исправляется за несколько часов. Если вы хотите пройти аудит своей инфраструктуры и CI/CD pipeline — мы в WebDirect проводим бесплатный IT Health Check с конкретным отчётом по вашей системе. Наша команда проанализирует вашу среду и предоставит ясную, честную оценку ситуации — вместе с конкретным планом улучшения.Нужна экспертная помощь?
Наша команда готова помочь вам реализовать стратегии, описанные в наших статьях.
