diff --git a/integration/systemd/amazon-ecs-agent.service b/integration/systemd/amazon-ecs-agent.service new file mode 100644 index 00000000..d56b0d5f --- /dev/null +++ b/integration/systemd/amazon-ecs-agent.service @@ -0,0 +1,152 @@ +# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the +# "License"). You may not use this file except in compliance +# with the License. A copy of the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and +# limitations under the License. + +# A systemd unit file to run `ecs-agent` in a Docker container. This service +# attempts to duplicate the functionality of the `ecs-init` Golang package. The +# notable differences currently are: +# +# 1. The unit file downloads the latest ECS Agent from +# S3 at startup, if the files (ECS Agent tar / MD5 hash) are missing. +# 2. The unit file does not currently handle the Agent's self-upgrade +# functionality. +# 3. The unit file does not clean up downloaded ECS Agents in /var/cache/ecs. + +[Unit] +Description=Amazon ECS Agent +Documentation=https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ECS_agent.html +Requires=docker.service +After=docker.service + +[Install] +WantedBy=multi-user.target + +[Service] +# The logic around the ECS Agent restart: +# - Restart on failure +# - Wait 5 seconds between restart +# - If the ECS Agent restarts more then 10 times in 5 minutes, +# it will stay failed +Type=simple +Restart=on-failure +RestartSec=5s +RestartPreventExitStatus=5 +StartLimitInterval=5min +StartLimitBurst=10 + +# It is recommended in production to version pin the ECS Agent +# to a known version vs running the latest flag on the docker container. +# See https://github.com/aws/amazon-ecs-agent/releases for agent versions. + +# It is recommended to use a systemd drop-in file vs editing this line or file. +# Your drop-in file could look like this: +# +# [Service] +# Environment=ECS_AGENT_VERSION=v1.17.2 +# +# Depending on the OS, it could be placed in +# /etc/systemd/system/amazon-ecs-agent.d , and named +# ecs_agent_version_override.conf +Environment=ECS_AGENT_VERSION=latest +Environment=DOWNLOAD_LOCATION=/var/cache/ecs + +ExecStartPre=-/bin/echo "Amazon ECS Agent systemd unit file version 1.0.0" + +# Create the directories needed for the ECS Agent. +ExecStartPre=/bin/mkdir -p /var/lib/ecs/dhclient /var/ecs-data /etc/ecs \ + /var/cache/ecs + +# Test if /etc/ecs/ecs.config is there, if not create it. +ExecStartPre=/bin/sh -c 'test -f /etc/ecs/ecs.config || touch /etc/ecs/ecs.config' + +# Download ECS Agent from S3. +ExecStartPre=/bin/echo "Downloading the ECS Agent from S3, if missing from instance" +ExecStartPre=/bin/sh -c '\ +REGION=$(curl -s 169.254.169.254/latest/meta-data/placement/availability-zone | sed "s/.$//"); \ +case $REGION in \ + cn-north-1) \ + wget https://s3.$${REGION}.amazonaws.com.cn/amazon-ecs-agent/ecs-agent-${ECS_AGENT_VERSION}.tar \ + https://s3.$${REGION}.amazonaws.com.cn/amazon-ecs-agent/ecs-agent-${ECS_AGENT_VERSION}.tar.md5 --directory-prefix=${DOWNLOAD_LOCATION} --no-clobber --quiet \ + ;; \ + us-gov-west-1) \ + wget https://s3-fips-$${REGION}.amazonaws.com/amazon-ecs-agent/ecs-agent-${ECS_AGENT_VERSION}.tar \ + https://s3-fips-$${REGION}.amazonaws.com/amazon-ecs-agent/ecs-agent-${ECS_AGENT_VERSION}.tar.md5 --directory-prefix=${DOWNLOAD_LOCATION} --no-clobber --quiet \ + ;; \ + *) \ + wget https://s3.amazonaws.com/amazon-ecs-agent/ecs-agent-${ECS_AGENT_VERSION}.tar \ + https://s3.amazonaws.com/amazon-ecs-agent/ecs-agent-${ECS_AGENT_VERSION}.tar.md5 --directory-prefix=${DOWNLOAD_LOCATION} --no-clobber --quiet \ + ;; \ +esac' + +# # Check the MD5 Sum of the downloaded ECS Agent. +ExecStartPre=/bin/echo "Checking the hash of the ECS Agent" +ExecStartPre=/bin/sh -c "if [ $(md5sum ${DOWNLOAD_LOCATION}/ecs-agent-${ECS_AGENT_VERSION}.tar | cut -d ' ' -f 1) != $(cat ${DOWNLOAD_LOCATION}/ecs-agent-${ECS_AGENT_VERSION}.tar.md5) ]; then exit 1; fi" + +# Load an updated ECS Agent downloaded from S3. +ExecStartPre=/bin/echo "Loading ECS Agent into Docker" +ExecStartPre=/bin/sh -c "test -f ${DOWNLOAD_LOCATION}/ecs-agent-${ECS_AGENT_VERSION}.tar && \ + docker load --quiet --input=${DOWNLOAD_LOCATION}/ecs-agent-${ECS_AGENT_VERSION}.tar" + +# Add the IPTable rules needed to enable IAM Roles for Tasks. +ExecStartPre=/bin/echo "Applying IPTables rules" +ExecStartPre=/sbin/iptables -t nat -A PREROUTING -d 169.254.170.2/32 \ + -p tcp -m tcp --dport 80 -j DNAT --to-destination 127.0.0.1:51679 +ExecStartPre=/sbin/iptables -t nat -A OUTPUT -d 169.254.170.2/32 \ + -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 51679 + +# Allow the port proxy to route traffic using loopback addresses +ExecStartPre=/bin/echo "Modifying the attributes of the kernel" +ExecStartPre=/sbin/sysctl --quiet --write net.ipv4.conf.all.route_localnet=1 + +# Remove the container named "ecs-agent" +ExecStartPre=-/bin/sh -c "docker rm ecs-agent > /dev/null 2>&1" + +# The ECS Agent is started via docker run +ExecStart=/usr/bin/docker run --name ecs-agent \ + --init \ + --detach=false \ + --net=host \ + --pid=host \ + --cap-add=SYS_ADMIN \ + --cap-add=NET_ADMIN \ + --volume=/var/run:/var/run \ + --volume=/var/log/ecs/:/log \ + --volume=/var/lib/ecs/data:/data \ + --volume=/etc/ecs:/etc/ecs \ + --volume=/sbin:/sbin \ + --volume=/lib:/lib \ + --volume=/lib64:/lib64 \ + --volume=/usr/lib:/usr/lib \ + --volume=/proc:/host/proc \ + --volume=/sys/fs/cgroup:/sys/fs/cgroup \ + --volume=/var/lib/ecs/dhclient:/var/lib/dhclient \ + --volume=/run/docker/execdriver/native:/var/lib/docker/execdriver/native:ro \ + --publish=127.0.0.1:51678:51678 \ + --log-driver=journald \ + --env-file=/etc/ecs/ecs.config \ + amazon/amazon-ecs-agent:${ECS_AGENT_VERSION} + +# Docker stop is used as it will send a SIGTEM and wait 10 seconds +# before sending SIGKILL +ExecStartPre=-/bin/sh -c "docker stop --time 10 ecs-agent > /dev/null 2>&1" + +# Remove the IPTable rules needed to enable IAM Roles for Tasks. +ExecStopPost=-/sbin/iptables -t nat -D PREROUTING -d 169.254.170.2/32 \ + -p tcp -m tcp --dport 80 -j DNAT --to-destination 127.0.0.1:51679 +ExecStopPost=-/sbin/iptables -t nat -D OUTPUT -d 169.254.170.2/32 \ + -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 51679 + +# Remove the port proxy to route traffic using loopback addresses +ExecStopPost=/bin/sh -c \ + "/sbin/sysctl --quiet --write net.ipv4.conf.all.route_localnet=$(/sbin/sysctl \ + -q -n net.ipv4.conf.default.route_localnet)" diff --git a/integration/systemd/ecs.config b/integration/systemd/ecs.config new file mode 100644 index 00000000..6f0befdd --- /dev/null +++ b/integration/systemd/ecs.config @@ -0,0 +1,9 @@ +ECS_UPDATES_ENABLED=false +ECS_DATADIR=/data +ECS_ENABLE_TASK_IAM_ROLE=true +ECS_ENABLE_TASK_IAM_ROLE_NETWORK_HOST=true +ECS_ENABLE_TASK_ENI=true +ECS_LOGFILE=/log/ecs-agent.log +ECS_AVAILABLE_LOGGING_DRIVERS=["json-file","syslog","awslogs","none"] +ECS_CGROUP_PREFIX=ecs +ECS_CLUSTER=default diff --git a/integration/systemd/load-and-verify-agent.sh b/integration/systemd/load-and-verify-agent.sh new file mode 100644 index 00000000..0b28b5cd --- /dev/null +++ b/integration/systemd/load-and-verify-agent.sh @@ -0,0 +1,43 @@ +#!/bin/bash +# Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You may +# not use this file except in compliance with the License. A copy of the +# License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is distributed +# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +# express or implied. See the License for the specific language governing +# permissions and limitations under the License. + +# This wrapper script ensures that we've loaded the desired ECS agent +# and have attached the "latest" tag to it. +# USAGE: load-and-verify-agent.sh DEFAULT_TAG + +docker ping > /dev/null || { + echo "Cannot talk to Docker daemon. Aborting." >&2 + exit 1 +} + +DEFAULT_TAG=$1 ; shift +AGENT_IMAGE_NAME=amazon/amazon-ecs-agent +DESIRED_IMAGE_FILE=/var/cache/ecs/desired-image + +if [ -f "$DESIRED_IMAGE_FILE" ]; then + DESIRED_TAG=$(head -n1 "$DESIRED_IMAGE_FILE") +else + DESIRED_TAG="$DEFAULT_TAG" +fi + +IMAGE_NAME="${AGENT_IMAGE_NAME}:${DESIRED_TAG}" + + +image_id=$(docker inspect "$IMAGE_NAME") +latest_image_id=$(docker inspect "${AGENT_IMAGE_NAME}:latest") + +if -z "$image_id" ; then + # We already have the desired image. Ensure that "latest" points to it. + docker tag ${AGENT_IMAGE_NAME}:${image_id##sha256:} ${AGENT_IMAGE_NAME}:latest +