正在加载,请稍候…

AWS ECS Fargate:无需管理服务器即可部署容器化应用

在 AWS ECS Fargate 上部署容器——任务定义、服务自动扩缩、ALB 集成、服务发现、来自 SSM 的密钥以及使用 GitHub Actions 的

AWS ECS Fargate:无需管理服务器即可部署容器化应用

ECS Fargate:无服务器容器

Fargate 无需管理 EC2 实例即可运行容器。您只需定义 CPU/内存,AWS 负责其余部分。

AWS ECS Fargate:无需管理服务器即可部署容器化应用 插图

任务定义

{
  "family": "api",
  "networkMode": "awsvpc",
  "requiresCompatibilities": ["FARGATE"],
  "cpu": "512",
  "memory": "1024",
  "executionRoleArn": "arn:aws:iam::123456789:role/ecsTaskExecutionRole",
  "taskRoleArn": "arn:aws:iam::123456789:role/ecsTaskRole",
  "containerDefinitions": [
    {
      "name": "api",
      "image": "123456789.dkr.ecr.us-east-1.amazonaws.com/api:latest",
      "portMappings": [
        { "containerPort": 3000, "protocol": "tcp" }
      ],
      "environment": [
        { "name": "NODE_ENV", "value": "production" },
        { "name": "PORT", "value": "3000" }
      ],
      "secrets": [
        { "name": "DATABASE_URL", "valueFrom": "arn:aws:ssm:us-east-1:123:parameter/myapp/prod/database-url" },
        { "name": "JWT_SECRET", "valueFrom": "arn:aws:secretsmanager:us-east-1:123:secret:myapp/jwt-secret" }
      ],
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group": "/ecs/api",
          "awslogs-region": "us-east-1",
          "awslogs-stream-prefix": "ecs"
        }
      },
      "healthCheck": {
        "command": ["CMD-SHELL", "curl -f http://localhost:3000/health || exit 1"],
        "interval": 30,
        "timeout": 10,
        "retries": 3,
        "startPeriod": 60
      }
    }
  ]
}

AWS ECS Fargate:无需管理服务器即可部署容器化应用 插图

服务定义与自动扩缩

# 创建服务
aws ecs create-service   --cluster production   --service-name api   --task-definition api:5   --desired-count 3   --launch-type FARGATE   --network-configuration "awsvpcConfiguration={
    subnets=[subnet-xxx,subnet-yyy],
    securityGroups=[sg-xxx],
    assignPublicIp=DISABLED
  }"   --load-balancers "targetGroupArn=arn:aws:elasticloadbalancing:...,containerName=api,containerPort=3000"   --deployment-configuration "maximumPercent=200,minimumHealthyPercent=100,deploymentCircuitBreaker={enable=true,rollback=true}"
// 自动扩缩策略
{
  "scalableDimension": "ecs:service:DesiredCount",
  "serviceNamespace": "ecs",
  "resourceId": "service/production/api",
  "minCapacity": 2,
  "maxCapacity": 20,
  "targetTrackingScalingPolicies": [
    {
      "targetValue": 70,
      "predefinedMetricSpecification": {
        "predefinedMetricType": "ECSServiceAverageCPUUtilization"
      },
      "scaleInCooldown": 300,
      "scaleOutCooldown": 60
    },
    {
      "targetValue": 1000,
      "predefinedMetricSpecification": {
        "predefinedMetricType": "ALBRequestCountPerTarget",
        "resourceLabel": "app/prod-alb/xxx/targetgroup/api/xxx"
      }
    }
  ]
}

AWS ECS Fargate:无需管理服务器即可部署容器化应用 插图

ECR 推送脚本

#!/bin/bash
set -e

AWS_REGION=us-east-1
AWS_ACCOUNT=123456789
ECR_REPO="\${AWS_ACCOUNT}.dkr.ecr.\${AWS_REGION}.amazonaws.com/api"
IMAGE_TAG="\${GITHUB_SHA:-latest}"

# 登录 ECR
aws ecr get-login-password --region $AWS_REGION |   docker login --username AWS --password-stdin $AWS_ACCOUNT.dkr.ecr.$AWS_REGION.amazonaws.com

# 构建并推送
docker build -t $ECR_REPO:$IMAGE_TAG .
docker push $ECR_REPO:$IMAGE_TAG

# 标记为 latest
docker tag $ECR_REPO:$IMAGE_TAG $ECR_REPO:latest
docker push $ECR_REPO:latest

# 更新 ECS 服务
aws ecs update-service   --cluster production   --service api   --force-new-deployment   --task-definition api

密钥管理

# 在 SSM Parameter Store 中存储密钥
aws ssm put-parameter   --name /myapp/prod/database-url   --value "postgresql://user:pass@rds-endpoint/myapp"   --type SecureString   --key-id alias/myapp-key

# ECS 任务读取密钥的 IAM 策略
{
  "Effect": "Allow",
  "Action": ["ssm:GetParameter", "ssm:GetParameters"],
  "Resource": "arn:aws:ssm:us-east-1:123:parameter/myapp/prod/*"
}

CloudWatch Logs Insights

# 查找过去一小时的错误
fields @timestamp, @message
| filter @message like /ERROR/
| sort @timestamp desc
| limit 100

# 从结构化日志中获取 P99 响应时间
fields @timestamp, duration
| filter statusCode >= 200
| stats pct(duration, 99) as p99 by bin(5m)