Философия Managed Services
Managed services -- это сервисы, в которых облачный провайдер берёт на себя операционную часть: обновления, бэкапы, масштабирование, мониторинг. Вы платите больше за час, но экономите на DevOps-инженерах и операционных рисках.
┌─────────────────────────────────────────────────────────┐
│ Спектр ответственности │
│ │
│ Вы управляете всем Провайдер управляет всем │
│ ◄──────────────────────────────────────────────────► │
│ │
│ EC2/VM Containers Managed DB Serverless │
│ (IaaS) (ECS/EKS) (RDS/Aurora) (Lambda/Fargate) │
│ │
│ OS, patches App only Schema only Code only │
│ Security Config Queries Business logic │
│ Backups Deploy Data Events │
└─────────────────────────────────────────────────────────┘
Когда использовать managed vs self-hosted
| Фактор | Self-hosted (EC2 + Docker) | Managed Service |
|---|---|---|
| Контроль | Полный | Ограниченный |
| Операционная нагрузка | Высокая | Минимальная |
| Стоимость | Дешевле per-hour | Дороже, но меньше DevOps |
| Масштабирование | Ручное / скрипты | Автоматическое / 1 клик |
| SLA | Ваша ответственность | 99.95-99.99% от провайдера |
| Время до production | Дни-недели | Минуты-часы |
Правило: используйте managed services по умолчанию, self-hosted -- только если есть конкретная причина (compliance, специфичная конфигурация, экономия при огромном масштабе).
Compute: где запускать код
EC2 (Elastic Compute Cloud)
Виртуальные машины. Полный контроль над ОС, конфигурацией, софтом.
Когда использовать: специфичные требования к ОС, GPU workloads, legacy приложения, stateful сервисы (например, PostgreSQL если не хотите RDS).
| Тип инстанса | Назначение | Пример |
|---|---|---|
| t3/t4g | General purpose, burstable | Web-серверы, dev/staging |
| m6i/m7g | General purpose, consistent | Production API |
| c6i/c7g | Compute-optimized | CPU-heavy обработка |
| r6i/r7g | Memory-optimized | Кэширование, analytics |
| g5/p4d | GPU | ML inference, rendering |
Экономия:
- Spot instances: до -90%, но могут быть прерваны (для batch jobs, workers)
- Reserved instances: до -72% за 1-3 года commitment
- Savings Plans: до -66%, более гибкие чем RI
ECS Fargate (Serverless Containers)
Запуск Docker-контейнеров без управления серверами. AWS выделяет ресурсы per-task.
Когда использовать: микросервисы, API, background workers, любое контейнеризированное приложение.
┌────────────────────────────────────────────┐
│ ECS Cluster │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Service │ │ Service │ │ Service │ │
│ │ API │ │ Worker │ │ Cron │ │
│ │ 3 tasks │ │ 2 tasks │ │ 1 task │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │
│ Fargate manages underlying infrastructure │
└────────────────────────────────────────────┘
Стоимость: ~$30/мес за 0.5 vCPU + 1GB RAM (24/7). Дороже EC2, но нет серверов для управления.
EKS (Elastic Kubernetes Service)
Managed Kubernetes. Control plane управляется AWS, вы управляете worker nodes.
Когда использовать: команда уже использует Kubernetes, сложные deployment паттерны, multi-cloud стратегия, нужны CRD/operators.
Стоимость: $73/мес за control plane + стоимость worker nodes.
Lambda (Serverless Functions)
Запуск функций по событиям. Платите только за время выполнения.
Когда использовать: обработка событий (S3 upload, SQS message), webhooks, scheduled tasks, API с неравномерной нагрузкой.
Событие → Lambda → Результат
S3 Upload → Resize Image → Save to S3
SQS Message → Process Order → Update DB
API Gateway → Handle Request → Return JSON
CloudWatch → Scheduled Cleanup → Delete Old Data
Ограничения: 15 мин max execution, 10GB RAM max, cold starts (100-500ms для Python/Node, 1-3s для Java).
Стоимость: $0.20 за 1M запросов + $0.0000166667 за GB-sec. Первые 1M запросов и 400K GB-sec бесплатны.
App Runner
Самый простой вариант: push Docker image → получаете URL. Без кластеров, без task definitions.
Когда использовать: простые API, прототипы, MVP.
Decision Matrix: Compute
Нужен полный контроль над ОС?
└── Да → EC2
└── Нет
└── Есть Docker image?
└── Да
│ └── Нужен Kubernetes?
│ └── Да → EKS
│ └── Нет
│ └── Простое приложение? → App Runner
│ └── Сложное (scaling, networking) → ECS Fargate
└── Нет
└── Event-driven / short tasks? → Lambda
└── Long-running → Container (ECS/EKS)
Storage: где хранить данные
S3 (Simple Storage Service)
Объектное хранилище с "бесконечной" ёмкостью. Durability 99.999999999% (11 девяток).
Кейсы: статические файлы, бэкапы, логи, data lake, аватарки пользователей, экспорты.
| Storage Class | Стоимость (за GB/мес) | Доступ | Use Case |
|---|---|---|---|
| S3 Standard | $0.023 | Мгновенный | Активные данные |
| S3 Infrequent Access | $0.0125 | Мгновенный, $0.01/GB retrieval | Бэкапы, логи 30+ дней |
| S3 Glacier Instant | $0.004 | Мгновенный | Архив с быстрым доступом |
| S3 Glacier Deep Archive | $0.00099 | 12-48 часов | Compliance архив 7+ лет |
PHP пример: загрузка аватарки в S3:
<?php
declare(strict_types=1);
use Aws\S3\S3Client;
final class S3FileUploader
{
public function __construct(
private readonly S3Client $s3,
private readonly string $bucket,
) {}
/**
* Upload user avatar with signed URL for private access.
*/
public function uploadAvatar(string $userId, string $filePath): string
{
$key = sprintf('avatars/%s/%s.webp', $userId, bin2hex(random_bytes(8)));
$this->s3->putObject([
'Bucket' => $this->bucket,
'Key' => $key,
'Body' => fopen($filePath, 'rb'),
'ContentType' => 'image/webp',
'ServerSideEncryption' => 'AES256',
'Metadata' => [
'user-id' => $userId,
'uploaded-at' => (new \DateTimeImmutable())->format('c'),
],
]);
return $key;
}
/**
* Generate pre-signed URL for temporary access (15 min).
*/
public function getSignedUrl(string $key): string
{
$cmd = $this->s3->getCommand('GetObject', [
'Bucket' => $this->bucket,
'Key' => $key,
]);
return (string) $this->s3->createPresignedRequest($cmd, '+15 minutes')->getUri();
}
}
Go пример:
package storage
import (
"context"
"fmt"
"io"
"time"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/s3"
)
type S3Uploader struct {
client *s3.Client
bucket string
}
func NewS3Uploader(client *s3.Client, bucket string) *S3Uploader {
return &S3Uploader{client: client, bucket: bucket}
}
// UploadAvatar stores user avatar with server-side encryption.
func (u *S3Uploader) UploadAvatar(ctx context.Context, userID string, body io.Reader) (string, error) {
key := fmt.Sprintf("avatars/%s/%d.webp", userID, time.Now().UnixNano())
_, err := u.client.PutObject(ctx, &s3.PutObjectInput{
Bucket: aws.String(u.bucket),
Key: aws.String(key),
Body: body,
ContentType: aws.String("image/webp"),
ServerSideEncryption: "AES256",
})
if err != nil {
return "", fmt.Errorf("upload avatar: %w", err)
}
return key, nil
}
// GetSignedURL generates pre-signed URL for temporary access.
func (u *S3Uploader) GetSignedURL(ctx context.Context, key string, ttl time.Duration) (string, error) {
presigner := s3.NewPresignClient(u.client)
req, err := presigner.PresignGetObject(ctx, &s3.GetObjectInput{
Bucket: aws.String(u.bucket),
Key: aws.String(key),
}, s3.WithPresignExpires(ttl))
if err != nil {
return "", fmt.Errorf("presign url: %w", err)
}
return req.URL, nil
}
EBS (Elastic Block Store)
Блочное хранилище, привязанное к EC2. Как SSD-диск для виртуалки.
Кейсы: корневой диск EC2, база данных (если self-hosted).
EFS (Elastic File System)
Managed NFS. Доступен из нескольких EC2/ECS одновременно.
Кейсы: shared storage для контейнеров, CMS с uploaded файлами, ML training data.
Databases: где хранить структурированные данные
RDS (Relational Database Service)
Managed PostgreSQL, MySQL, MariaDB, Oracle, SQL Server. AWS управляет бэкапами, патчами, failover.
Ключевые фичи:
- Multi-AZ: автоматический failover (30-60 сек)
- Read Replicas: до 15 реплик для чтения
- Automated backups: point-in-time recovery до 35 дней
- Performance Insights: мониторинг SQL-запросов
# Terraform: RDS PostgreSQL with Multi-AZ
resource "aws_db_instance" "main" {
identifier = "${var.project}-db"
engine = "postgres"
engine_version = "16.4"
instance_class = var.environment == "prod" ? "db.r6g.large" : "db.t4g.micro"
allocated_storage = 100
max_allocated_storage = 500 # Auto-scaling storage
storage_encrypted = true
db_name = "app_db"
username = "app"
password = data.aws_secretsmanager_secret_version.db.secret_string
multi_az = var.environment == "prod"
db_subnet_group_name = aws_db_subnet_group.main.name
vpc_security_group_ids = [aws_security_group.db.id]
backup_retention_period = var.environment == "prod" ? 35 : 7
backup_window = "03:00-04:00"
maintenance_window = "Sun:04:00-Sun:05:00"
performance_insights_enabled = var.environment == "prod"
monitoring_interval = var.environment == "prod" ? 60 : 0
deletion_protection = var.environment == "prod"
skip_final_snapshot = var.environment != "prod"
tags = {
Name = "${var.project}-db"
Environment = var.environment
}
}
Стоимость: db.t4g.micro ~$12/мес (dev), db.r6g.large ~$175/мес (prod) + storage.
Aurora (PostgreSQL/MySQL compatible)
AWS-оптимизированная РСУБД. До 5x быстрее MySQL, 3x быстрее PostgreSQL. Хранилище до 128 TB, автоматическое масштабирование.
Когда использовать: production с высокими требованиями к производительности, >100GB данных, нужен быстрый failover (<30 сек).
Aurora Serverless v2: автоматическое масштабирование от 0.5 до 256 ACU. Платите за фактическое потребление.
ElastiCache (Redis / Memcached)
Managed Redis или Memcached для кэширования и сессий.
# Terraform: ElastiCache Redis cluster
resource "aws_elasticache_replication_group" "main" {
replication_group_id = "${var.project}-redis"
description = "Redis cluster for ${var.project}"
engine = "redis"
engine_version = "7.1"
node_type = var.environment == "prod" ? "cache.r6g.large" : "cache.t4g.micro"
num_cache_clusters = var.environment == "prod" ? 2 : 1
at_rest_encryption_enabled = true
transit_encryption_enabled = true
auth_token = data.aws_secretsmanager_secret_version.redis.secret_string
subnet_group_name = aws_elasticache_subnet_group.main.name
security_group_ids = [aws_security_group.redis.id]
automatic_failover_enabled = var.environment == "prod"
multi_az_enabled = var.environment == "prod"
snapshot_retention_limit = var.environment == "prod" ? 7 : 0
tags = {
Name = "${var.project}-redis"
Environment = var.environment
}
}
DynamoDB
NoSQL key-value / document database. Бесконечно масштабируемая, serverless.
Когда использовать: простые access patterns (get by key, query by partition), session storage, feature flags, rate limiting counters.
Когда НЕ использовать: сложные JOIN-запросы, ad-hoc queries, OLAP.
Messaging: как связать компоненты
SQS (Simple Queue Service)
Managed очередь сообщений. Полностью serverless, автоматическое масштабирование.
| Тип | Гарантии | Throughput | Ordering |
|---|---|---|---|
| Standard | At-least-once | Неограниченный | Best-effort |
| FIFO | Exactly-once | 3000 msg/sec (batch), 300 msg/sec (per MessageGroupId) | Strict per group |
Стоимость: первые 1M запросов бесплатны, далее $0.40 за 1M.
<?php
declare(strict_types=1);
use Aws\Sqs\SqsClient;
final class SqsProducer
{
public function __construct(
private readonly SqsClient $sqs,
private readonly string $queueUrl,
) {}
public function send(string $messageBody, array $attributes = []): string
{
$result = $this->sqs->sendMessage([
'QueueUrl' => $this->queueUrl,
'MessageBody' => $messageBody,
'MessageAttributes' => $this->formatAttributes($attributes),
]);
return $result['MessageId'];
}
private function formatAttributes(array $attributes): array
{
$formatted = [];
foreach ($attributes as $key => $value) {
$formatted[$key] = [
'DataType' => 'String',
'StringValue' => (string) $value,
];
}
return $formatted;
}
}
SNS (Simple Notification Service)
Pub/Sub для fan-out. Одно сообщение → несколько получателей (SQS, Lambda, HTTP, Email, SMS).
┌── SQS (order processing)
SNS Topic ────┼── SQS (notification service)
├── Lambda (analytics)
└── HTTP (external webhook)
EventBridge
Event bus для event-driven архитектуры. Фильтрация событий по правилам, schema registry.
Когда использовать: сложная маршрутизация событий, интеграция с SaaS (Stripe, Auth0), cross-account events.
Monitoring: как следить за приложением
CloudWatch
Мониторинг, логирование и алертинг. Основной инструмент наблюдаемости в AWS.
Компоненты:
- Metrics: CPU, Memory, Request Count, Latency (встроенные + custom)
- Logs: централизованное хранилище логов с поиском
- Alarms: алерты при превышении threshold
- Dashboards: визуализация метрик
# CloudWatch Alarm: high CPU on ECS
resource "aws_cloudwatch_metric_alarm" "high_cpu" {
alarm_name = "${var.project}-high-cpu"
comparison_operator = "GreaterThanThreshold"
evaluation_periods = 3
metric_name = "CPUUtilization"
namespace = "AWS/ECS"
period = 60
statistic = "Average"
threshold = 80
dimensions = {
ClusterName = aws_ecs_cluster.main.name
ServiceName = aws_ecs_service.api.name
}
alarm_actions = [aws_sns_topic.alerts.arn]
tags = {
Environment = var.environment
}
}
# CloudWatch Alarm: high error rate on ALB
resource "aws_cloudwatch_metric_alarm" "high_5xx" {
alarm_name = "${var.project}-high-5xx"
comparison_operator = "GreaterThanThreshold"
evaluation_periods = 2
metric_name = "HTTPCode_Target_5XX_Count"
namespace = "AWS/ApplicationELB"
period = 300
statistic = "Sum"
threshold = 50
dimensions = {
LoadBalancer = aws_lb.main.arn_suffix
}
alarm_actions = [aws_sns_topic.alerts.arn]
}
X-Ray
Distributed tracing для микросервисов. Визуализация вызовов между сервисами, выявление bottlenecks.
Когда использовать: микросервисная архитектура, отладка медленных запросов, understanding service dependencies.
Сводная таблица: что когда использовать
| Задача | Сервис | Стоимость (ориентир) |
|---|---|---|
| Web API (контейнер) | ECS Fargate | $30-150/мес |
| Background worker | ECS Fargate / Lambda | $10-50/мес |
| Обработка событий | Lambda | $0-10/мес (при <1M/мес) |
| PostgreSQL | RDS | $12-200/мес |
| Redis cache | ElastiCache | $13-200/мес |
| Key-value store | DynamoDB | $0-50/мес |
| Файлы/бэкапы | S3 | $0.023/GB |
| Очередь сообщений | SQS | $0-5/мес |
| Pub/Sub fan-out | SNS | $0-5/мес |
| Поиск | OpenSearch | $50-300/мес |
| Мониторинг | CloudWatch | $0-30/мес |
| DNS | Route 53 | $0.50/zone + $0.40/1M queries |
| CDN | CloudFront | $0-30/мес |
Правило: для dev/staging используйте минимальные инстансы (t4g.micro, db.t4g.micro). Для prod -- right-size через Performance Insights и CloudWatch metrics.
Стратегии экономии
1. Right-sizing
Мониторьте CPU/Memory utilization. Если средняя загрузка <30%, нужен инстанс поменьше.
2. Spot / Serverless для dev
Dev/staging окружения не нужны 24/7. Используйте scheduled scaling или serverless (Aurora Serverless, Fargate Spot).
3. S3 Lifecycle Policies
resource "aws_s3_bucket_lifecycle_configuration" "logs" {
bucket = aws_s3_bucket.logs.id
rule {
id = "archive-old-logs"
status = "Enabled"
transition {
days = 30
storage_class = "STANDARD_IA"
}
transition {
days = 90
storage_class = "GLACIER"
}
expiration {
days = 365
}
}
}
4. Reserved capacity
Для стабильных production workloads: Reserved Instances (RDS, ElastiCache) или Savings Plans (Compute).
5. VPC Endpoints
Используйте Gateway endpoints для S3/DynamoDB (бесплатно) вместо NAT Gateway ($0.045/GB).