web-dev-qa-db-fra.com

création d'une «cible» pour une règle d'événement cloudwatch via cloudformation pour une tâche de type de lancement fargate

J'essaie de créer une tâche planifiée (règle d'événements CloudWatch) dans mon modèle CloudFormation qui aurait les paramètres Ecs suivants:

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

Mon ECS CLuster est lancé sur Fargate et non EC2, et je n'ai PAS de service en cours d'exécution (le cas d'utilisation n'a pas besoin d'un processus long, planifiant directement les tâches à partir des règles d'événements).

Chaque fois que j'exécute ce modèle (avec LaunchType et NetworkConfiguration), la création de la pile échoue, avec cette erreur:

Propriété non prise en charge rencontrée NetworkConfiguration


Comme alternative, j'ai également essayé de lancer la tâche planifiée à partir de l'AWS CLI, mais il semble que les options de configuration réseau et de type de lancement ne soient pas disponibles non plus:

Échec de la validation des paramètres: paramètre inconnu dans les cibles [0] .EcsParameters: "LaunchType", doit être l'un de: TaskDefinitionArn, TaskCount


Selon cette page sur la documentation AWS elle-même, je devrais pouvoir spécifier LaunchType et NetworkConfiguration dans ma section EcsParameters dans Targets dans Properties du AWS::Events::Rule Ressource.

Y a-t-il quelque chose que je puisse essayer qui pourrait fonctionner?

11
tanvi

CloudFormation n'a pas encore rattrapé les paramètres nécessaires pour exécuter une tâche Fargate en tant que cible directe d'une règle d'événements CloudWatch. En attendant, vous pouvez obtenir le même résultat en faisant en sorte que la règle cible une fonction Lambda qui exécute la tâche Fargate.

Pour que cela fonctionne, la règle des événements aura besoin de lambda:InvokeFunction autorisation sur la fonction Lambda, et la fonction Lambda aura besoin du ecs:RunTask et iam:PassRole autorisation sur les ressources appropriées (en plus des autorisations de journaux habituelles dans AWSLambdaBasicExecutionRole).

Edit: Voici un exemple de modèle CF qui montre de quoi je parle. (Il est reconstitué et simplifié à partir de ce que nous utilisons, donc non testé, mais illustre, espérons-le, le processus.)

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

Je définis la fonction Lambda dans ma pile de cluster, où j'ai déjà les paramètres ClusterName, Subnets et SecurityGroups, et je peux les transmettre directement à l'environnement Lambda. L'autorisation de planification et d'appel peut ensuite être définie dans une ou plusieurs piles distinctes, en transmettant le TaskDefinition pour chaque tâche via l'entrée de la fonction Lambda. De cette façon, vous pouvez avoir une Lambda par cluster mais utiliser autant de tâches différentes que nécessaire. Vous pouvez également ajouter une chaîne de commande personnalisée et/ou d'autres remplacements de conteneur à l'entrée Lambda qui peuvent être transmis via le paramètre overrides de run_task.

Edit # 2: Voici un exemple de définition de tâche Fargate qui peut aller dans un modèle CF:

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
4
chadawagner

Même si AWS n'a pas mis à jour la documentation aujourd'hui (15 juillet 2019), cela fonctionne comme décrit par l'affiche initiale.

2
Sebastian Annies

Après une journée de recherche, il semble qu'AWS n'ait toujours pas pris en charge cette fonctionnalité via CloudFormation. Cependant, voici une alternative qui a fonctionné à travers le aws events put-targets commande sur le cli.

Cette méthode échoue pour les anciennes versions de la cli. exécutez ceci pour mettre à jour: pip install awscli --upgrade --user Voici la version sur laquelle je suis actuellement: aws-cli/1.16.9 Python/2.7.15 Darwin/17.7.0 botocore/1.11.9

Utilisez le aws events put-targets --rule <value> --targets <value> commande. Assurez-vous que vous disposez d'une règle déjà définie sur votre cluster. Sinon, vous pouvez le faire avec le aws events put-rule cmd. Reportez-vous aux documents AWS pour put-rule , et pour put-target .

Un exemple de règle de la documentation est donné ci-dessous:

aws events put-rule --name "DailyLambdaFunction" --schedule-expression "cron(0 9 * * ? *)"

La commande put-target qui a fonctionné pour moi est la suivante:

aws events put-targets --rule cli-RS-rule --targets '{"Arn": "arn:aws:ecs:1234/cluster/clustername","EcsParameters": {"LaunchType": "FARGATE","NetworkConfiguration": {"awsvpcConfiguration": {"AssignPublicIp": "ENABLED", "SecurityGroups": [ "sg-id1233" ], "Subnets": [ "subnet-1234" ] }},"TaskCount": 1,"TaskDefinitionArn": "arn:aws:ecs:1234:task-definition/taskdef"},"Id": "sampleID111","RoleArn": "arn:aws:iam:1234:role/eventrole"}'
2
tanvi