Облачная инфраструктура Production
Cloud Production — подход к построению и эксплуатации облачной инфраструктуры, рассчитанной на рабочую нагрузку: отказоустойчивость, масштабирование, безопасность, наблюдаемость и контролируемую стоимость.
В production-среде обычно используют управляемые сервисы облачного провайдера. Провайдер обслуживает часть инфраструктурного слоя, а команда отвечает за конфигурацию, данные, права доступа, сетевую архитектуру и приложение.
Пример типовой архитектуры:
Пользователи
|
DNS / CDN / WAF
|
Облачный Load Balancer
|
Managed Kubernetes в нескольких Availability Zones
| |
Managed Database Object Storage
Multi-AZ резервные копииКлючевая идея production-архитектуры — устранять единичные точки отказа и чётко разделять ответственность между облачным провайдером и владельцем системы.
Содержание
- Основные принципы Cloud Production
- Managed Kubernetes
- Amazon EKS
- Google Kubernetes Engine
- Аналоги Managed Kubernetes
- Проектирование production-кластера
- Managed databases
- Высокая доступность баз данных
- Резервное копирование и восстановление
- Load balancers в облаке
- Виды балансировщиков
- Балансировка трафика в Kubernetes
- Multi-AZ-развёртывания
- Отказоустойчивость приложения
- Cost optimization
- Наблюдаемость и эксплуатация
- Безопасность production-инфраструктуры
- Общий пример архитектуры
- Чек-лист перед запуском
Основные принципы Cloud Production
Production-инфраструктура должна продолжать работу при отказе отдельного экземпляра, узла или зоны доступности. Для этого применяются:
- несколько экземпляров приложения;
- размещение компонентов в нескольких Availability Zones;
- автоматическая замена неисправных экземпляров;
- балансировка нагрузки;
- резервное копирование данных;
- мониторинг, централизованные логи и оповещения;
- управление инфраструктурой через код;
- минимально необходимые права доступа;
- контролируемые обновления и возможность отката.
Модель общей ответственности
Облачный провайдер и клиент отвечают за разные уровни системы.
| Область | Обычно отвечает провайдер | Обычно отвечает клиент |
|---|---|---|
| Физический дата-центр | Да | Нет |
| Физические серверы и сеть | Да | Нет |
| Управляемый control plane Kubernetes | Да | Частично: конфигурация и доступ |
| Гостевая ОС виртуальной машины | Нет или частично | Да |
| Конфигурация приложения | Нет | Да |
| IAM и права доступа | Предоставляет механизм | Настраивает клиент |
| Данные и их классификация | Нет | Да |
| Резервное копирование | Предоставляет возможности | Включает и проверяет клиент |
| Шифрование | Предоставляет сервисы | Выбирает и настраивает клиент |
Использование managed-сервиса не означает, что провайдер полностью отвечает за приложение и данные. Например, провайдер может обновлять control plane Kubernetes, но политики RBAC, сетевые правила и безопасность контейнеров остаются ответственностью команды.
Availability Zone и Region
Region — отдельный географический регион облачного провайдера.
Availability Zone, или AZ, — изолированная площадка внутри региона со своей инфраструктурой питания и сети. В одном регионе обычно доступно несколько зон.
Region
├── Availability Zone A
├── Availability Zone B
└── Availability Zone CРазмещение приложения в нескольких AZ защищает от отказа одной зоны. Размещение в нескольких регионах дополнительно защищает от региональных отказов, но значительно усложняет работу с данными, маршрутизацией и согласованностью.
RTO и RPO
Требования к восстановлению удобно описывать двумя показателями:
- RTO, Recovery Time Objective — допустимое время восстановления сервиса;
- RPO, Recovery Point Objective — допустимый объём потерянных данных, обычно выраженный временем.
Пример:
RTO: 30 минут
RPO: 5 минутЭто означает, что сервис должен быть восстановлен не позднее чем через 30 минут, а допустимая потеря данных не должна превышать примерно 5 минут.
Архитектура, частота резервных копий и стоимость системы зависят от требуемых RTO и RPO.
Managed Kubernetes
Managed Kubernetes — Kubernetes-кластер, в котором облачный провайдер управляет control plane полностью или частично.
К распространённым сервисам относятся:
| Облако | Сервис Kubernetes | Managed database | Балансировка |
|---|---|---|---|
| AWS | Amazon EKS | Amazon RDS, Aurora | ELB: ALB, NLB |
| Google Cloud | Google Kubernetes Engine | Cloud SQL, AlloyDB | Cloud Load Balancing |
| Microsoft Azure | Azure Kubernetes Service | Azure SQL, Azure Database for PostgreSQL | Azure Load Balancer, Application Gateway |
| Другие провайдеры | Managed Kubernetes | Управляемые SQL/NoSQL-сервисы | Облачные L4/L7-балансировщики |
Точные названия и возможности зависят от провайдера, но общие архитектурные принципы похожи.
Что обычно управляется провайдером
В managed Kubernetes провайдер обычно берёт на себя:
- запуск и доступность API Server;
- обслуживание
etcd; - работу Scheduler и Controller Manager;
- резервирование компонентов control plane;
- интеграцию control plane с облачной сетью;
- обновление control plane в пределах поддерживаемых версий;
- интеграцию с IAM, логированием и мониторингом.
Пользователь обычно отвечает за:
- worker nodes или serverless-профили;
- Kubernetes-манифесты и Helm-релизы;
- обновление node groups;
- RBAC и сервисные аккаунты;
- сетевые политики;
- requests и limits;
- безопасность контейнеров;
- резервное копирование прикладных данных;
- наблюдаемость и реагирование на инциденты.
Managed control plane и worker nodes
Облачный провайдер
└── Managed control plane
├── API Server
├── etcd
├── Scheduler
└── Controller Manager
Проект клиента
└── Data plane
├── Node group A
├── Node group B
├── Pods
├── Services
└── IngressWorker nodes могут запускаться как:
- обычные виртуальные машины;
- управляемые группы узлов;
- автоматически создаваемые узлы;
- serverless-контейнеры без явного управления виртуальными машинами.
Преимущества Managed Kubernetes
- меньше операций с control plane;
- встроенная интеграция с сетью, IAM и балансировщиками;
- автоматизированные обновления и исправления;
- высокая доступность управляющих компонентов;
- удобное подключение облачных дисков и балансировщиков;
- интеграция с сервисами логирования и мониторинга.
Ограничения
- стоимость control plane, worker nodes, сетевого трафика и дополнительных сервисов;
- зависимость от интеграций конкретного провайдера;
- ограничения на настройку управляющих компонентов;
- необходимость следить за версиями Kubernetes и обновлять node groups;
- сложность диагностики на границе Kubernetes и облачной инфраструктуры.
Amazon EKS
Amazon Elastic Kubernetes Service, или EKS, — управляемый Kubernetes в AWS.
Основные элементы EKS:
- EKS cluster — managed control plane;
- managed node groups — управляемые группы EC2-узлов;
- self-managed nodes — самостоятельно обслуживаемые EC2-узлы;
- Fargate profiles — запуск отдельных Pod без управления EC2-узлами;
- VPC CNI — интеграция Pod с адресным пространством VPC;
- IAM integration — связь AWS IAM с доступом к кластеру и облачным API;
- add-ons — управляемые дополнения, например CoreDNS и сетевой плагин.
Типовая структура EKS
VPC
├── Public subnet, AZ-a
│ └── Load Balancer
├── Public subnet, AZ-b
│ └── Load Balancer
├── Private subnet, AZ-a
│ └── EKS worker nodes
├── Private subnet, AZ-b
│ └── EKS worker nodes
└── Database subnets
└── RDS Multi-AZWorker nodes обычно размещают в приватных подсетях. Внешний трафик принимает публичный балансировщик, а исходящий доступ узлов при необходимости проходит через NAT Gateway или VPC endpoints.
Доступ Pod к AWS API
Не следует передавать постоянные AWS-ключи в Kubernetes Secret, если доступна интеграция сервисного аккаунта с облачной ролью.
Принцип:
Pod
└── Kubernetes ServiceAccount
└── IAM role
└── IAM policy
└── разрешённые AWS APIКаждое приложение получает только необходимые разрешения. Например, приложение для загрузки файлов может получить доступ только к конкретному S3-бакету.
Google Kubernetes Engine
Google Kubernetes Engine, или GKE, — управляемый Kubernetes в Google Cloud.
Основные варианты:
- Standard — больше контроля над конфигурацией узлов и кластера;
- Autopilot — провайдер управляет большей частью data plane, а ресурсы планируются на основании Pod.
Типовые интеграции GKE:
- managed control plane;
- node pools;
- автоматическое масштабирование;
- Workload Identity для доступа Pod к облачным сервисам;
- интеграция с Cloud Load Balancing;
- persistent disks через CSI;
- Cloud Logging и Cloud Monitoring.
Workload Identity
Workload Identity связывает Kubernetes ServiceAccount с облачной учётной записью. Это позволяет Pod получать временные учётные данные без хранения постоянного ключа в контейнере.
Общая схема аналогична другим облакам:
Pod → ServiceAccount → Cloud IAM identity → разрешённый сервисRegional-кластеры
Для production предпочтительнее архитектура, в которой control plane и worker nodes распределены по нескольким зонам региона. Зональный кластер может оказаться более уязвимым к отказу одной зоны.
Аналоги Managed Kubernetes
Несмотря на различия в названиях, управляемые Kubernetes-сервисы обычно предоставляют одинаковые базовые возможности:
| Возможность | Назначение |
|---|---|
| Managed control plane | Управление API Server, etcd и контроллерами |
| Node pools / node groups | Группировка узлов по типу и назначению |
| Cluster autoscaler | Изменение количества узлов |
| Load Balancer integration | Создание облачного балансировщика из Kubernetes |
| Block storage integration | Динамическое выделение дисков через CSI |
| Workload identity | Доступ Pod к облачным API без постоянных ключей |
| Managed add-ons | Обслуживание системных компонентов |
| Observability integration | Передача метрик и логов в облачные сервисы |
При выборе сервиса следует оценивать не только стоимость узлов, но и:
- стоимость control plane;
- стоимость балансировщиков;
- межзонный трафик;
- NAT и исходящий трафик;
- диски и снимки;
- хранение и обработку логов;
- поддержку требуемых версий Kubernetes;
- доступность нужных типов виртуальных машин в регионе.
Проектирование production-кластера
Node pools
Разные типы нагрузок удобно размещать в отдельных группах узлов:
Кластер
├── system node pool
├── application node pool
├── memory-optimized node pool
└── spot/preemptible node poolДля управления размещением применяются:
- labels;
- node selectors;
- node affinity;
- taints и tolerations;
- topology spread constraints.
Пример выбора группы узлов:
apiVersion: apps/v1
kind: Deployment
metadata:
name: reports
spec:
replicas: 2
selector:
matchLabels:
app: reports
template:
metadata:
labels:
app: reports
spec:
nodeSelector:
workload: memory-optimized
containers:
- name: reports
image: registry.example.com/reports:1.4.0
resources:
requests:
cpu: "500m"
memory: "1Gi"
limits:
cpu: "2"
memory: "2Gi"Requests и limits
requests используются Scheduler для размещения Pod и влияют на масштабирование узлов.
limits ограничивают максимальное потребление ресурсов контейнером.
resources:
requests:
cpu: "250m"
memory: "256Mi"
limits:
cpu: "1"
memory: "512Mi"Если requests сильно завышены, узлы используются неэффективно. Если они занижены, на одном узле может оказаться слишком много Pod, что повышает риск нехватки ресурсов.
При превышении memory limit контейнер может быть завершён с причиной OOMKilled. CPU limit обычно приводит к ограничению процессорного времени, а не к завершению контейнера.
Распределение Pod по зонам
topologySpreadConstraints помогают не размещать все реплики в одной зоне:
spec:
replicas: 3
template:
metadata:
labels:
app: api
spec:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: api
containers:
- name: api
image: registry.example.com/api:2.1.0Для защиты от обслуживания узлов применяется PodDisruptionBudget:
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: api
spec:
minAvailable: 2
selector:
matchLabels:
app: apiPodDisruptionBudget ограничивает обровольные прерывания, например при обновлении узлов. Он не гарантирует доступность при аварийном отказе узла или зоны.
Обновление кластера
Безопасный процесс обновления обычно включает:
- проверку совместимости API и дополнений;
- обновление тестового кластера;
- обновление control plane;
- обновление системных add-ons;
- создание новой группы узлов;
- перенос нагрузки на новые узлы;
- удаление старой группы после проверки.
Перед обновлением необходимо проверить устаревшие Kubernetes API, версии Ingress Controller, CSI-драйверов и сетевых плагинов.
Managed databases
Managed database — база данных, для которой облачный провайдер автоматизирует часть административных операций.
Примеры категорий:
| Категория | Примеры технологий | Типичные задачи |
|---|---|---|
| Реляционные БД | PostgreSQL, MySQL, SQL Server | Транзакции, связи, SQL |
| Документные БД | Совместимые с document model | Каталоги, профили, гибкая схема |
| Key-value | Распределённые key-value-хранилища | Сессии, быстрый доступ по ключу |
| In-memory | Redis-совместимые сервисы | Кэш, очереди, rate limiting |
| Data warehouse | Аналитические колоночные системы | BI и аналитика больших объёмов |
Провайдер обычно автоматизирует:
- установку СУБД;
- резервное копирование;
- установку исправлений;
- мониторинг инфраструктурных метрик;
- замену неисправного экземпляра;
- репликацию и failover при соответствующей конфигурации;
- создание снимков;
- шифрование дисков.
Команда по-прежнему отвечает за:
- схему данных;
- запросы и индексы;
- пользователей БД и права;
- параметры подключения;
- классификацию данных;
- проверку восстановления из резервных копий;
- масштабирование с учётом нагрузки;
- безопасную сетевую доступность;
- миграции приложения.
Выбор managed database
При выборе оценивают:
- модель данных;
- требования к транзакциям;
- объём данных;
- профиль чтения и записи;
- допустимую задержку;
- RTO и RPO;
- требования к региону хранения данных;
- поддержку реплик чтения;
- возможности вертикального и горизонтального масштабирования;
- стоимость вычислений, хранения, резервных копий и трафика.
Подключение приложения
База данных обычно размещается в приватных подсетях и не получает публичный адрес.
Application Pod / VM
|
private network
|
Managed Database endpointДоступ ограничивается сетевыми правилами и учётной записью БД. Не следует разрешать подключение ко всем адресам 0.0.0.0/0.
Пример строки подключения через переменные окружения:
env:
- name: DB_HOST
value: postgres.internal.example
- name: DB_PORT
value: "5432"
- name: DB_NAME
value: application
- name: DB_USER
valueFrom:
secretKeyRef:
name: database-credentials
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: database-credentials
key: passwordВ production предпочтительно получать секреты из специализированного secret manager и автоматически ротировать их, если платформа это поддерживает.
Connection pooling
Каждый Pod приложения может создавать несколько подключений к базе. При автоматическом масштабировании общее количество подключений быстро растёт:
20 Pod × 20 соединений = 400 соединенийЧтобы избежать исчерпания лимита, применяются:
- ограничение размера пула в приложении;
- внешний connection pooler;
- управляемый database proxy;
- корректные тайм-ауты;
- закрытие неиспользуемых соединений.
Высокая доступность баз данных
Primary и standby
В Multi-AZ-конфигурации основная база реплицирует данные на резервный экземпляр в другой зоне.
AZ-a AZ-b
Primary database ────────> Standby database
^
|
единый endpointПри отказе primary управляемый сервис переключает endpoint на standby. Конкретное время переключения зависит от сервиса, конфигурации и характера отказа.
Standby и read replica
Эти механизмы решают разные задачи.
| Механизм | Основная цель | Обычно обслуживает чтение |
|---|---|---|
| Multi-AZ standby | Высокая доступность и failover | Не всегда |
| Read replica | Масштабирование чтения | Да |
Read replica может реплицироваться асинхронно, поэтому данные на ней иногда отстают от primary. Это следует учитывать для операций, где требуется немедленно прочитать только что записанные данные.
Вертикальное масштабирование
Вертикальное масштабирование увеличивает ресурсы одного экземпляра:
4 vCPU, 16 GiB → 8 vCPU, 32 GiBЭто простой подход, но у него есть предел. Изменение класса экземпляра также может потребовать перезапуска или failover.
Горизонтальное масштабирование
Для масштабирования чтения применяются read replicas. Горизонтальное масштабирование записи сложнее и может требовать:
- шардирования;
- распределённой базы данных;
- изменения модели данных;
- разделения нагрузки между несколькими хранилищами.
Миграции схемы
Миграции должны быть совместимы с поэтапным обновлением приложения.
Безопасная последовательность:
- добавить новые поля или таблицы без удаления старых;
- развернуть версию приложения, поддерживающую обе схемы;
- перенести или заполнить данные;
- переключить чтение на новую схему;
- удалить старые поля отдельным изменением.
Следует избегать блокирующих изменений больших таблиц в часы пик.
Резервное копирование и восстановление
Резервная копия полезна только в том случае, если из неё можно восстановить данные.
Основные механизмы
- автоматические резервные копии;
- ручные snapshots перед рискованными изменениями;
- Point-in-Time Recovery;
- репликация в другой регион;
- экспорт критичных данных в независимое хранилище.
Point-in-Time Recovery
PITR позволяет восстановить базу на выбранный момент времени в пределах периода хранения журналов.
12:00 — полная резервная копия
12:00–15:30 — журналы изменений
15:30 — требуемая точка восстановленияОбычно восстановление создаёт новый экземпляр базы. После этого приложение необходимо переключить на новый endpoint или перенести нужные данные.
Проверка восстановления
Регулярная проверка должна подтверждать:
- что резервные копии действительно создаются;
- что данные можно восстановить;
- что время восстановления соответствует RTO;
- что потеря данных соответствует RPO;
- что команда знает процедуру переключения приложения;
- что восстановленная база проходит проверку целостности.
Защита резервных копий
Резервные копии должны иметь:
- шифрование;
- отдельные права доступа;
- политику хранения;
- защиту от случайного удаления;
- при необходимости копии в другом аккаунте или регионе.
Load balancers в облаке
Load Balancer принимает входящий трафик и распределяет его между несколькими целевыми экземплярами.
Клиенты
|
Load Balancer
├── Instance / Pod A
├── Instance / Pod B
└── Instance / Pod CОсновные функции:
- распределение нагрузки;
- проверка состояния backend;
- исключение неисправных целей;
- завершение TLS;
- маршрутизация по домену или пути;
- интеграция с автоскейлингом;
- сохранение журналов доступа;
- интеграция с WAF.
Health checks
Балансировщик периодически проверяет backend:
GET /health/readyЕсли проверка не проходит, backend временно исключается из балансировки.
Endpoint проверки должен:
- быстро отвечать;
- возвращать корректный код состояния;
- не выполнять тяжёлые операции;
- отражать готовность экземпляра принимать запросы.
Не следует использовать endpoint, который всегда возвращает 200, даже если приложение потеряло доступ к критической зависимости.
TLS termination
Балансировщик может завершать HTTPS-соединение:
Client -- HTTPS --> Load Balancer -- HTTP/HTTPS --> BackendСертификаты удобно хранить и обновлять через управляемый certificate manager. Для чувствительного трафика можно применять шифрование и между балансировщиком и backend.
Sticky sessions
Sticky sessions направляют клиента на один и тот же backend. Это иногда необходимо для устаревших stateful-приложений, но усложняет масштабирование и failover.
Предпочтительнее хранить состояние вне экземпляра приложения:
- в базе данных;
- в распределённом кэше;
- в объектном хранилище;
- в подписанном токене, если это соответствует модели безопасности.
Виды балансировщиков
Layer 4
L4-балансировщик работает на транспортном уровне и маршрутизирует TCP или UDP-соединения.
Подходит для:
- высокой производительности;
- TCP-сервисов;
- баз данных и нестандартных протоколов;
- сохранения исходных сетевых характеристик, если это поддерживается сервисом.
TCP connection → L4 Load Balancer → BackendLayer 7
L7-балансировщик понимает HTTP и HTTPS и может маршрутизировать запросы по содержимому.
api.example.com → API service
static.example.com → Static service
/admin → Admin serviceВозможности L7:
- маршрутизация по host и path;
- redirect с HTTP на HTTPS;
- TLS termination;
- изменение HTTP-заголовков;
- интеграция с WAF;
- cookie-based stickiness;
- канареечная маршрутизация, если она поддерживается.
Internal и internet-facing
Internet-facing Load Balancer доступен из интернета.
Internal Load Balancer имеет приватный адрес и используется для внутренних сервисов.
Internet → Public LB → Web application
Internal services → Internal LB → Internal APIВнутренние сервисы не следует публиковать наружу без необходимости.
Cross-zone load balancing
Cross-zone-балансировка позволяет распределять трафик между backend в разных AZ. Она улучшает равномерность нагрузки, но может создавать межзонный трафик, которы в некоторых облаках тарифицируется отдельно.
Балансировка трафика в Kubernetes
В managed Kubernetes облачный балансировщик обычно создаётся через Service типа LoadBalancer или через Ingress/Gateway-контроллер.
Service типа LoadBalancer
apiVersion: v1
kind: Service
metadata:
name: api
spec:
type: LoadBalancer
selector:
app: api
ports:
- name: http
port: 80
targetPort: 8080Облачный контроллер создаёт внешний или внутренний балансировщик и направляет трафик к сервису.
Такой подход удобен для отдельного L4-балансировщика, но отдельный балансировщик для каждого сервиса может быть дорогим.
Ingress
Ingress позволяет использовать один L7-балансировщик для нескольких приложений:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: applications
spec:
ingressClassName: cloud-ingress
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api
port:
number: 80
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: frontend
port:
number: 80Для работы Ingress необходим Ingress Controller. В облаке им может быть контроллер, создающий managed load balancer, или отдельный контроллер внутри кластера.
External traffic policy
Для Service типа LoadBalancer параметр externalTrafficPolicy влияет на маршрутизацию внешнего трафика:
spec:
type: LoadBalancer
externalTrafficPolicy: LocalLocal может помочь сохранить исходный IP клиента и избежать дополнительного межузлового перехода, но требует достаточного числа локальных endpoint на узлах, принимающих трафик.
Multi-AZ-развёртывания
Multi-AZ означает размещение компонентов приложения в нескольких зонах доступности одного региона.
Region
├── AZ-a
│ ├── Load Balancer node
│ ├── Kubernetes nodes
│ └── Database primary
├── AZ-b
│ ├── Load Balancer node
│ ├── Kubernetes nodes
│ └── Database standby
└── AZ-c
├── Load Balancer node
└── Kubernetes nodesЧто необходимо распределять
Для полной Multi-AZ-архитектуры недостаточно распределить только виртуальные машины. Нужно проверить:
- подсети в нескольких AZ;
- worker nodes в нескольких AZ;
- реплики Pod в нескольких AZ;
- балансировщик с несколькими зонами;
- базу данных с Multi-AZ/failover;
- NAT или другой исходящий маршрут без единой точки отказа;
- persistent storage и его зональные ограничения;
- DNS и сертификаты;
- мониторинг и оповещения.
Подсети
Типичная VPC содержит публичные и приватные подсети в каждой зоне:
VPC 10.0.0.0/16
├── AZ-a
│ ├── public-a 10.0.0.0/24
│ └── private-a 10.0.10.0/24
├── AZ-b
│ ├── public-b 10.0.1.0/24
│ └── private-b 10.0.11.0/24
└── AZ-c
├── public-c 10.0.2.0/24
└── private-c 10.0.12.0/24Публичные подсети используются для компонентов, которым необходим прямой маршрут через Internet Gateway, например для публичных балансировщиков. Приложения и базы данных обычно находятся в приватных подсетях.
Зональные диски
Многие блочные диски привязаны к одной Availability Zone. Pod с таким диском нельзя произвольно запустить в другой зоне без восстановления или репликации данных.
Следует учитывать:
- topology выбранного
StorageClass; - режим
volumeBindingMode; - зону созданного
PersistentVolume; - стратегию восстановления диска;
- поддержку репликации хранилищем.
Пример StorageClass с отложенным созданием тома:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: production-block
provisioner: csi.example.cloud
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: trueWaitForFirstConsumer позволяет выбрать зону диска с учётом размещения Pod.
NAT и исходящий доступ
Один NAT Gateway в одной AZ может стать точкой отказа и источником межзонного трафика. Более отказоустойчивая схема использует отдельный NAT в каждой зоне и зональные таблицы маршрутизации.
private-a → NAT-a
private-b → NAT-b
private-c → NAT-cЭто повышает доступность, но также увеличивает стоимость. Для доступа к облачным сервисам можно применять private endpoints, если они доступны, сокращая зависимость от NAT и стоимость обработки трафика.
Multi-AZ и Multi-Region
| Характеристика | Multi-AZ | Multi-Region |
|---|---|---|
| Защита от отказа узла | Да | Да |
| Защита от отказа зоны | Да | Да |
| Защита от отказа региона | Нет | Да |
| Задержка между компонентами | Обычно низкая | Выше |
| Сложность данных | Умеренная | Высокая |
| Стоимость | Выше single-AZ | Обычно значительно выше |
Multi-Region требуется не каждому проекту. Решение должно исходить из бизнес-требований, а не только из желания получить максимально сложную архитектуру.
Отказоустойчивость приложения
Несколько реплик
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
spec:
replicas: 3
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
containers:
- name: api
image: registry.example.com/api:2.1.0
ports:
- containerPort: 8080Нескольк реплик помогают пережить отказ одного Pod или узла. Реплики должны быть распределены между узлами и зонами.
Readiness, liveness и startup probes
containers:
- name: api
image: registry.example.com/api:2.1.0
readinessProbe:
httpGet:
path: /health/ready
port: 8080
periodSeconds: 5
failureThreshold: 3
livenessProbe:
httpGet:
path: /health/live
port: 8080
periodSeconds: 10
failureThreshold: 3
startupProbe:
httpGet:
path: /health/startup
port: 8080
periodSeconds: 5
failureThreshold: 30- readinessProbe определяет, можно ли направлять трафик в Pod;
- livenessProbe определяет, нужно ли перезапустить контейнер;
- startupProbe даёт медленно запускающемуся приложению время на старт.
Liveness-проверка не должна завершать контейнер только из-за кратковременной недоступности внешней базы данных. Иначе общий сбой зависимости может вызвать массовые перезапуски.
Graceful shutdown
При завершении Pod приложение должно:
- перестать принимать новые запросы;
- завершить текущие операции;
- закрыть соединения;
- остановиться до окончания
terminationGracePeriodSeconds.
spec:
terminationGracePeriodSeconds: 30
containers:
- name: api
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 5"]Простой sleep иногда используют, чтобы дать балансировке время исключить endpoint, но лучше, чтобы само приложение корректно обрабатывало сигнал завершения.
Retry и timeout
Сетевые вызовы могут временно завершаться ошибкой. Клиенты должны использовать:
- ограниченный timeout;
- конечное число повторов;
- exponential backoff;
- jitter;
- идемпотентность повторяемых операций;
- circuit breaker при необходимости.
Неограниченные повторы увеличивают нагрузку во время сбоя и могут вызвать retry storm.
Cost optimization
Cost optimization — систематическая работа по снижению расходов без нарушения требований к доступности, производительности и безопасности.
Оптимизация не означает выбор самого дешёвого ресурса. Необходимо оценивать полную стоимость системы и последствия отказа.
Основные источники расходов
- виртуальные машины и worker nodes;
- managed Kubernetes control plane;
- базы данных;
- диски и snapshots;
- объектное хранилище;
- load balancers;
- NAT Gateway;
- межзонный и исходящий интернет-трафик;
- логи, метрики и трассировки;
- резервные копии;
- публичные IPv4-адреса;
- managed security-сервисы.
Теги и распределение затрат
Ресурсы следует помечать тегами или labels:
environment = production
service = payments
team = platform
cost-center = commerce
managed-by = terraformТеги позволяют строить отчёты по командам, сервисам и средам. Стандарт тегирования должен применяться автоматически через Terraform-модули или организационные политики.
Rightsizing
Rightsizing — подбор ресурсов по фактической нагрузке.
Примеры:
- уменьшить тип почти неиспользуемой виртуальной машины;
- снизить завышенные Kubernetes
requests; - выбрать memory-optimized узлы для памяти и compute-optimized для CPU;
- уменьшить размер простаивающей базы данных;
- удалить неиспользуемые диски и snapshots.
Изменения следует делать на основании метрик за репрезентативный период, включая часы пик.
Автомасштабирование
На разных уровнях могут работать:
- HPA — меняет число Pod;
- VPA — рекомендует или изменяет ресурсы Pod;
- cluster autoscaler — меняет число узлов;
- node auto-provisioning — создаёт подходящие группы узлов;
- autoscaling managed database — зависит от конкретного сервиса.
Эти механизмы должны быть согласованы. Например, HPA создаёт дополнительные Pod, а cluster autoscaler добавляет узлы, если Pod некуда разместить.
Spot и preemptible instances
Прерываемые экземпляры дешевле обычных, но облако может забрать их с коротким уведомлением.
Подходят для:
- stateless-приложений с несколькими репликами;
- batch-задач;
- CI/CD runners;
- фоновой обработки с повторным запуском;
- некритичных сред.
Не следует размещать всю production-нагрузку только на прерываемых экземплярах. Обычно используют сочетание обычных и spot-узлов.
Node pool A: on-demand, базовая ёмкость
Node pool B: spot, дополнительная ёмкостьПриложение должно корректно обрабатывать эвакуацию Pod и повторное выполнение задач.
Commitments и reserved capacity
Для постоянной предсказуемой нагрузки провайдеры предлагают модели обязательств на длительный срок. Они могут снизить стоимость вычислений, но уменьшают гибкость.
Перед покупкой обязательств следует оценить:
- стабильную базовую нагрузку;
- вероятность смены региона или типа ресурсов;
- планируемый рост;
- покрытие скидки;
- срок обязательства.
Хранилища
Оптимизация хранения включает:
- выбор подходящего класса диска;
- удаление неподключённых дисков;
- lifecycle для snapshots;
- tiering объектов в более холодные классы;
- удаление незавершённых multipart uploads;
- ограничение срока хранения временных данных;
- сжатие логов и артефактов.
Пример жизненного цикла объектов:
0–30 дней → Standard
31–90 дней → Infrequent Access
после 90 дней → Archive
после 365 дней → DeleteПереходы между классами и раннее удаление могут тарифицироваться, поэтому политику следует сопоставлять с реальным профилем доступа.
Сетевой трафик
Сетевые расходы часто недооценивают. Отдельно могут тарифицироваться:
- исходящий трафик в интернет;
- межрегионный трафик;
- межзонный трафик;
- обработка через NAT;
- обработка балансировщиком;
- private endpoints.
Способы оптимизации:
- использовать CDN для статического контента;
- не передавать большие объёмы между регионами без необходимости;
- учитывать zonal affinity;
- применять private endpoints для облачных сервисов;
- сжимать ответы;
- кэшировать часто запрашиваемые данные.
Экономия на межзонном трафике не должна разрушать отказоустойчивость. Например, размещение всех реплик в одной зоне может снизить сетевые расходы, но создаст риск полного отказа сервиса при проблеме с этой зоной.
Логи и метрики
Стоимость observability может расти быстрее стоимости вычислений.
Рекомендуется:
- задавать retention;
- исключать бесполезные debug-логи из production;
- не записывать секреты и персональные данные;
- применять sampling для трассировок;
- нормализовать labels, чтобы избегать высокой кардинальности;
- хранить только действительно используемые метрики;
- архивировать нужные журналы в более дешёвое хранилище.
Бюджеты и оповещения
Необходимо настроить:
- месячные бюджеты;
- предупреждения при достижении порогов;
- обнаружение аномальных расходов;
- отчёты по сервисам и командам;
- регулярный review неиспользуемых ресурсов.
Бюджетное оповещение обычно не останавливает ресурсы автоматически. Автоматическое отключение production-компонентов из-за превышения бюджета может привести к аварии и должно применяться только при явно продуманной политике.
Наблюдаемость и эксплуатация
Production-система должна предоставлять информацию о своём состоянии.
Три основных сигнала
- метрики — численные временные ряды;
- логи — события и сообщения;
- трассировки — путь запроса между сервисами.
Дополнительно отслеживают события инфраструктуры, изменения конфигурации и audit logs.
Основные метрики
Для HTTP-сервиса полезны:
- request rate;
- error rate;
- latency;
- saturation;
- число активных соединений;
- длина очереди;
- использование CPU и памяти;
- рестарты контейнеров.
Для базы данных:
- CPU и память;
- свободное место;
- число соединений;
- задержка запросов;
- блокировки;
- lag репликации;
- IOPS;
- cache hit ratio.
SLI, SLO и SLA
- SLI — измеряемый показатель, например доля успешных запросов;
- SLO — целевое значение показателя;
- SLA — внешнее обязательство перед клиентом.
Пример SLO:
99.9% HTTP-запросов за 30 дней завершаются успешно.
95% запросов выполняются не дольше 300 мс.Оповещения полезнее строить вокруг пользовательских симптомов и расходования error budget, а не только вокруг CPU отдельной виртуальной машины.
Централизованные логи
Логи нескольких Pod и узлов должны собираться централизованно. Запись только в локальный файл контейнера ненадёжна: Pod может быть удалён или перемещён.
Структурированный лог:
{
"timestamp": "2026-09-24T12:00:00Z",
"level": "error",
"service": "payments-api",
"request_id": "req-8f31",
"message": "database timeout"
}Не следует записывать в логи:
- пароли;
- токены;
- ключи API;
- полные платёжные данные;
- другие секреты и чувствительную информацию.
Runbooks
Для критичных оповещений полезно иметь runbook:
Alert: высокая доля HTTP 5xx
1. Проверить область воздействия.
2. Проверить последние deployment.
3. Проверить доступность базы и внешних зависимостей.
4. Проверить saturation и число реплик.
5. При необходимости выполнить rollback.
6. Зафиксировать временную шкалу инцидента.Runbook должен быть коротким, проверенным и доступным дежурной команде.
Безопасность production-инфраструктуры
IAM и минимальные привилегии
Каждый компонент получает только необходимые права:
Application A → чтение из bucket A
Application B → запись в queue B
CI/CD → обновление конкретного deployment
Administrator → отдельная роль с усиленной аутентификациейСледует избегать:
- общих постоянных access keys;
- административных прав для приложений;
- одной роли на все workload;
- хранения облачных ключей в образе контейнера;
- использования личной учётной записи в автоматизации.
Workload identity
Для доступа Pod к облачным сервисам применяют workload identity или аналогичный механизм:
Kubernetes ServiceAccount
↓
Cloud IAM role/account
↓
Краткоживущие credentialsЭто безопаснее постоянных ключей в Kubernetes Secret.
Сетевая сегментация
- публичными должны быть только необходимые endpoints;
- базы данных размещаются в приватных подсетях;
- administrative endpoints не публикуются в интернет;
- Security Groups или аналоги разрешают только необходимые направления;
- NetworkPolicy ограничивает взаимодействие между Pod;
- egress-контроль применяется для критичных workload.
Шифрование
Следует применять:
- TLS для трафика;
- шифрование дисков;
- шифрование резервных копий;
- шифрование объектов;
- управляемые ключи KMS при соответствующих требованиях;
- ротацию ключей и секретов.
Управление секретами
Секреты лучше хранить в managed secret manager или vault-системе. Kubernetes Secret сам по себе не является полноценным внешним хранилищем секретов.
Безопасная схема:
Secret Manager
↓ временный доступ
CSI driver / operator / application
↓
PodСекреты не должны попадать в:
- Git;
- Terraform state в открытом виде;
- container image;
- логи;
- параметры командной строки, если они сохраняются в истории или process list.
Audit logs
Audit logs помогают установить:
- кто изменил ресурс;
- когда произошло изменение;
- какой API был вызван;
- откуда поступил запрос;
- было ли действие разрешено.
Для критичных журналов следует настроить достаточный срок хранения и защиту от удаления.
Общий пример архитектуры
Рассмотрим production-приложение из frontend, API и PostgreSQL.
Internet
|
DNS
|
CDN / WAF
|
Public L7 Load Balancer
|
Managed Kubernetes cluster
├── AZ-a
│ ├── frontend Pod
│ └── api Pod
├── AZ-b
│ ├── frontend Pod
│ └── api Pod
└── AZ-c
├── frontend Pod
└── api Pod
|
+── Managed PostgreSQL Multi-AZ
|
+── Object Storage
|
+── Secret ManagerКомпоненты
| Компонент | Назначение |
|---|---|
| DNS | Преобразование домена в адрес сервиса |
| CDN | Кэширование статического контента ближе к пользователю |
| WAF | Фильтрация типовых вредоносных HTTP-запросов |
| L7 Load Balancer | TLS и маршрутизация HTTP-трафика |
| Managed Kubernetes | Запуск и масштабирование контейнеров |
| Managed PostgreSQL | Транзакционные данные приложения |
| Object Storage | Пользовательские файлы и артефакты |
| Secret Manager | Хранение секретов |
| Monitoring | Метрики, dashboard и alerting |
| Centralized Logging | Поиск и хранение журналов |
Поток запроса
- Пользователь обращается к
app.example.com. - DNS возвращает адрес CDN или балансировщика.
- WAF проверяет HTTP-запрос.
- L7 Load Balancer завершает TLS.
- Ingress направляет запрос в нужный Kubernetes Service.
- Service выбирает готовый Pod.
- API обращается к базе данных через приватную сеть.
- Файлы сохраняются в object storage через workload identity.
- Метрики, логи и трассировки отправляются в систему наблюдаемости.
Пример HPA
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: api
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api
minReplicas: 3
maxReplicas: 20
behavior:
scaleDown:
stabilizationWindowSeconds: 300
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 65Минимум три реплики обеспечивает базовое распределение по зонам. Фактическое распределение следует закрепить topology spread constraints или affinity.
Пример NetworkPolicy
Следующая политика разрешает входящий трафик к API только от Pod с меткой app: ingress-controller в namespace ingress-system:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-ingress
namespace: production
spec:
podSelector:
matchLabels:
app: api
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: ingress-system
podSelector:
matchLabels:
app: ingress-controller
ports:
- protocol: TCP
port: 8080Для применения NetworkPolicy сетевой плагин кластера должен поддерживать их выполнение.
Стратегия deployment
Для обычного rolling update:
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 1maxUnavailable: 0 не допускает планового уменьшения количества доступных реплик во время обновления, но временно требует дополнительной ёмкости.
Перед выпуском необходимо проверить:
- readiness probe новой версии;
- совместимость миграций базы;
- достаточную ёмкость кластера;
- dashboard и alerting;
- процедуру rollback.
Чек-лист перед запуском
Архитектура
- Компоненты распределены минимум по двум Availability Zones.
- Нет неучтённых единичных точек отказа.
- Определены RTO и RPO.
- Выбран понятный план восстановления после отказа зоны.
- Stateless-компоненты имеют несколько реплик.
Managed Kubernetes
- Control plane и node pools используют поддерживаемые версии.
- Worker nodes распределены по зонам.
- Для Pod заданы requests и limits.
- Настроены readiness, liveness и startup probes.
- Применяются PodDisruptionBudget и topology spread constraints.
- Проверена работа cluster autoscaler.
- Системные и прикладные workload разделены при необходимости.
- Настроен безопасный процесс обновления кластера.
База данных
- База находится в приватной сети.
- Включена Multi-AZ-конфигурация, если этого требует доступность.
- Создаются автоматические резервные копии.
- Проверено восстановление из backup или PITR.
- Настроен мониторинг соединений, места, задержек и репликации.
- Размер connection pool соответствует лимитам базы.
- Миграции схемы поддерживают поэтапное обновление.
Балансировка и сеть
- Балансировщик работает в нескольких зонах.
- Health checks проверяют готовность приложения.
- TLS-сертификаты обновляются автоматически.
- Публичный доступ разрешён только необходимым компонентам.
- Security Groups, firewall rules и NetworkPolicy минимальны.
- Учтены стоимость NAT, межзонного и исходящего трафика.
Безопасность
- Для людей и сервисов настроены отдельные identities.
- Применяется принцип наименьших привилегий.
- Pod используют workload identity вместо постоянных ключей.
- Секреты хранятся в специализированном secret manager.
- Включено шифрование данных и резервных копий.
- Включены audit logs.
- Административный доступ защищён усиленной аутентификацией.
Наблюдаемость
- Собираются метрики, логи и трассировки.
- Определены SLI и SLO.
- Настроены оповещения по пользовательским симптомам.
- Для критичных alert существуют runbooks.
- У логов и метрик задан срок хранения.
- Логи не содержат секретов.
Стоимость
- На ресурсах есть обязательные теги.
- Настроены бюджеты и уведомления об аномалиях.
- Выполнен rightsizing узлов и баз данных.
- Удалены неиспользуемые диски, адреса и snapshots.
- Для постоянной нагрузки оценены долгосрочные обязательства.
- Spot-экземпляры используются только для устойчивых к прерыванию workload.
- Настроены lifecycle-политики хранения.
- Проверены расходы на логи и сетевой трафик.
Cloud Production строится не вокруг одного конкретного сервиса, а вокруг набора проверяемых свойств: система должна выдерживать ожидаемые отказы, восстанавливаться в заданные сроки, безопасно работать с данными, масштабироваться под нагрузкой и сохранять предсказуемую стоимость. Managed Kubernetes, managed databases и облачные load balancers уменьшают объём ручного администрирования, но требуют корректной архитектуры, настройки и регулярных проверок.