我正在尝试在CloudFormation模板中创建一个计划任务(CloudWatch Events规则),该任务将具有以下EcsParameters:

EcsParameters:
        LaunchType: FARGATE
        NetworkConfiguration:
          AwsVpcConfiguration:
            AssignPublicIp: !Ref PublicIpAssignment
            SecurityGroups:
              - !Ref EcsSecurityGroups
            Subnets:
              - !Ref SubnetName
        TaskCount: 1
        TaskDefinitionArn: !Ref TaskDefinitionOne

我的ECS CLuster是在Fargate而非EC2上启动的,并且我没有运行任何服务(用例不需要长时间运行的流程,可以直接从事件规则中安排任务。)

每当我运行此模板(使用LaunchTypeNetworkConfiguration)时,堆栈创建都会失败,并显示以下错误:



另外,我也尝试从AWS CLI启动计划的任务,但是似乎那里的网络配置和启动类型选项也不可用:



根据AWS文档本身上的this page,我应该能够在LaunchType资源的NetworkConfigurationEcsParametersTargets中的Properties部分中指定AWS::Events::Rule和ojit_code。

我有什么可以尝试的方法吗?

最佳答案

CloudFormation尚未 catch 运行Fargate任务作为CloudWatch Events Rule的直接目标所需的参数。同时,通过将规则目标定位为运行Fargate任务的Lambda函数,可以达到相同的结果。

为此,事件规则将需要对Lambda函数具有lambda:InvokeFunction权限,而Lambda函数将需要对相应资源的ecs:RunTaskiam:PassRole权限(除了AWSLambdaBasicExecutionRole中的常规日志权限)。

编辑:这是一个示例CF模板,显示了我在说什么。 (它被拼凑起来并从我们正在使用的内容中简化了,因此未经测试,但希望能说明该过程。)

Parameters:
  #ClusterName
  #Subnets
  #SecurityGroups
  #CronExpression
  #TaskDefinitionArn
  #TaskRoleArn
  #ExecutionRoleArn

Resources:
  FargateLauncherRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub ${AWS::StackName}-FargateLauncher-${AWS::Region}
      AssumeRolePolicyDocument:
        Statement:
          -
            Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
      Path: /

  FargateLauncherPolicy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyName: !Sub ${AWS::StackName}-FargateLauncher-${AWS::Region}
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          -
            Sid: RunTaskAccess
            Effect: Allow
            Action:
              - ecs:RunTask
            Resource: '*'
          -
            Sid: PassRoleAccess
            Effect: Allow
            Action:
              - iam:PassRole
            Resource:
              # whatever you have defined in your TaskDefinition, if any
              - !Ref TaskRoleArn
              - !Ref ExecutionRoleArn
      Roles:
        - !Ref FargateLauncherRole

  FargateLauncher:
    Type: AWS::Lambda::Function
    DependsOn: FargateLauncherPolicy
    Properties:
      Environment:
        Variables:
          CLUSTER_NAME: !Ref ClusterName
          SUBNETS: !Ref Subnets
          SECURITY_GROUPS: !Ref SecurityGroups
      Handler: index.handler
      Role: !GetAtt FargateLauncherRole.Arn
      Runtime: python3.6
      Code:
        ZipFile: |
          from os import getenv
          from boto3 import client
          ecs = client('ecs')

          def handler(event, context):
            ecs.run_task(
              cluster=getenv('CLUSTER_NAME'),
              launchType='FARGATE',
              taskDefinition=event.get('taskDefinition'),
              count=1,
              platformVersion='LATEST',
              networkConfiguration={'awsvpcConfiguration': {
                'subnets': getenv('SUBNETS').split(','),
                'securityGroups': getenv('SECURITY_GROUPS').split(','),
                'assignPublicIp': 'DISABLED'
              }})

  Schedule:
    Type: AWS::Events::Rule
    Properties:
      ScheduleExpression: !Sub "cron(${CronExpression})"
      State: ENABLED
      Targets:
        -
          Id: fargate-launcher
          Arn: !GetAtt FargateLauncher.Arn
          Input: !Sub |
            {
              "taskDefinition": "${TaskDefinitionArn}"
            }

  InvokePermission:
    Type: AWS::Lambda::Permission
    Properties:
      FunctionName: !Ref FargateLauncher
      Action: lambda:InvokeFunction
      Principal: events.amazonaws.com
      SourceArn: !GetAtt Schedule.Arn

我在集群堆栈中定义了Lambda函数,其中已经有了ClusterNameSubnetsSecurityGroups参数,并且可以将它们直接传递给Lambda环境。然后可以在一个或多个单独的堆栈中定义调度和调用权限,并通过Lambda函数的输入为每个任务传递TaskDefinition。这样,每个群集可以有一个Lambda,但可以根据需要使用许多不同的任务。您还可以向Lambda输入添加自定义命令字符串和/或其他容器替代,这些替代可以通过overridesrun_task参数传递。

编辑#2 :
这是可以在CF模板中使用的Fargate TaskDefinition示例:
TaskDefinition:
  Type: AWS::ECS::TaskDefinition
  Properties:
    Family: !Ref Family
    Cpu: !Ref Cpu
    Memory: !Ref Memory
    NetworkMode: awsvpc
    ExecutionRoleArn: !Ref ExecutionRoleArn
    TaskRoleArn: !Ref TaskRoleArn
    RequiresCompatibilities:
      - FARGATE
    ContainerDefinitions:
      - Name: !Ref ContainerName
        Essential: true
        Image: !Ref Image
        LogConfiguration:
          LogDriver: awslogs
          Options:
            awslogs-group: !Ref LogGroup
            awslogs-region: !Ref AWS::Region
            awslogs-stream-prefix: !Ref LogPrefix

关于amazon-web-services - 通过cloudformation为fargate launchtype任务为cloudwatch事件规则创建 'Target',我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52208700/

10-11 09:10
查看更多