Существует момент, который переживает каждый основатель. Вы только что закрыли первый раунд финансирования, ваш продукт набирает обороты, и кто-то в канале Slack упоминает, что вам «вероятно, стоит задуматься о Kubernetes». Ваш CTO задумчиво кивает. Все начинают искать учебники по Kubernetes в полночь. К следующему утру вы убеждаете себя, что Kubernetes — неизбежная часть вашего пути к статусу единорога с миллиардной оценкой.

Вот неудобная правда: вы, вероятно, совершаете ужасную ошибку.

Я здесь не для того, чтобы критиковать Kubernetes. Это инженерное чудо. Это отраслевой стандарт по уважительной причине. Такие компании, как Spotify, OpenAI и бесчисленное множество других предприятий, масштабируют свои услуги на тысячах машин с помощью Kubernetes. Но вот в чём дело — вы не Spotify. Вы стартап. И у вас нет проблемы с масштабированием, которую решает Kubernetes; у вас просто нет такой проблемы.

Ловушка Kubernetes

Позвольте мне описать, как это обычно происходит в стартапах. Вы запускаете несколько сервисов на простой инфраструктуре. Может быть, вы используете Docker Compose локально и развёртываете на пару инстансов AWS. Бизнес идёт хорошо. Трафик растёт. Где-то через шесть или двенадцать месяцев подкрадывается тревога. А что, если трафик вдруг увеличится в 10 раз? А что, если нам нужно будет развернуть несколько инстансов? Что, если… что, если… что, если?

На сцену выходит Kubernetes.

Kubernetes обещает автоматическое масштабирование, самовосстановление, декларативную инфраструктуру, независимость от поставщиков и все другие замечательные вещи, о которых вы читали в публикациях на Medium. Звучит идеально. Звучит именно так, как вам нужно. Поэтому вы выделяете двух разработчиков для «модернизации инфраструктуры». Следующие три месяца вы пишете YAML-файлы, боретесь с сетью, отлаживаете проблемы с разрешением DNS для пода в 2 часа ночи и постепенно осознаёте, что Kubernetes — это не просто оркестрация контейнеров, это полное изменение образа жизни.

Вишенка на торте? Ваш трафик не увеличился в 10 раз. Вы по-прежнему обрабатываете столько же запросов, сколько и шесть месяцев назад. Но теперь у вас есть требования к знаниям Kubernetes в вакансиях, DevOps-специалист, чья работа заключается в управлении Kubernetes, и вы тратите примерно в четыре раза больше денег на инфраструктуру, потому что у вас минимальный жизнеспособный производственный кластер, требующий постоянного присмотра.

Это то, что я называю преждевременной оптимизацией инфраструктуры. Это эквивалент преждевременной оптимизации в коде — корень всего зла.

Реальность трафика стартапов

Позвольте мне поделиться тем, о чём большинство успешных стартапов не говорят: большинство из них никогда не достигают масштаба, при котором Kubernetes становится необходим. Исследование 2019 года показало, что примерно 90% стартапов, которые терпят неудачу, делают это из-за отсутствия спроса, а не из-за проблем с масштабируемостью. Ваша инфраструктура не убивает ваш стартап. Отсутствие клиентов убивает ваш стартап.

Подумайте, что на самом деле важно, когда вы пытаетесь найти соответствие продукта и рынка:

  • Выпуск функций (а не управление оркестрацией контейнеров).
  • Понимание поведения пользователей (а не отладка сети Kubernetes).
  • Итерация продукта (а не посещение конференций SRE).
  • Снижение затрат (а не оплата кластера Kubernetes, работающего на 5% мощности).

Инфраструктура, которая вам нужна на этом этапе, должна не мешать. Она должна решать скучные операционные задачи, чтобы ваши инженеры могли сосредоточиться на создании действительно важных вещей. Вам нужны управляемые сервисы, а не инфраструктура, которой вы должны управлять.

Скрытые затраты, о которых никто не говорит

Вот о чём вас не предупреждают в маркетинговых материалах Kubernetes: истинные затраты на внедрение.

Время разработчиков: каждый инженер, который работает с вашей инфраструктурой, должен знать Kubernetes. Это не бесплатно. Это месяцы времени на обучение новых сотрудников. Это сеансы отладки, которые занимают в три раза больше времени, потому что вы пытаетесь понять, в вашем ли коде проблема, в конфигурации Docker или в политике сети Kubernetes.

Операционные затраты: кто-то должен управлять вашим кластером Kubernetes. Кто-то должен устанавливать патчи безопасности, обновлять версии Kubernetes, управлять реестром контейнеров, настраивать мониторинг, реализовывать надлежащий RBAC, управлять постоянными томами и справляться с неизбежными инцидентами в 3 часа ночи, когда падает управляющая плоскость кластера.

