如何使用Terraform在CodePipeline中运行一次性ECS任务?
解决CodePipeline中执行Django数据库迁移一次性任务的问题
问题分析
你尝试用CodeBuild、CodePipeline和Terraform部署Django应用,但在流水线中启动数据库迁移的一次性任务时遇到问题——当前CodePipeline的ECS阶段配置里,TaskDefinition不是有效参数。这是因为你使用的ECS provider的Deploy类型动作,是用来更新ECS服务的,而非触发一次性任务执行。
解决方案
有两种常用方式实现流水线中的数据库迁移任务:
方案一:用CodeBuild直接执行迁移
无需依赖ECS任务,直接在CodeBuild阶段运行迁移命令。需要确保CodeBuild环境能访问数据库,且已安装Django项目依赖。
修改Terraform配置,添加CodeBuild阶段:
stage { name = "RunMigrations" action { name = "RunMigrationsAction" category = "Build" owner = "AWS" provider = "CodeBuild" version = "1" input_artifacts = ["BuildOutput"] configuration = { ProjectName = aws_codebuild_project.django_migration.name } } } resource "aws_codebuild_project" "django_migration" { name = "django-migration-build" description = "执行Django数据库迁移" build_timeout = "5" source { type = "CODEPIPELINE" buildspec = <<EOF version: 0.2 phases: install: runtime-versions: python: 3.11 commands: - pip install -r requirements.txt build: commands: - export DJANGO_SETTINGS_MODULE=你的项目名.settings.production - python manage.py migrate --noinput EOF } environment { compute_type = "BUILD_GENERAL1_SMALL" image = "aws/codebuild/amazonlinux2-x86_64-standard:4.0" type = "LINUX_CONTAINER" environment_variable { name = "DATABASE_URL" value = var.database_url } # 添加其他必要环境变量,比如SECRET_KEY等 } service_role = aws_iam_role.codebuild-service-role.arn } # 配置CodeBuild角色权限 resource "aws_iam_role" "codebuild-service-role" { name = "codebuild-django-migration-role" assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [ { Action = "sts:AssumeRole" Effect = "Allow" Principal = { Service = "codebuild.amazonaws.com" } } ] }) } resource "aws_iam_role_policy_attachment" "codebuild-policy" { role = aws_iam_role.codebuild-service-role.name policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" # 按需添加数据库访问权限,比如RDS相关权限 }
方案二:通过CodeBuild调用ECS Run Task执行迁移
如果必须用ECS任务执行迁移,可在CodeBuild中通过AWS CLI调用ecs run-task命令触发任务。
stage { name = "RunMigrations" action { name = "RunMigrationsAction" category = "Build" owner = "AWS" provider = "CodeBuild" version = "1" input_artifacts = ["BuildOutput"] configuration = { ProjectName = aws_codebuild_project.django_migration_ecs.name } } } resource "aws_codebuild_project" "django_migration_ecs" { name = "django-migration-ecs-build" description = "触发ECS迁移任务" build_timeout = "5" source { type = "CODEPIPELINE" buildspec = <<EOF version: 0.2 phases: build: commands: - aws ecs run-task --cluster ${var.ecs_cluster_name} --task-definition ${aws_ecs_task_definition.django_migration.family}:${aws_ecs_task_definition.django_migration.revision} --launch-type FARGATE --network-configuration "awsvpcConfiguration={subnets=[${join(",", var.private_subnets)}],securityGroups=[${var.security_group_id}],assignPublicIp=DISABLED}" EOF } environment { compute_type = "BUILD_GENERAL1_SMALL" image = "aws/codebuild/amazonlinux2-x86_64-standard:4.0" type = "LINUX_CONTAINER" } service_role = aws_iam_role.codebuild-ecs-role.arn } # 配置CodeBuild角色的ECS权限 resource "aws_iam_role" "codebuild-ecs-role" { name = "codebuild-django-migration-ecs-role" assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [ { Action = "sts:AssumeRole" Effect = "Allow" Principal = { Service = "codebuild.amazonaws.com" } } ] }) } resource "aws_iam_role_policy" "ecs-run-task-policy" { name = "ecs-run-task-policy" role = aws_iam_role.codebuild-ecs-role.id policy = jsonencode({ Version = "2012-10-17" Statement = [ { Action = [ "ecs:RunTask", "iam:PassRole" ] Effect = "Allow" Resource = [ aws_ecs_task_definition.django_migration.arn, aws_iam_role.ecs-task-execution-role.arn ] } ] }) }
优化ECS任务定义建议
保留你原有的ECS任务定义,但可做以下调整:
- 删除
portMappings配置:迁移任务无需对外暴露端口 - 确保任务执行角色拥有数据库访问权限
内容的提问来源于stack exchange,提问作者Slam Droid
相关产品推荐
相关产品推荐

