【问题标题】:How to run AWS ECS Task with CloudFormation overriding container environment variables如何使用 CloudFormation 覆盖容器环境变量运行 AWS ECS 任务
【发布时间】:2021-05-16 17:04:58
【问题描述】:

我正在寻找一种运行 ecs 任务的方法。我已经有了集群和任务定义设置。我只是想使用 CloudFormation 模板触发任务。我知道我可以通过单击控制台来运行任务并且它工作正常。对于cfn,方法需要正确定义。

检查随附的屏幕截图。我想使用 CloudFormation 运行该任务并传递容器覆盖环境变量。根据我当前的模板,它不允许我像使用控制台那样做同样的事情。使用控制台我只需要选择以下选项

  1. Launch type 
  2. Task Definition 
              Family
              Revision 
  3. VPC and security groups 
  4. Environment variable overrides rest of the things automatically selected

它开始使用控制台,但使用 cloudformaton 模板我们如何做到这一点。有没有可能做或者没有这个功能?

      "taskdefinition": {
    "Type" : "AWS::ECS::TaskDefinition",
    "DependsOn": "DatabaseMaster",
    "Properties" : {
        "ContainerDefinitions" : [{
            "Environment" : [
              {
                 "Name" : "TARGET_DATABASE",
                 "Value" : {"Ref":"DBName"}
              },
              {
                 "Name" : "TARGET_HOST",
                 "Value" : {"Fn::GetAtt": ["DatabaseMaster", "Endpoint.Address"]}
              }
            ]
          }],
        "ExecutionRoleArn" : "arn:aws:iam::xxxxxxxxxx:role/ecsTaskExecutionRole",
        "Family" : "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
        "TaskRoleArn" : "arn:aws:iam::xxxxxxxxxxxxxxx:role/xxxxxxxxxxxxxxx-XXXXXXXXX"
    }
  },
  "EcsService": {
    "Type" : "AWS::ECS::Service",
    "Properties" : {
        "Cluster" : "xxxxxxxxxxxxxxxxx",
        "LaunchType" : "FARGATE",
        "NetworkConfiguration" : {
               "AwsvpcConfiguration" : {
                      "SecurityGroups" : ["sg-xxxxxxxxxxx"],
                      "Subnets" : ["subnet-xxxxxxxxxxxxxx"]
                      }
           },
        "TaskDefinition" : "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
      }
  }

代码中没有有效性错误,我说的是方法。我添加了图像名称容器名称,但现在它要求内存和 cpu,它不应该要求,因为它已经定义我们只需要运行一个任务。

已编辑

我想在创建数据库后运行任务,并希望将这些数据库值传递给任务以运行并完成作业。