Ментальная сложность: у Kubernetes кривая обучения, которая больше похожа не на кривую, а на обрыв. Вы не просто учите оркестрацию контейнеров — вы учите сервисы, ингрессы, деплойменты, стейтефулсеты, DaemonSets, операторов, определения пользовательских ресурсов и около сорока других концепций, которые взаимодействуют неочевидным образом.

Увеличение затрат: теперь вы платите за ресурсы по-другому. С традиционными виртуальными машинами вы могли бы запустить три инстанса, которые стоили бы вам 50 долларов в месяц каждый. С Kubernetes вам нужен минимально жизнеспособный кластер — обычно не менее трёх узлов для высокой доступности. Вы смотрите на 300–500 долларов в месяц минимум, прежде чем даже развернуть первое приложение. И вот забавная часть: ваша инфраструктура Kubernetes не очень хорошо справляется с эффективным управлением всплесками трафика, потому что вы обязуетесь запускать эти минимальные узлы, даже когда они в основном бездействуют.

Забытая золотая середина

О чём никто не говорит, так это о том, что существует огромная золотая середина между «я запускаю всё на одном сервере» и «мне нужен кластер Kubernetes». Именно здесь 95% стартапов должны находиться в первые несколько лет.

Cloud Run, AWS Lambda, Google App Engine, Azure Container Apps — эти бессерверные и похожие на бессерверные платформы — то, на чём должны работать стартапы. Вы развёртываете контейнер. Платформа управляет масштабированием, балансировкой нагрузки, проверкой работоспособности и развёртыванием. Вы платите за то, что используете. Вы не управляете кластером. Ваши разработчики тратят время на создание продуктов, а не на устранение неполадок в YAML.

Позвольте мне привести конкретный пример. Я работал с стартапом, который обрабатывал около 50 запросов в секунду с предсказуемыми шаблонами трафика. Они были на Kubernetes, и это стоило им примерно 800 долларов в месяц на инфраструктуру плюс эквивалент 0,5 FTE на работу DevOps. Мы переместили их в Google Cloud Run с некоторыми управляемыми базами данных и кэшированием Redis. Те же производительность и надёжность, 200 долларов в месяц на инфраструктуру, и вдруг DevOps-специалист может сосредоточиться на других вещах.

Прелесть в том, что если им в конечном итоге понадобится Kubernetes — действительно понадобится, а не гипотетически — они смогут сделать этот шаг. В отличие от проприетарных решений Platform-as-a-Service, которые вас запирают, Cloud Run использует стандартные контейнеры. Ваш путь миграции на Kubernetes будет плавным.

Давайте поговорим об архитектуре

Вот как выглядит типичная инфраструктура стартапа до ошибки с Kubernetes:

graph TB Client["Пользователи/Клиенты"] LB["Облачный балансировщик нагрузки"] App1["Контейнер приложения\n(Cloud Run)"] App2["Контейнер приложения\n(Cloud Run)"] Cache["Кэш Redis\n(Управляемый)"] DB["PostgreSQL\n(Управляемый)"] Queue["Очередь сообщений\n(Управляемый)"] Workers["Рабочие\n(Cloud Run)"] Client -->|HTTPS| LB LB -->|Распределяет трафик| App1 LB -->|Распределяет трафик| App2 App1 -->|Чтения/Записи| DB App1 -->|Запросы к кэшу| Cache App1 -->|Публикует задания| Queue App2 -->|Чтения/Записи| DB App2 -->|Запросы к кэшу| Cache Workers -->|Потребляет задания| Queue Workers -->|Чтения/Записи| DB

Заметьте, чего не хватает? Нет кластера Kubernetes. Нет управления узлами. Нет конфигурации балансировки нагрузки между подами. Нет обнаружения сервисов. Все эти проблемы решает платформа.

Ваша команда по инфраструктуре состоит из: никого. Ваша инфраструктура определена в вашем репозитории infrastructure-as-code примерно в 50 строках Terraform. Новым инженерам не нужно изучать Kubernetes. Им просто нужно знать, как писать код, который может работать в контейнере, что они, вероятно, уже знают.

Практический пример

Позвольте мне показать вам, как это выглядит на самом деле в коде. Вот минимальная настройка для стартапа с использованием Terraform и Google Cloud Run:

# main.tf
terraform {
required_providers {
google = {
source = "hashicorp/google"
version = "~> 5.0"
}
}
}
provider "google" {
project = var.gcp_project
region = var.gcp_region
}
resource "google_cloud_run_service" "api" {
name = "startup-api"
location = var.gcp_region
project = var.gcp_project
launch_stage = "GA"
template {
spec {
containers {
image = "${var.gcp_region}-docker.pkg.dev/${var.gcp_project}/startup/api:${var.image_tag}"
env {
name = "DATABASE_URL"
value = google_cloud_sql_instances.postgres.connection_name
}
env {
name = "REDIS_URL