aws-cloudformation-task-ecs-deploy-gh
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseAWS CloudFormation Task ECS Deploy with GitHub Actions
借助GitHub Actions实现AWS CloudFormation任务与ECS部署
Comprehensive skill for deploying ECS containers using GitHub Actions CI/CD pipelines with CloudFormation infrastructure management.
本技能全面介绍如何结合GitHub Actions CI/CD流水线与CloudFormation基础设施管理,完成ECS容器部署。
Overview
概述
Deploy containerized applications to Amazon ECS using GitHub Actions workflows. This skill covers the complete deployment pipeline: authentication with AWS (OIDC recommended), building Docker images, pushing to Amazon ECR, updating task definitions, and deploying ECS services. Integrate with CloudFormation for infrastructure-as-code management and implement production-grade deployment strategies.
通过GitHub Actions工作流将容器化应用部署至Amazon ECS。本技能覆盖完整部署流程:AWS认证(推荐使用OIDC)、构建Docker镜像、推送至Amazon ECR、更新任务定义以及部署ECS服务。集成CloudFormation实现基础设施即代码管理,并落地生产级部署策略。
When to Use
适用场景
Use this skill when:
- Deploying Docker containers to Amazon ECS
- Setting up GitHub Actions CI/CD pipelines for AWS
- Configuring AWS authentication for GitHub Actions (OIDC or IAM keys)
- Building and pushing Docker images to Amazon ECR
- Updating ECS task definitions dynamically
- Implementing blue/green or rolling deployments
- Managing CloudFormation stacks from CI/CD
- Setting up multi-environment deployments (dev/staging/prod)
- Configuring private ECR repositories with image scanning
- Automating container deployment with proper security practices
Trigger phrases:
- "Deploy to ECS with GitHub Actions"
- "Set up CI/CD for ECS containers"
- "Configure GitHub Actions for AWS deployment"
- "Build and push Docker image to ECR"
- "Update ECS task definition from CI/CD"
- "Implement blue/green deployment for ECS"
- "Deploy CloudFormation stack from GitHub Actions"
在以下场景使用本技能:
- 向Amazon ECS部署Docker容器
- 为AWS搭建GitHub Actions CI/CD流水线
- 为GitHub Actions配置AWS认证(OIDC或IAM密钥)
- 构建并推送Docker镜像至Amazon ECR
- 动态更新ECS任务定义
- 实现蓝绿部署或滚动部署
- 通过CI/CD管理CloudFormation堆栈
- 搭建多环境部署(开发/预发布/生产)
- 配置带镜像扫描的私有ECR仓库
- 遵循安全实践实现容器部署自动化
触发关键词:
- "使用GitHub Actions部署至ECS"
- "为ECS容器搭建CI/CD流水线"
- "为AWS部署配置GitHub Actions"
- "构建并推送Docker镜像至ECR"
- "通过CI/CD更新ECS任务定义"
- "为ECS实现蓝绿部署"
- "通过GitHub Actions部署CloudFormation堆栈"
Quick Start
快速开始
Basic ECS Deployment Workflow
基础ECS部署工作流
yaml
name: Deploy to ECS
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/github-actions-ecs-role
aws-region: us-east-1
- name: Login to ECR
uses: aws-actions/amazon-ecr-login@v2
- name: Build and push image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: my-app
IMAGE_TAG: ${{ github.sha }}
run: |
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
- name: Update task definition
uses: aws-actions/amazon-ecs-render-task-definition@v1
id: render-task
with:
task-definition: task-definition.json
container-name: my-app
image: ${{ steps.login-ecr.outputs.registry }}/my-app:${{ github.sha }}
- name: Deploy to ECS
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
with:
task-definition: ${{ steps.render-task.outputs.task-definition }}
service: my-service
cluster: my-cluster
wait-for-service-stability: trueyaml
name: Deploy to ECS
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/github-actions-ecs-role
aws-region: us-east-1
- name: Login to ECR
uses: aws-actions/amazon-ecr-login@v2
- name: Build and push image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: my-app
IMAGE_TAG: ${{ github.sha }}
run: |
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
- name: Update task definition
uses: aws-actions/amazon-ecs-render-task-definition@v1
id: render-task
with:
task-definition: task-definition.json
container-name: my-app
image: ${{ steps.login-ecr.outputs.registry }}/my-app:${{ github.sha }}
- name: Deploy to ECS
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
with:
task-definition: ${{ steps.render-task.outputs.task-definition }}
service: my-service
cluster: my-cluster
wait-for-service-stability: trueAuthentication Methods
认证方式
OIDC Authentication (Recommended)
OIDC认证(推荐)
OpenID Connect (OIDC) provides secure, passwordless authentication between GitHub Actions and AWS.
Prerequisites:
- Create IAM role with trust policy for GitHub:
yaml
Type: AWS::IAM::Role
Properties:
RoleName: github-actions-ecs-role
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Federated: !Sub 'arn:aws:iam::${AWS::AccountId}:oidc-provider/token.actions.githubusercontent.com'
Action: sts:AssumeRoleWithWebIdentity
Condition:
StringEquals:
token.actions.githubusercontent.com:aud: sts.amazonaws.com
StringLike:
token.actions.githubusercontent.com:sub: repo:my-org/my-repo:*
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonECS_FullAccess
- arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryFullAccess- Configure GitHub Actions workflow:
yaml
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/github-actions-ecs-role
aws-region: us-east-1OpenID Connect (OIDC) 为GitHub Actions与AWS之间提供安全的无密码认证机制。
前置条件:
- 创建针对GitHub的IAM角色信任策略:
yaml
Type: AWS::IAM::Role
Properties:
RoleName: github-actions-ecs-role
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Federated: !Sub 'arn:aws:iam::${AWS::AccountId}:oidc-provider/token.actions.githubusercontent.com'
Action: sts:AssumeRoleWithWebIdentity
Condition:
StringEquals:
token.actions.githubusercontent.com:aud: sts.amazonaws.com
StringLike:
token.actions.githubusercontent.com:sub: repo:my-org/my-repo:*
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonECS_FullAccess
- arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryFullAccess- 配置GitHub Actions工作流:
yaml
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/github-actions-ecs-role
aws-region: us-east-1IAM Key Authentication (Legacy)
IAM密钥认证(传统方式)
yaml
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1Store credentials in GitHub repository secrets (Settings → Secrets and variables → Actions).
yaml
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1将凭证存储在GitHub仓库密钥中(设置 → 密钥和变量 → Actions)。
Build and Push to ECR
构建并推送至ECR
ECR Repository CloudFormation Template
ECR仓库CloudFormation模板
yaml
ECRRepository:
Type: AWS::ECR::Repository
Properties:
RepositoryName: my-app
ImageScanningConfiguration:
ScanOnPush: true
ImageTagMutability: IMMUTABLE
LifecyclePolicy:
LifecyclePolicyText: |
{
"rules": [
{
"rulePriority": 1,
"description": "Keep last 30 images",
"selection": {
"tagStatus": "tagged",
"tagPrefixList": ["v"],
"countType": "imageCountMoreThan",
"countNumber": 30
},
"action": {
"type": "expire"
}
}
]
}yaml
ECRRepository:
Type: AWS::ECR::Repository
Properties:
RepositoryName: my-app
ImageScanningConfiguration:
ScanOnPush: true
ImageTagMutability: IMMUTABLE
LifecyclePolicy:
LifecyclePolicyText: |
{
"rules": [
{
"rulePriority": 1,
"description": "Keep last 30 images",
"selection": {
"tagStatus": "tagged",
"tagPrefixList": ["v"],
"countType": "imageCountMoreThan",
"countNumber": 30
},
"action": {
"type": "expire"
}
}
]
}Build and Push Step
构建与推送步骤
yaml
- name: Login to ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: |
${{ steps.login-ecr.outputs.registry }}/my-app:${{ github.sha }}
${{ steps.login-ecr.outputs.registry }}/my-app:latest
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
BUILD_DATE=${{ github.event.head_commit.timestamp }}
VERSION=${{ github.sha }}yaml
- name: Login to ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: |
${{ steps.login-ecr.outputs.registry }}/my-app:${{ github.sha }}
${{ steps.login-ecr.outputs.registry }}/my-app:latest
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
BUILD_DATE=${{ github.event.head_commit.timestamp }}
VERSION=${{ github.sha }}Task Definition Management
任务定义管理
Basic Task Definition
基础任务定义
task-definition.json:
json
{
"family": "my-app-task",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"cpu": "256",
"memory": "512",
"executionRoleArn": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole",
"taskRoleArn": "arn:aws:iam::123456789012:role/ecsTaskRole",
"containerDefinitions": [
{
"name": "my-app",
"image": "PLACEHOLDER_IMAGE",
"portMappings": [
{
"containerPort": 8080,
"protocol": "tcp"
}
],
"environment": [
{
"name": "ENVIRONMENT",
"value": "production"
}
],
"secrets": [
{
"name": "DB_PASSWORD",
"valueFrom": "arn:aws:secretsmanager:us-east-1:123456789012:secret:my-app/db-password"
}
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/my-app",
"awslogs-region": "us-east-1",
"awslogs-stream-prefix": "ecs",
"awslogs-create-group": "true"
}
}
}
]
}task-definition.json:
json
{
"family": "my-app-task",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"cpu": "256",
"memory": "512",
"executionRoleArn": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole",
"taskRoleArn": "arn:aws:iam::123456789012:role/ecsTaskRole",
"containerDefinitions": [
{
"name": "my-app",
"image": "PLACEHOLDER_IMAGE",
"portMappings": [
{
"containerPort": 8080,
"protocol": "tcp"
}
],
"environment": [
{
"name": "ENVIRONMENT",
"value": "production"
}
],
"secrets": [
{
"name": "DB_PASSWORD",
"valueFrom": "arn:aws:secretsmanager:us-east-1:123456789012:secret:my-app/db-password"
}
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/my-app",
"awslogs-region": "us-east-1",
"awslogs-stream-prefix": "ecs",
"awslogs-create-group": "true"
}
}
}
]
}Dynamic Task Definition Update
动态任务定义更新
yaml
- name: Render task definition
uses: aws-actions/amazon-ecs-render-task-definition@v1
id: render-task
with:
task-definition: task-definition.json
container-name: my-app
image: ${{ steps.login-ecr.outputs.registry }}/my-app:${{ github.sha }}
- name: Deploy task definition
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
with:
task-definition: ${{ steps.render-task.outputs.task-definition }}
service: my-service
cluster: my-cluster
wait-for-service-stability: true
deploy_timeout: 30 minutesyaml
- name: Render task definition
uses: aws-actions/amazon-ecs-render-task-definition@v1
id: render-task
with:
task-definition: task-definition.json
container-name: my-app
image: ${{ steps.login-ecr.outputs.registry }}/my-app:${{ github.sha }}
- name: Deploy task definition
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
with:
task-definition: ${{ steps.render-task.outputs.task-definition }}
service: my-service
cluster: my-cluster
wait-for-service-stability: true
deploy_timeout: 30 minutesECS Deployment Strategies
ECS部署策略
Rolling Deployment (Default)
滚动部署(默认)
yaml
- name: Deploy to ECS (Rolling)
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
with:
task-definition: ${{ steps.render-task.outputs.task-definition }}
service: my-service
cluster: my-cluster
wait-for-service-stability: trueCloudFormation Service Configuration:
yaml
ECSService:
Type: AWS::ECS::Service
Properties:
ServiceName: my-service
Cluster: !Ref ECSCluster
TaskDefinition: !Ref TaskDefinition
DeploymentConfiguration:
MaximumPercent: 200
MinimumHealthyPercent: 100
DeploymentCircuitBreaker:
Enable: true
Rollback: true
HealthCheckGracePeriodSeconds: 60
EnableECSManagedTags: true
PropagateTags: SERVICEyaml
- name: Deploy to ECS (Rolling)
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
with:
task-definition: ${{ steps.render-task.outputs.task-definition }}
service: my-service
cluster: my-cluster
wait-for-service-stability: trueCloudFormation服务配置:
yaml
ECSService:
Type: AWS::ECS::Service
Properties:
ServiceName: my-service
Cluster: !Ref ECSCluster
TaskDefinition: !Ref TaskDefinition
DeploymentConfiguration:
MaximumPercent: 200
MinimumHealthyPercent: 100
DeploymentCircuitBreaker:
Enable: true
Rollback: true
HealthCheckGracePeriodSeconds: 60
EnableECSManagedTags: true
PropagateTags: SERVICEBlue/Green Deployment with CodeDeploy
结合CodeDeploy的蓝绿部署
yaml
- name: Deploy to ECS (Blue/Green)
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
with:
task-definition: ${{ steps.render-task.outputs.task-definition }}
service: my-service
cluster: my-cluster
codedeploy-appspec: appspec.yaml
codedeploy-application: my-app
codedeploy-deployment-group: my-deployment-group
wait-for-service-stability: trueappspec.yaml:
yaml
version: 0.0
Resources:
- TargetService:
Type: AWS::ECS::Service
Properties:
TaskDefinition: <TASK_DEFINITION>
LoadBalancerInfo:
ContainerName: my-app
ContainerPort: 8080
PlatformVersion: "1.4.0"CloudFormation CodeDeploy Configuration:
yaml
CodeDeployApplication:
Type: AWS::CodeDeploy::Application
Properties:
ApplicationName: my-app
ComputePlatform: ECS
CodeDeployDeploymentGroup:
Type: AWS::CodeDeploy::DeploymentGroup
Properties:
ApplicationName: !Ref CodeDeployApplication
DeploymentGroupName: my-deployment-group
ServiceRoleArn: !Ref CodeDeployServiceRole
DeploymentConfigName: CodeDeployDefault.ECSAllAtOnce
DeploymentStyle:
DeploymentType: BLUE_GREEN
DeploymentOption: WITH_TRAFFIC_CONTROL
AutoRollbackConfiguration:
Enabled: true
Events:
- DEPLOYMENT_FAILURE
- DEPLOYMENT_STOP_ON_ALARM
- DEPLOYMENT_STOP_ON_REQUEST
AlarmConfiguration:
Alarms:
- !Ref CPUPercentageAlarm
- !Ref MemoryPercentageAlarm
BlueGreenDeploymentConfiguration:
TerminateBlueInstancesOnDeploymentSuccess:
Action: TERMINATE
WaitTimeInMinutes: 5
DeploymentReadyOption:
ActionOnTimeout: CONTINUE_DEPLOYMENT
WaitTimeInMinutes: 0
LoadBalancerInfo:
TargetGroupPairInfoList:
- TargetGroups:
- Ref: BlueTargetGroup
- Ref: GreenTargetGroup
ProdTrafficRoute:
ListenerArns:
- !Ref ProductionListeneryaml
- name: Deploy to ECS (Blue/Green)
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
with:
task-definition: ${{ steps.render-task.outputs.task-definition }}
service: my-service
cluster: my-cluster
codedeploy-appspec: appspec.yaml
codedeploy-application: my-app
codedeploy-deployment-group: my-deployment-group
wait-for-service-stability: trueappspec.yaml:
yaml
version: 0.0
Resources:
- TargetService:
Type: AWS::ECS::Service
Properties:
TaskDefinition: <TASK_DEFINITION>
LoadBalancerInfo:
ContainerName: my-app
ContainerPort: 8080
PlatformVersion: "1.4.0"CloudFormation CodeDeploy配置:
yaml
CodeDeployApplication:
Type: AWS::CodeDeploy::Application
Properties:
ApplicationName: my-app
ComputePlatform: ECS
CodeDeployDeploymentGroup:
Type: AWS::CodeDeploy::DeploymentGroup
Properties:
ApplicationName: !Ref CodeDeployApplication
DeploymentGroupName: my-deployment-group
ServiceRoleArn: !Ref CodeDeployServiceRole
DeploymentConfigName: CodeDeployDefault.ECSAllAtOnce
DeploymentStyle:
DeploymentType: BLUE_GREEN
DeploymentOption: WITH_TRAFFIC_CONTROL
AutoRollbackConfiguration:
Enabled: true
Events:
- DEPLOYMENT_FAILURE
- DEPLOYMENT_STOP_ON_ALARM
- DEPLOYMENT_STOP_ON_REQUEST
AlarmConfiguration:
Alarms:
- !Ref CPUPercentageAlarm
- !Ref MemoryPercentageAlarm
BlueGreenDeploymentConfiguration:
TerminateBlueInstancesOnDeploymentSuccess:
Action: TERMINATE
WaitTimeInMinutes: 5
DeploymentReadyOption:
ActionOnTimeout: CONTINUE_DEPLOYMENT
WaitTimeInMinutes: 0
LoadBalancerInfo:
TargetGroupPairInfoList:
- TargetGroups:
- Ref: BlueTargetGroup
- Ref: GreenTargetGroup
ProdTrafficRoute:
ListenerArns:
- !Ref ProductionListenerCloudFormation Integration
CloudFormation集成
Update Stack from GitHub Actions
通过GitHub Actions更新堆栈
yaml
- name: Deploy CloudFormation stack
run: |
aws cloudformation deploy \
--template-file infrastructure/ecs-stack.yaml \
--stack-name my-app-ecs \
--capabilities CAPABILITY_NAMED_IAM \
--parameter-overrides \
Environment=production \
DesiredCount=2 \
CPU=256 \
Memory=512 \
ImageUrl=${{ steps.login-ecr.outputs.registry }}/my-app:${{ github.sha }}yaml
- name: Deploy CloudFormation stack
run: |
aws cloudformation deploy \
--template-file infrastructure/ecs-stack.yaml \
--stack-name my-app-ecs \
--capabilities CAPABILITY_NAMED_IAM \
--parameter-overrides \
Environment=production \
DesiredCount=2 \
CPU=256 \
Memory=512 \
ImageUrl=${{ steps.login-ecr.outputs.registry }}/my-app:${{ github.sha }}CloudFormation Stack with ECS Resources
包含ECS资源的CloudFormation堆栈
ecs-stack.yaml:
yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: ECS Fargate Service with CloudFormation
Parameters:
Environment:
Type: String
AllowedValues: [dev, staging, prod]
DesiredCount:
Type: Number
Default: 2
CPU:
Type: String
Default: '256'
Memory:
Type: String
Default: '512'
ImageUrl:
Type: String
Resources:
ECSCluster:
Type: AWS::ECS::Cluster
Properties:
ClusterName: !Sub '${Environment}-cluster'
ClusterSettings:
- Name: containerInsights
Value: enabled
TaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
Family: !Sub '${Environment}-task'
Cpu: !Ref CPU
Memory: !Ref Memory
NetworkMode: awsvpc
RequiresCompatibilities:
- FARGATE
ExecutionRoleArn: !GetAtt TaskExecutionRole.Arn
TaskRoleArn: !GetAtt TaskRole.Arn
ContainerDefinitions:
- Name: my-app
Image: !Ref ImageUrl
PortMappings:
- ContainerPort: 8080
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-group: !Ref LogGroup
awslogs-region: !Ref AWS::Region
awslogs-stream-prefix: ecs
ECSService:
Type: AWS::ECS::Service
DependsOn: LoadBalancerListener
Properties:
ServiceName: !Sub '${Environment}-service'
Cluster: !Ref ECSCluster
TaskDefinition: !Ref TaskDefinition
DesiredCount: !Ref DesiredCount
LaunchType: FARGATE
NetworkConfiguration:
AwsvpcConfiguration:
Subnets:
- !Ref PrivateSubnetA
- !Ref PrivateSubnetB
SecurityGroups:
- !Ref ContainerSecurityGroup
AssignPublicIp: DISABLED
LoadBalancers:
- ContainerName: my-app
ContainerPort: 8080
TargetGroupArn: !Ref TargetGroup
DeploymentConfiguration:
MaximumPercent: 200
MinimumHealthyPercent: 100
DeploymentCircuitBreaker:
Enable: true
Rollback: true
HealthCheckGracePeriodSeconds: 60
Outputs:
ServiceURL:
Description: Service URL
Value: !Sub 'http://${LoadBalancer.DNSName}'ecs-stack.yaml:
yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: ECS Fargate Service with CloudFormation
Parameters:
Environment:
Type: String
AllowedValues: [dev, staging, prod]
DesiredCount:
Type: Number
Default: 2
CPU:
Type: String
Default: '256'
Memory:
Type: String
Default: '512'
ImageUrl:
Type: String
Resources:
ECSCluster:
Type: AWS::ECS::Cluster
Properties:
ClusterName: !Sub '${Environment}-cluster'
ClusterSettings:
- Name: containerInsights
Value: enabled
TaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
Family: !Sub '${Environment}-task'
Cpu: !Ref CPU
Memory: !Ref Memory
NetworkMode: awsvpc
RequiresCompatibilities:
- FARGATE
ExecutionRoleArn: !GetAtt TaskExecutionRole.Arn
TaskRoleArn: !GetAtt TaskRole.Arn
ContainerDefinitions:
- Name: my-app
Image: !Ref ImageUrl
PortMappings:
- ContainerPort: 8080
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-group: !Ref LogGroup
awslogs-region: !Ref AWS::Region
awslogs-stream-prefix: ecs
ECSService:
Type: AWS::ECS::Service
DependsOn: LoadBalancerListener
Properties:
ServiceName: !Sub '${Environment}-service'
Cluster: !Ref ECSCluster
TaskDefinition: !Ref TaskDefinition
DesiredCount: !Ref DesiredCount
LaunchType: FARGATE
NetworkConfiguration:
AwsvpcConfiguration:
Subnets:
- !Ref PrivateSubnetA
- !Ref PrivateSubnetB
SecurityGroups:
- !Ref ContainerSecurityGroup
AssignPublicIp: DISABLED
LoadBalancers:
- ContainerName: my-app
ContainerPort: 8080
TargetGroupArn: !Ref TargetGroup
DeploymentConfiguration:
MaximumPercent: 200
MinimumHealthyPercent: 100
DeploymentCircuitBreaker:
Enable: true
Rollback: true
HealthCheckGracePeriodSeconds: 60
Outputs:
ServiceURL:
Description: Service URL
Value: !Sub 'http://${LoadBalancer.DNSName}'Stack Outputs for Cross-Stack References
用于跨堆栈引用的堆栈输出
yaml
Outputs:
ClusterName:
Description: ECS Cluster Name
Value: !Ref ECSCluster
Export:
Name: !Sub '${AWS::StackName}-ClusterName'
ServiceName:
Description: ECS Service Name
Value: !Ref ECSService
Export:
Name: !Sub '${AWS::StackName}-ServiceName'
TaskDefinitionArn:
Description: Task Definition ARN
Value: !Ref TaskDefinition
Export:
Name: !Sub '${AWS::StackName}-TaskDefinitionArn'yaml
Outputs:
ClusterName:
Description: ECS Cluster Name
Value: !Ref ECSCluster
Export:
Name: !Sub '${AWS::StackName}-ClusterName'
ServiceName:
Description: ECS Service Name
Value: !Ref ECSService
Export:
Name: !Sub '${AWS::StackName}-ServiceName'
TaskDefinitionArn:
Description: Task Definition ARN
Value: !Ref TaskDefinition
Export:
Name: !Sub '${AWS::StackName}-TaskDefinitionArn'Best Practices
最佳实践
Security
安全
- Use OIDC authentication instead of long-lived IAM keys
- Implement least privilege IAM roles with specific permissions
- Enable ECR image scanning on push
- Use AWS Secrets Manager for sensitive data
- Encrypt ECR repositories with KMS
- VPC endpoints for ECR and ECS without internet gateway
- Security groups restrict access to minimum required
- 使用OIDC认证替代长期IAM密钥
- 实现最小权限IAM角色,配置特定权限
- 启用ECR镜像推送扫描
- 使用AWS Secrets Manager存储敏感数据
- 通过KMS加密ECR仓库
- 为ECR和ECS配置VPC终端节点,无需互联网网关
- 安全组限制访问,仅开放必要端口
IAM Role Permissions
IAM角色权限
yaml
ECSDeployRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Federated: !Sub 'arn:aws:iam::${AWS::AccountId}:oidc-provider/token.actions.githubusercontent.com'
Action: sts:AssumeRoleWithWebIdentity
Condition:
StringEquals:
token.actions.githubusercontent.com:aud: sts.amazonaws.com
StringLike:
token.actions.githubusercontent.com:sub: repo:${GitHubOrg}/${GitHubRepo}:*
Policies:
- PolicyName: ECSDeployPolicy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- ecs:DescribeServices
- ecs:DescribeTaskDefinition
- ecs:DescribeTasks
- ecs:ListTasks
- ecs:RegisterTaskDefinition
- ecs:UpdateService
Resource: !Sub 'arn:aws:ecs:${AWS::Region}:${AWS::AccountId}:*'
- Effect: Allow
Action:
- ecr:GetAuthorizationToken
- ecr:BatchCheckLayerAvailability
- ecr:GetDownloadUrlForLayer
- ecr:GetRepositoryPolicy
- ecr:DescribeRepositories
- ecr:ListImages
- ecr:DescribeImages
- ecr:BatchGetImage
- ecr:InitiateLayerUpload
- ecr:UploadLayerPart
- ecr:CompleteLayerUpload
- ecr:PutImage
Resource: !Sub 'arn:aws:ecr:${AWS::Region}:${AWS::AccountId}:repository/${ECRRepositoryName}'
- Effect: Allow
Action:
- cloudformation:DescribeStacks
- cloudformation:CreateStack
- cloudformation:UpdateStack
- cloudformation:DescribeStackEvents
Resource: !Sub 'arn:aws:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/${CloudFormationStackName}/*'yaml
ECSDeployRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Federated: !Sub 'arn:aws:iam::${AWS::AccountId}:oidc-provider/token.actions.githubusercontent.com'
Action: sts:AssumeRoleWithWebIdentity
Condition:
StringEquals:
token.actions.githubusercontent.com:aud: sts.amazonaws.com
StringLike:
token.actions.githubusercontent.com:sub: repo:${GitHubOrg}/${GitHubRepo}:*
Policies:
- PolicyName: ECSDeployPolicy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- ecs:DescribeServices
- ecs:DescribeTaskDefinition
- ecs:DescribeTasks
- ecs:ListTasks
- ecs:RegisterTaskDefinition
- ecs:UpdateService
Resource: !Sub 'arn:aws:ecs:${AWS::Region}:${AWS::AccountId}:*'
- Effect: Allow
Action:
- ecr:GetAuthorizationToken
- ecr:BatchCheckLayerAvailability
- ecr:GetDownloadUrlForLayer
- ecr:GetRepositoryPolicy
- ecr:DescribeRepositories
- ecr:ListImages
- ecr:DescribeImages
- ecr:BatchGetImage
- ecr:InitiateLayerUpload
- ecr:UploadLayerPart
- ecr:CompleteLayerUpload
- ecr:PutImage
Resource: !Sub 'arn:aws:ecr:${AWS::Region}:${AWS::AccountId}:repository/${ECRRepositoryName}'
- Effect: Allow
Action:
- cloudformation:DescribeStacks
- cloudformation:CreateStack
- cloudformation:UpdateStack
- cloudformation:DescribeStackEvents
Resource: !Sub 'arn:aws:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/${CloudFormationStackName}/*'Performance
性能
- Docker layer caching with GitHub Actions cache
- Multi-stage builds to minimize image size
- Parallel deployments across multiple environments
- Fargate Spot for cost savings on non-critical workloads
- CloudWatch Logs with appropriate retention policies
- 通过GitHub Actions缓存实现Docker层缓存
- 使用多阶段构建最小化镜像体积
- 多环境并行部署
- 使用Fargate Spot降低非关键工作负载成本
- 配置CloudWatch Logs并设置合适的保留策略
Cost Optimization
成本优化
- ECR lifecycle policies to clean up old images
- Fargate Spot instances for development/testing
- Right-sized task CPU and memory
- Auto-scaling based on metrics
- Scheduled scaling for predictable traffic patterns
- 配置ECR生命周期策略清理旧镜像
- 为开发/测试环境使用Fargate Spot实例
- 合理调整任务CPU与内存规格
- 基于指标实现自动扩缩容
- 为可预测流量配置定时扩缩容
Multi-Environment Deployments
多环境部署
yaml
name: Deploy to ECS
on:
push:
branches: [main, staging, develop]
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
strategy:
matrix:
environment: [dev, staging, prod]
steps:
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/github-actions-ecs-${{ matrix.environment }}
aws-region: us-east-1
- name: Deploy to ${{ matrix.environment }}
run: |
aws cloudformation deploy \
--template-file infrastructure/ecs-stack.yaml \
--stack-name my-app-${{ matrix.environment }} \
--parameter-overrides \
Environment=${{ matrix.environment }} \
ImageUrl=${{ steps.build-image.outputs.image-url }}yaml
name: Deploy to ECS
on:
push:
branches: [main, staging, develop]
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
strategy:
matrix:
environment: [dev, staging, prod]
steps:
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/github-actions-ecs-${{ matrix.environment }}
aws-region: us-east-1
- name: Deploy to ${{ matrix.environment }}
run: |
aws cloudformation deploy \
--template-file infrastructure/ecs-stack.yaml \
--stack-name my-app-${{ matrix.environment }} \
--parameter-overrides \
Environment=${{ matrix.environment }} \
ImageUrl=${{ steps.build-image.outputs.image-url }}Monitoring and Observability
监控与可观测性
- CloudWatch Container Insights for ECS metrics
- Application logs centralized in CloudWatch Logs
- Health checks with proper grace periods
- CloudWatch Alarms for deployment failures
- X-Ray tracing for distributed tracing
- 使用CloudWatch Container Insights获取ECS指标
- 将应用日志集中存储至CloudWatch Logs
- 配置健康检查并设置合理的宽限期
- 配置CloudWatch告警监控部署失败
- 使用X-Ray追踪实现分布式链路追踪
Further Reading
拓展阅读
- Reference Documentation - Detailed technical reference for GitHub Actions syntax, OIDC configuration, ECR operations, task definitions, and CloudFormation integration
- Production Examples - Complete, production-ready workflows including basic deployments, multi-environment setups, blue/green deployments, private ECR with scanning, CloudFormation stack updates, and full CI/CD pipelines with testing
- 参考文档 - GitHub Actions语法、OIDC配置、ECR操作、任务定义及CloudFormation集成的详细技术参考
- 生产示例 - 完整的生产就绪工作流,包括基础部署、多环境配置、蓝绿部署、带扫描的私有ECR、CloudFormation堆栈更新及包含测试的完整CI/CD流水线
Key Concepts
核心概念
- GitHub Actions: Automate workflows from GitHub repository events
- OIDC Authentication: Secure, tokenless authentication between GitHub and AWS
- ECR: Amazon Elastic Container Registry for Docker image storage
- ECS: Amazon Elastic Container Service for container orchestration
- Fargate: Serverless compute engine for ECS without managing servers
- Task Definition: Blueprint for ECS containers (similar to Pod spec in Kubernetes)
- Service: Long-running ECS service with load balancing and auto-scaling
- CloudFormation: Infrastructure as Code for AWS resource management
- Blue/Green Deployment: Zero-downtime deployment strategy with CodeDeploy
- GitHub Actions: 基于GitHub仓库事件自动化工作流
- OIDC Authentication: GitHub与AWS之间的安全无令牌认证
- ECR: 用于存储Docker镜像的Amazon弹性容器注册表
- ECS: 用于容器编排的Amazon弹性容器服务
- Fargate: 无需管理服务器的ECS无服务器计算引擎
- Task Definition: ECS容器的蓝图(类似Kubernetes中的Pod规格)
- Service: 具备负载均衡与自动扩缩容的长期运行ECS服务
- CloudFormation: 用于AWS资源管理的基础设施即代码工具
- Blue/Green Deployment: 结合CodeDeploy实现的零停机部署策略
Common Troubleshooting
常见问题排查
Authentication failures:
- Verify OIDC trust relationship matches GitHub organization/repository
- Check IAM role has proper permissions for ECR and ECS
- Ensure GitHub Actions repository has permission
id-token: write
Deployment failures:
- Check CloudWatch Logs for application errors
- Verify task definition matches service requirements
- Ensure sufficient CPU/memory in Fargate cluster
- Review health check configuration
ECR push failures:
- Verify repository exists and permissions are correct
- Check image tag format and registry URL
- Ensure Docker daemon is running in GitHub Actions runner
- Verify image size doesn't exceed ECR limits
CloudFormation rollback:
- Review stack events in AWS Console
- Check parameter values match resource constraints
- Verify IAM role has permission
cloudformation:UpdateStack - Enable termination protection for production stacks
认证失败:
- 验证OIDC信任关系是否匹配GitHub组织/仓库
- 检查IAM角色是否拥有ECR与ECS的正确权限
- 确保GitHub Actions仓库拥有权限
id-token: write
部署失败:
- 检查CloudWatch Logs中的应用错误
- 验证任务定义是否符合服务要求
- 确保Fargate集群有足够的CPU/内存资源
- 检查健康检查配置
ECR推送失败:
- 验证仓库是否存在且权限配置正确
- 检查镜像标签格式与注册表URL
- 确保GitHub Actions运行器中Docker守护进程已启动
- 验证镜像大小未超出ECR限制
CloudFormation回滚:
- 在AWS控制台查看堆栈事件
- 检查参数值是否符合资源约束
- 验证IAM角色是否拥有权限
cloudformation:UpdateStack - 为生产堆栈启用终止保护
Related Skills
相关技能
- aws-cloudformation-ecs - Design and implement ECS cluster architecture
- aws-sdk-java-v2-ecs - Programmatic ECS management with Java SDK
- aws-cloudformation - Core CloudFormation patterns and best practices
- aws-cloudformation-ecs - 设计并实现ECS集群架构
- aws-sdk-java-v2-ecs - 使用Java SDK实现ECR编程式管理
- aws-cloudformation - CloudFormation核心模式与最佳实践