将AWS ECS Fargate安排为启动和停止任务

时间:2018-12-19 23:12:24

标签: amazon-web-services aws-fargate

根据AWS文档,他们说:“ Fargate支持调度任务以响应CloudWatch事件。您可以轻松启动和停止仅需在特定时间运行的Fargate任务

可以从CLoudWatch Events或ECS Task Scheduler轻松启用Fargate任务的启动。

但是我找不到Fargate Tasks的STOP。 是否可能需要使用Lambda而不是本机Fargate功能来停止任务?

我的目标是仅在8ap-5pm之间运行ECS容器!

6 个答案:

答案 0 :(得分:3)

我已经采用了建议的代码@ Mr3381并进行了一些改进:

interface EventLambda {
  status: string,
  services: string[]
}

interface UpdateServiceParams {
  cluster: string
  service: string
  desiredCount: number
}

// Load AWS SDK for Node.js
import AWS from 'aws-sdk';

export const handler = async (event: EventLambda): Promise<string[]> => {
  const ecs = new AWS.ECS({region: 'sa-east-1'});
  const promises = new Array<Promise<any>>();
  const desiredCount = event.status == 'start' ? 1 : 0

  event.services.forEach(service => {
      var params: UpdateServiceParams = {
        cluster: process.env.ECS_CLUSTER!,
        service,
        desiredCount
      };
      promises.push(updateService(ecs, params, desiredCount))
    }
  )
  return Promise.all(promises)
};

function updateService(ecs: AWS.ECS, params: UpdateServiceParams, desiredCount: number): Promise<string> {
  return new Promise((resolve, reject) => {
    ecs.updateService(params, function(err, data) {
      if (err) {
        console.log(err, err.stack); // An error occurred
        resolve(`${params.service} not updated`);
      }
      else {
        console.log(data); // Successful response
        resolve(`${params.service} updated => Desired count: ${desiredCount}`)
      }
    });
  })
}

它现在在TypeScript中,并支持一系列服务作为输入。

仅需将其转换为JavaScript即可在AWS上运行。

确保具有执行功能和更新服务所需的权限。这可以通过将ECS中的策略 describeServices updateServices 附加到Lambda函数IAM角色来实现。

答案 1 :(得分:1)

我相信这是解决您办公时间问题的最佳解决方案。

只需使用以下命令在EC2实例中安排本地cron作业即可根据时间戳更新所需的计数,您就可以开始了。

$ aws ecs update-service --cluster <cluster-name> --service <service-name> --desired-count x

如果这对您有帮助,请告诉我。

答案 2 :(得分:0)

与“开始”相同,但是您需要将“所需任务”指定为0。 我的问题是计划程序需要任务定义,因此,如果升级它,则还需要更改计划程序。 存在一些服务,lambda或项目来处理吗? 我需要停止Fargate容器的群集。

答案 3 :(得分:0)

@Francesco Grotta的

答案是正确的。通过我们可以创建以下资源,以按计划触发此操作:

  • lambda函数,用于通过更新ECS服务DesiredCount来启动或停止。
  • 预定的CloudWatch Events,以启动ECS任务。
  • 预定的CloudWatch Events,以停止ECS任务。

基于CloudWatch Events的输入将启动或停止ECS服务的Lambda函数:

    if(event.status == 'stop'){
        var params = {
            cluster: process.env.ECS_CLUSTER,
            service: process.env.ECS_SERVICE_NAME,
            desiredCount: 0
        };
    }
    else{
        var params = {
            cluster: process.env.ECS_CLUSTER,
            service: process.env.ECS_SERVICE_NAME,
            desiredCount: 1
        };
    }

    var ecs = new AWS.ECS();
    ecs.updateService(params, function (err, data) {
        if (err) console.log(err, err.stack); // an error occurred
        else console.log(data);           // successful response
    });

在Cloudformation模板中,创建将按计划调用Lambda函数的资源:

  StartEcsLambdaSchedule:
    Type: AWS::Events::Rule
    Properties:
      Description: >
        A schedule for the Lambda function to start ECS service during office hours.
      ScheduleExpression: !Ref StartEcsLambdaScheduleExpression
      State: ENABLED
      Targets:
        - Arn: !Sub ${EcsTaskScheduleLambdaFunction.Arn}
          Id: StartEcsLambdaScheduleV1
          Input: '{"status": "start"}'

  StopEcsLambdaSchedule:
    Type: AWS::Events::Rule
    Properties:
      Description: >
        A schedule for the Lambda function to stop ECS service after office hours.
      ScheduleExpression: !Ref StopEcsLambdaScheduleExpression
      State: ENABLED
      Targets:
        - Arn: !Sub ${EcsTaskScheduleLambdaFunction.Arn}
          Id: StopEcsLambdaScheduleV1
          Input: '{"status": "stop"}'

答案 4 :(得分:0)

下面将找出所有的qa、uat或dev集群(前提是它们的名字中有字符串qa、uat或dev),然后将其下所有服务的任务数设置为0。只需cron如果您想启动所有非生产环境,请使用此脚本并为 --desired-count 1 创建另一个 cron。创建 /tmp/ecs-stop.log 文件以按原样使用脚本。确保文件是可写的,并且脚本是可执行的,以便 cron 能够运行脚本并写入日志文件。

#!/bin/bash
export AWS_PAGER="" # Doesnt ask user to press q for paginated outputs
export AWS_PROFILE=default
d=$(date +%Y-%m-%d)
for cluster in $(/usr/local/bin/aws ecs list-clusters --output text | awk '{print $2}' | egrep -i 'qa|uat|dev'  )
do 
    echo -e "Cluster ==> $cluster"
    for service in $(/usr/local/bin/aws ecs list-services --cluster $cluster --output text | awk '{print $2}')
    do
        echo "Service ==> Stopping $service..."
        /usr/local/bin/aws ecs update-service --cluster $cluster --service $service --desired-count 0 > /dev/null 2>&1
    done
echo
done
echo "Stopped all non-prod ECS services."
echo "The script ran on $d" >> /tmp/ecs-stop.log

答案 5 :(得分:0)

<块引用>

这是我的解决方案,它高度依赖于一位出色的 AWS 员工 (Alfredo J)。

首先,您需要创建一个 Lambda 函数并添加此 Python 脚本:

import json
import boto3
import logging

logger = logging.getLogger()
logger.setLevel(logging.INFO)

client = boto3.client('ecs')

def lambda_handler(event, context):
    cluster = event["cluster"]
    service_names = event["service_names"]
    service_desired_count = int(event["service_desired_count"])

    for service_name in service_names.split(","):
        response = client.update_service(
            cluster=cluster,
            service=service_name,
            desiredCount=service_desired_count
            )

        logger.info("Updated {0} service in {1} cluster with desire count set to {2} tasks".format(service_name, cluster, service_desired_count))
        
    return {
        'statusCode': 200,
        'new_desired_count': service_desired_count
    }

脚本需要以下 JSON 格式的变量:

{
  "cluster": "clusterName",
  "service_names": "service1,service2",
  "service_desired_count": "0"
}

地点:

  • cluster 是您要修改的集群的名称。
  • service_names 是服务集合的数组。
  • service_desired_count 是所需服务的数量。 0 是停止服务/秒,任何其他数字是启动服务/秒。

创建完所有内容后,您需要在 Amazon EventBridge(以前称为 CloudWatch Events)中创建一些规则。在这里,您可以根据预期的时间表定义要触发的事件。

如果出现故障,您需要仔细检查创建的 IAM 角色是否具有所需的策略,例如:ecs:UpdateService。您可以从日志中检查这一点。