如何避免在带有 Amazon Linux 1 AMI 且磁盘空间不足的 Amazon ECS 容器实例上放置任务?

2 分钟阅读
0

我使用带有 Amazon Linux 1 Amazon 系统映像 (AMI) 的 Amazon Elastic Container Service (Amazon ECS) 容器实例。但是,我无法在磁盘空间不足的具有 Linux 1 AMI 的 Amazon ECS 容器实例上启动任务。在 Docker Daemon 尝试从 Docker 镜像存储库中提取 Docker 镜像,然后再运行任务时,就会发生这种情况。我该如何预防此问题?

简短描述

使用 Amazon Elastic Compute Cloud (Amazon EC2) 启动类型来启动任务时,Amazon ECS 不会考虑容器实例上的磁盘空间可用性。Amazon ECS 根据任务定义中指定的要求(例如 CPU、内存和端口)来确定 放置任务的位置。 要解决此问题,您可以使用用于监控磁盘空间的磁盘空间监控脚本。该脚本会返回一个值,该值显示 Amazon ECS 容器实例上的可用磁盘空间。返回的值与容器实例关联,采用自定义属性的形式。与容器实例配置文件关联的 AWS Identity and Access Management (IAM) 角色必须拥有更新此自定义属性值的权限。

然后,使用任务定义指定任务放置约束条件,该约束条件会限制在磁盘空间不足的容器实例上放置任务。

**注意:**Amazon Linux 1 的支持服务将于 2020 年 12 月 31 日终止。最佳做法是在支持终止之前将工作负载迁移到 Amazon Linux 2。

解决方法

启动带有为 Amazon ECS 优化的 Amazon Linux AMI 的容器实例

**重要提示:**最佳做法是启动带有配置了多个可用区的 Auto Scaling 组的实例。您可以添加命令来引导启动配置用户数据中的实例。

注意:如果您在运行 AWS 命令行界面 (AWS CLI) 命令时收到错误,请确保您运行的是最新版本的 AWS CLI

1.    运行以下命令,以在容器实例启动配置的用户数据部分安装 AWS CLI 和 jq 包。有关更多信息,请参阅 jq 网站上的 ./jq

yum install -y aws-cli jq

**注意:**用户数据部分通过在启动时运行命令来引导 Amazon EC2 实例。

2.    打开 IAM 控制台,然后创建以下内联策略

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "ecs:PutAttributes",
            "Resource": "*"
        }
    ]
}

**重要提示:**上述策略使用通配符参数,该参数允许主体为账户中的任何兼容资源(容器实例)调用 ecs:PutAttributes。该示例是为了便于使用,而最佳做法是尽可能授予最低权限。有关更多信息,请参阅 Amazon Elastic Container Service 基于身份的策略示例。以下示例策略将调用限制为仅对特定集群中的容器实例进行调用:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ecs:PutAttributes"
            ],
            "Resource": [
                "arn:aws:ecs:<region>:<accountId>:container-instance/<clusterName>/*"
            ]
        }
    ]
}

3.    将内联策略ecsInstanceRole IAM 角色关联。

**注意:**IAM 权限在 AWS CLI 中使用 aws ecs put-attribute 命令将 SpaceLeft 自定义属性与容器实例关联。SpaceLeft 自定义属性由磁盘空间监视脚本计算。

在 Amazon ECS 容器实例上安装并运行磁盘空间监视脚本

1.    要监视集群的磁盘空间(以 GB 为单位),请在容器实例上安装以下脚本:

#! /usr/bin/env bash
set -o pipefail
set -o nounset
set -o errexit

until curl -s http://localhost:51678/v1/metadata
do
   sleep 1
done

clusterName=$(curl -s http://localhost:51678/v1/metadata | jq .Cluster | tr -d '"' )
SpaceLeft=$(docker info | grep 'Data Space Available' | cut -d':' -f2)
Unit=$(echo "$SpaceLeft" | grep -o '..$')
if [ "$Unit" != GB ]; then
    SpaceLeft=$(echo "$SpaceLeft" | sed 's/[A-Za-z]*//g' | cut -d '.' -f1)
    SpaceLeftValue=$(echo "$SpaceLeft" | awk '{$1=$1/(1000); print $1;}')
else
        SpaceLeftValue=$(echo "$SpaceLeft" | sed 's/[A-Za-z]*//g')
fi

instanceArn=$(curl -s http://localhost:51678/v1/metadata | jq -r '. | .ContainerInstanceArn' | awk -F/ '{print $NF}' )
region=$(curl -s http://localhost:51678/v1/metadata | jq -r '. | .ContainerInstanceArn' | awk -F: '{print $4}')

aws ecs put-attributes \
  --cluster "$clusterName" \
  --attributes name="SpaceLeft",value="$SpaceLeftValue",targetType="container-instance",targetId="$instanceArn" \
  --region "$region"

**注意:**您可以将脚本命名为 diskspaceMonitoring.sh,然后将其添加到集群中每个 Amazon ECS 容器实例上的 /home/ec2-user/diskspaceMonitoring.sh 路径。您也可以在容器实例启动配置上的用户数据中指定磁盘空间监控脚本。

2.    在容器实例上,运行以下脚本:

$echo "* * * * * root /home/ec2-user/diskspaceMonitoring.sh" >> /etc/crontab

**注意:**您可以将脚本作为 cron 作业的一部分以一分钟的间隔定期运行。您也可以选择不同的时间间隔。您可以将脚本添加到启动配置上的用户数据中。

3.    打开 Amazon ECS 控制台,然后通过 Amazon ECS 任务定义创建任务放置限制。例如:

"placementConstraints": [
    {
        "expression": "attribute:SpaceLeft >= 0.1",
        "type": "memberOf"
    }
]

相关的任务定义现在具有放置约束条件,该约束条件会限制在磁盘空间不足的容器实例上放置任务。


相关信息

CannotCreateContainerError:API 错误 (500):devmapper

AMI 存储配置

相关视频

AWS 官方
AWS 官方已更新 3 年前