使用Lambda进行ECS自动部署

时间:2019-11-25 16:43:24

标签: amazon-web-services aws-lambda amazon-ecs

我快要结束了这一件事。我目前正在为AWS应用程序设置自动部署。该应用程序在没有负载均衡器的ECS内部运行。

这里的想法是,当将新的Docker映像推送到ECR时,cloudTrail会获取日志,cloudWatch触发并发出警报,该警报会发给SNS,而SNS会触发lambda进行部署。到目前为止,除了lambda之外,我都能正常工作。

我正在使用的代码在python中,如下所示:

import boto3
import pprint
import os

region = "us-east-2"
client = boto3.client('ecs', region_name=region)


response = client.list_task_definitions(familyPrefix= 'stage-dcs-task-000', status='ACTIVE')

def lambda_handler(event, context):
    response = client.register_task_definition(
        family='stage-dcs-task-000',
        networkMode='bridge',
        containerDefinitions=[
            {
                'name': 'dcs-stage-container-000',
                'image': 'ecrUrlHere:latest',
                'cpu': 10,
                'memory': 500,
                'portMappings': [
                    {
                        'containerPort': 8080,
                        'hostPort': 80,
                        'protocol': 'tcp'
                    },
                ],
                'essential': True,
            },
        ],
    )
    taskDefinitionRev = response['taskDefinition']['family'] + ':' + str(response['taskDefinition']['revision'])


    response = client.update_service(
        cluster='stage-secretName-conversation-service',
        service='stage-dcs-service-000',
        desiredCount=1,
        taskDefinition=taskDefinitionRev,
        deploymentConfiguration={
            'maximumPercent': 200,
            'minimumHealthyPercent': 100
        },
        forceNewDeployment=True
    )

现在,此lambda失败,并显示错误

  "errorMessage": "An error occurred (InvalidParameterException) when calling the UpdateService operation: The container stage-dcs-container-000is not valid. The value for 'containerName' must already be specified in the task definition. Registry: ARN-LINK-HERE"

查看在AWS中创建的内容,正确创建任务定义,并正确命名和配置容器。根据我对文档的了解,我对update-service的调用是正确的,我只是不知道为什么容器名称无效。

有趣的是,我虽然容器名称可能必须是唯一的。因此,我开始将任务修订版号添加到容器名称的末尾,以代替000,但是,我总是找回stage-dcs-container-000作为无效名称,并且不知道它可能来自何处。这里有什么想法吗?

进行更多调试后,我发现引发当前错误的是当前任务定义中的容器名称。根据容器名称规则,我不能使用破折号,因此我将其改为下划线,但是相同的问题仍然存在。

资源:这是我一直关注的教程https://medium.com/@YadavPrakshi/automate-zero-downtime-deployment-with-amazon-ecs-and-lambda-c4e49953273d

1 个答案:

答案 0 :(得分:0)

我花了一些时间才弄清楚这一点,但最终我解决了。实话实说,我不是100%知道修复的内容,但是我知道至少有两个错误。

第一个事实是,我以某种方式设法陷入了我在堆栈不同部分的名称中包含非法字符的状态。举一个明确的例子,在容器名称中我使用破折号(-),这是一个非法字符。为了解决这个问题,最终使用骆驼壳重新创建了整个技术堆栈。

第二个是我在lambda函数中有一些错误,特别是在创建任务修订版时。我最终注意到通过cli创建东西时,我以某种方式错过了docker要求。我如何解决这个问题是我在AWS领事中创建了任务修订版,然后将json复制到了lambda内部的register_task_definition方法中。这就是我从“ DID NOT WORK”开始的过程。

response = client.register_task_definition(
        family='stage-dcs-task-000',
        networkMode='bridge',
        containerDefinitions=[
            {
                'name': 'dcs-stage-container-000',
                'image': 'ecrUrlHere:latest',
                'cpu': 10,
                'memory': 500,
                'portMappings': [
                    {
                        'containerPort': 8080,
                        'hostPort': 80,
                        'protocol': 'tcp'
                    },
                ],
                'essential': True,
            },
        ],
    )

这就是我完成的工作。

response = client.register_task_definition(
        containerDefinitions=[
            {
                "portMappings": [
                    {
                        "hostPort": 80,
                        "protocol": "tcp",
                        "containerPort": 8080
                    }
                ],
                "cpu": 10,
                "environment": [],
                "mountPoints": [],
                "memoryReservation": 500,
                "volumesFrom": [],
                "image": "image uri here",
                "essential": True,
                "name": "productionDCSContainer"
            }
        ],
        family="productionDCSTask",
        requiresCompatibilities=[
            "EC2"
        ],
        networkMode="bridge"
    )

应该注意的是,很容易陷入死锁版本更新的状态,也就是说,您具有诸如minPercentage = 100,maxPercentage = 100且期望值为1之类的东西。在这种情况下,AWS永远不会杀死正在运行的实例以启动更新。解决方法是让minInstance = 0,maxInstance = 200%,并让forceNewDeployment = True。