MidТеория7 min

Cloud Managed Services

Обзор управляемых сервисов облака: compute, storage, databases, messaging, monitoring. Когда что использовать

Философия 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).

Проверь себя

5 из 7

Когда стоит использовать Aurora вместо обычного RDS PostgreSQL?

В чём главное отличие SQS Standard от SQS FIFO?

Какой AWS сервис лучше использовать для fan-out (одно событие → несколько обработчиков)?

Какой S3 Storage Class подходит для логов старше 30 дней, к которым редко обращаются?

Какой AWS compute сервис лучше всего подходит для запуска Docker-контейнеров без управления серверами?