【问题讨论】:

    标签: json amazon-web-services amazon-cloudformation amazon-ecs


    【解决方案1】:

    如果您想传递变量并运行任务,这是一个工作示例。就我而言,我想在创建数据库后运行一个任务,但使用环境变量,直接 AWS 不提供任何功能,这是可以帮助触发您的 ecs 任务的解决方案。

    "IAMRole": {
        "Type": "AWS::IAM::Role",
        "Properties": {
          "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [
              {
                "Effect": "Allow",
                "Principal": {
                  "Service": [
                    "events.amazonaws.com"
                  ]
                },
                "Action": [
                  "sts:AssumeRole"
                ]
              }
            ]
          },
          "Description": "Allow CloudWatch Events to trigger ECS task",
          "Policies": [
            {
              "PolicyName": "Allow-ECS-Access",
              "PolicyDocument": {
                "Version": "2012-10-17",
                "Statement": [
                  {
                    "Effect": "Allow",
                    "Action": [
                      "ecs:*",
                      "iam:PassRole",
                      "logs:CreateLogStream",
                      "logs:PutLogEvents"
                    ],
                    "Resource": "*"
                  }
                ]
              }
            }
          ],
          "RoleName": { "Fn::Join": [ "", ["CloudWatchTriggerECSRole-", { "Ref": "DBInstanceIdentifier" }]]}
        }
      },
      "DummyParameter": {
          "Type" : "AWS::SSM::Parameter",
          "Properties" : {
              "Name" : {"Fn::Sub": "${AWS::StackName}-${DatabaseMaster}-EndpointAddress"},
              "Type" : "String",
              "Value" : {"Fn::GetAtt": "DatabaseMaster.Endpoint.Address"}
          },
          "DependsOn": "TaskSchedule"
      },
      "TaskSchedule": {
        "Type": "AWS::Events::Rule",
        "Properties": {
          "Description": "Trigger ECS task upon creation of DB instance",
          "Name": { "Fn::Join": [ "", ["ECSTaskTrigger-", { "Ref": "DBName" }]]},
          "RoleArn": {"Fn::GetAtt": "IAMRole.Arn"},
          "EventPattern": {
              "source": [ "aws.ssm" ],
              "detail-type": ["Parameter Store Change"] ,
              "resources": [{"Fn::Sub":"arn:aws:ssm:eu-west-1:XXXXXXX:parameter/${AWS::StackName}-${DatabaseMaster}-EndpointAddress"}],
              "detail": {
                  "operation": ["Create"],
                  "name": [{"Fn::Sub": "${AWS::StackName}-${DatabaseMaster}-EndpointAddress"}],
                  "type": ["String"]
              }
          },
          "State": "ENABLED",
          "Targets": [
            {
              "Arn": "arn:aws:ecs:eu-west-1:xxxxxxxx:cluster/NameOf-demo",
              "Id": "NameOf-demo",
              "RoleArn": {"Fn::GetAtt": "IAMRole.Arn"},
              "EcsParameters": {
                "LaunchType": "FARGATE",
                "NetworkConfiguration": {
                  "AwsVpcConfiguration": {
                    "SecurityGroups": {"Ref":"VPCSecurityGroups"},
                    "Subnets": {"Ref":"DBSubnetName"}
                  }
                },
                "PlatformVersion": "LATEST",
                "TaskDefinitionArn": "arn:aws:ecs:eu-west-1:XXXXXXXX:task-definition/NameXXXXXXXXX:1"
              },
              "Input": {"Fn::Sub": [
                  "{\"containerOverrides\":[{\"name\":\"MyContainerName\",\"environment\":[{\"name\":\"VAR1\",\"value\":\"${TargetDatabase}\"},{\"name\":\"VAR2\",\"value\":\"${TargetHost}\"},{\"name\":\"VAR3\",\"value\":\"${TargetHostPassword}\"},{\"name\":\"VAR4\",\"value\":\"${TargetPort}\"},{\"name\":\"VAR5\",\"value\":\"${TargetUser}\"},{\"name\":\"VAR6\",\"value\":\"${TargetLocation}\"},{\"name\":\"VAR7\",\"value\":\"${TargetRegion}\"}]}]}",
                  {
                      "VAR1":      {"Ref":"DBName"},
                      "VAR2":          {"Fn::GetAtt": ["DatabaseMaster", "Endpoint.Address"]},
                      "VAR3":  {"Ref":"DBPassword"},
                      "VAR4":          "5432",
                      "VAR5":          {"Ref":"DBUser"},
                      "VAR6":      "value6",
                      "VAR7":        "eu-west-2"
                  }
              ]}
            }
          ]
        }
      }
    

    【讨论】:

      【解决方案2】:

      对于 Fargate 任务,我们需要在 CPU 中指定Task Definition。以及任务或容器定义中的内存或内存预留。

      环境变量应作为 ContainerDefinitions 传递给每个容器,并在从 ecs task-run from console 或 cli 运行任务时覆盖。

      {
         "ContainerTaskdefinition": {
            "Type": "AWS::ECS::TaskDefinition",
            "Properties": {
               "Family": "SomeFamily",
               "ExecutionRoleArn": !Ref RoleArn,
               "TaskRoleArn": !Ref TaskRoleArn,
               "Cpu": "256",
               "Memory": "1GB",
               "NetworkMode": "awsvpc",
               "RequiresCompatibilities": [
                  "EC2",
                  "FARGATE"
               ],
               "ContainerDefinitions": [
                  {
                     "Name": "container name",
                     "Cpu": 256,
                     "Essential": "true",
                     "Image": !Ref EcsImage,
                     "Memory": "1024",
                     "LogConfiguration": {
                        "LogDriver": "awslogs",
                        "Options": {
                           "awslogs-group": null,
                           "awslogs-region": null,
                           "awslogs-stream-prefix": "ecs"
                        }
                     },
                     "Environment": [
                        {
                           "Name": "ENV_ONE_KEY",
                           "Value": "Valu1"
                        },
                        {
                           "Name": "ENV_TWO_KEY",
                           "Value": "Valu2"
                        }
                     ]
                  }
               ]
            }
         }
      }
      

      编辑(来自 cmets 的讨论): ECS Task Run 不是成云资源,只能从控制台或 CLI 运行。 但如果我们选择从 cloudformation 资源运行,则可以使用 cloudformation 自定义资源来完成。但是一旦任务结束,我们现在拥有 cloudformation 中的资源,而背后没有实际资源。所以,自定义资源需要做:

      • 在创建时:运行任务。
      • 删除时:什么都不做。
      • 更新时:重新运行任务

      每次我们需要运行任务时,通过更改属性或逻辑 ID 来强制更新。

      【讨论】:

      • 但是,使用控制台没有这样的选项。如果我们的任务定义已经定义了,那为什么还要重新定义呢?
      • 所以,您已经手动创建了任务定义,您只想在 cloudformation 中创建服务,但是您的 cloudformation 模板正在尝试再次创建任务定义,但您只需要创建一个使用现有任务定义的服务正确,您需要 CF 吗?
      • 我使用 cdk 创建了任务定义,我可以调整 cdk 以按计划运行,但这不是必需的,我只想在执行 CloudFormation 模板时运行任务来运行我的解决方案。所以这就是为什么我在 CloudFormation 中添加任务运行部分,只在需要时运行。现在的问题是我如何才能像使用控制台一样实现这一点,而我不需要提到 cpu ram 等。我说的是任务而不是服务。运行一个任务而已。创建服务是另一回事。请看截图
      • 我不认为任务运行是实际资源,所以,我们需要一个服务或调度任务。我们可能可以使用自定义资源运行任务,但是如果该任务完成或死亡会发生什么情况,我们是否对云形式的资源感到震惊而没有实际资源?但我想,使用运行任务的自定义资源,您可以触发对资源的一些更改以重新触发再次创建任务的更新资源,从 cf 中删除资源会简单地忽略?
      • 我的任务只是一个从 s3 恢复数据库并在恢复成功或不成功后停止的工作。它刚刚被杀死,使用控制台我可以做到这一点并且它工作正常但是使用cfn cab w 如何做到这一点?因为这不是一个计划,它应该在创建数据库之后运行,因为在我的模板数据库中正在创建,所以之后我需要从 s3 恢复备份并且我的任务正在做这项工作,为了自动化这些东西,我需要触发带有变量的任务,这将使其更加通用和可重用。
      猜你喜欢
      • 1970-01-01
      • 2016-07-09
      • 2017-09-05
      • 2019-08-17
      • 2011-02-12
      • 2017-10-14
      • 2016-12-28
      • 1970-01-01
      • 2020-06-01
      相关资源
      最近更新 更多