From 0f30704d2a592a0a68f4a56bc750f66fb66f317c Mon Sep 17 00:00:00 2001 From: Noah Meyerhans Date: Thu, 10 Aug 2017 11:24:31 -0700 Subject: [PATCH 01/17] Add a systemd unit file for running ECS Agent --- integration/systemd/ecs-agent.service | 61 +++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 integration/systemd/ecs-agent.service diff --git a/integration/systemd/ecs-agent.service b/integration/systemd/ecs-agent.service new file mode 100644 index 00000000..6ee75911 --- /dev/null +++ b/integration/systemd/ecs-agent.service @@ -0,0 +1,61 @@ +# Copyright 2017 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 does an unconditional pull of the latest ECS Agent from +# Docker Hub at startup. +# 2. The unit file does not currently handle the Agent's self-upgrade +# functionality. + +[Unit] +Description=Amazon ECS Agent +Documentation=http://docs.aws.amazon.com/AmazonECS/latest/developerguide/ECS_agent.html +Requires=docker.service +After=docker.service + +[Service] +Type=simple +ExecStartPre=/usr/bin/docker pull amazon/amazon-ecs-agent:latest +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 +ExecStartPre=/sbin/sysctl -w net.ipv4.conf.all.route_localnet=1 +ExecStartPre=-/usr/bin/docker rm ecs-agent +ExecStart=/usr/bin/docker run --name ecs-agent \ + --restart=on-failure:10 \ + --volume=/var/run:/var/run \ + --volume=/var/log/ecs/:/log \ + --volume=/var/lib/ecs/data:/data \ + --volume=/etc/ecs:/etc/ecs \ + --net=host \ + --env ECS_LOGFILE=/log/ecs-agent.log \ + --env ECS_DATADIR=/data \ + --env ECS_UPDATES_ENABLED=false \ + --env ECS_AVAILABLE_LOGGING_DRIVERS='["json-file","syslog","awslogs"]' \ + --env ECS_ENABLE_TASK_IAM_ROLE=true \ + --env ECS_ENABLE_TASK_IAM_ROLE_NETWORK_HOST=true \ + --env-file=/etc/ecs/ecs.config \ + amazon/amazon-ecs-agent:latest +ExecStop=/usr/bin/docker stop ecs-agent +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 +ExecStopPost=/bin/sh -c \ + "/sbin/sysctl -w net.ipv4.conf.all.route_localnet=$(/sbin/sysctl -q -n net.ipv4.conf.default.route_localnet)" +Restart=on-failure +RestartPreventExitStatus=5 From 09aac00473529f62b9726287a79b7548321e4758 Mon Sep 17 00:00:00 2001 From: Noah Meyerhans Date: Tue, 7 Nov 2017 11:40:03 -0800 Subject: [PATCH 02/17] WIP: work on supporting agent updates --- integration/systemd/ecs-agent.service | 9 +++- integration/systemd/load-and-verify-agent.sh | 43 ++++++++++++++++++++ 2 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 integration/systemd/load-and-verify-agent.sh diff --git a/integration/systemd/ecs-agent.service b/integration/systemd/ecs-agent.service index 6ee75911..64021bf6 100644 --- a/integration/systemd/ecs-agent.service +++ b/integration/systemd/ecs-agent.service @@ -27,8 +27,12 @@ Requires=docker.service After=docker.service [Service] +Environment=AGENT_TAG=v1.15.0 Type=simple -ExecStartPre=/usr/bin/docker pull amazon/amazon-ecs-agent:latest +# Load an updated agent, if it exists: +ExecStartPre=-/bin/sh -c 'test -f /var/cache/ecs/desired-image && docker load $(cat /var/cache/ecs/desired-image) && rm -f $(cat /var/cache/ecs/desired-image) /var/cache/ecs/desired-image' +# If we don't have an agent, load from disk, if possible, or Docker Hub: +ExecStartPre=/bin/sh -c "docker inspect amazon/amazon-ecs-agent || docker load < /var/cache/ecs/ecs-agent.tar || docker pull amazon/amazon-ecs-agent:${AGENT_TAG}" 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 \ @@ -48,8 +52,9 @@ ExecStart=/usr/bin/docker run --name ecs-agent \ --env ECS_AVAILABLE_LOGGING_DRIVERS='["json-file","syslog","awslogs"]' \ --env ECS_ENABLE_TASK_IAM_ROLE=true \ --env ECS_ENABLE_TASK_IAM_ROLE_NETWORK_HOST=true \ + --env ECS_UPDATES_ENABLED=true \ --env-file=/etc/ecs/ecs.config \ - amazon/amazon-ecs-agent:latest + amazon/amazon-ecs-agent:${AGENT_TAG} ExecStop=/usr/bin/docker stop ecs-agent 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 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 + From 4d7b43d91628ec2778a50e22dac993e085ac6857 Mon Sep 17 00:00:00 2001 From: Noah Meyerhans Date: Thu, 7 Dec 2017 09:43:09 -0800 Subject: [PATCH 03/17] Updates for agent 1.16.0 and awsvpc networking Load and run agent 1.16.0 Update agent runtime configuration to support awsvpc requirements. --- integration/systemd/ecs-agent.service | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/integration/systemd/ecs-agent.service b/integration/systemd/ecs-agent.service index 64021bf6..bc25bc0c 100644 --- a/integration/systemd/ecs-agent.service +++ b/integration/systemd/ecs-agent.service @@ -27,7 +27,7 @@ Requires=docker.service After=docker.service [Service] -Environment=AGENT_TAG=v1.15.0 +Environment=AGENT_TAG=v1.16.0 Type=simple # Load an updated agent, if it exists: ExecStartPre=-/bin/sh -c 'test -f /var/cache/ecs/desired-image && docker load $(cat /var/cache/ecs/desired-image) && rm -f $(cat /var/cache/ecs/desired-image) /var/cache/ecs/desired-image' @@ -39,12 +39,21 @@ ExecStartPre=/sbin/iptables -t nat -A OUTPUT -d 169.254.170.2/32 \ -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 51679 ExecStartPre=/sbin/sysctl -w net.ipv4.conf.all.route_localnet=1 ExecStartPre=-/usr/bin/docker rm ecs-agent +ExecStartPre=-/bin/mkdir -p /var/lib/ecs/dhclient ExecStart=/usr/bin/docker run --name ecs-agent \ + --init \ --restart=on-failure:10 \ --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 \ --net=host \ --env ECS_LOGFILE=/log/ecs-agent.log \ --env ECS_DATADIR=/data \ @@ -53,7 +62,10 @@ ExecStart=/usr/bin/docker run --name ecs-agent \ --env ECS_ENABLE_TASK_IAM_ROLE=true \ --env ECS_ENABLE_TASK_IAM_ROLE_NETWORK_HOST=true \ --env ECS_UPDATES_ENABLED=true \ + --env ECS_ENABLE_TASK_ENI=true \ --env-file=/etc/ecs/ecs.config \ + --cap-add=sys_admin \ + --cap-add=net_admin \ amazon/amazon-ecs-agent:${AGENT_TAG} ExecStop=/usr/bin/docker stop ecs-agent ExecStopPost=-/sbin/iptables -t nat -D PREROUTING -d 169.254.170.2/32 \ From c08574c4fcabd1d056c4d4adebff44193bdceaf6 Mon Sep 17 00:00:00 2001 From: Noah Meyerhans Date: Wed, 20 Dec 2017 16:12:43 -0800 Subject: [PATCH 04/17] Add an Install section to the systemd service file --- integration/systemd/ecs-agent.service | 3 +++ 1 file changed, 3 insertions(+) diff --git a/integration/systemd/ecs-agent.service b/integration/systemd/ecs-agent.service index bc25bc0c..d2946da4 100644 --- a/integration/systemd/ecs-agent.service +++ b/integration/systemd/ecs-agent.service @@ -26,6 +26,9 @@ Documentation=http://docs.aws.amazon.com/AmazonECS/latest/developerguide/ECS_age Requires=docker.service After=docker.service +[Install] +WantedBy=multi-user.target + [Service] Environment=AGENT_TAG=v1.16.0 Type=simple From 5b8ba6e97998441e55be096b8c45d98e4e186709 Mon Sep 17 00:00:00 2001 From: Noah Meyerhans Date: Fri, 5 Jan 2018 15:42:44 -0800 Subject: [PATCH 05/17] Update to load ecs agent 1.16.1 --- integration/systemd/ecs-agent.service | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration/systemd/ecs-agent.service b/integration/systemd/ecs-agent.service index d2946da4..eeba9b3f 100644 --- a/integration/systemd/ecs-agent.service +++ b/integration/systemd/ecs-agent.service @@ -30,7 +30,7 @@ After=docker.service WantedBy=multi-user.target [Service] -Environment=AGENT_TAG=v1.16.0 +Environment=AGENT_TAG=v1.16.1 Type=simple # Load an updated agent, if it exists: ExecStartPre=-/bin/sh -c 'test -f /var/cache/ecs/desired-image && docker load $(cat /var/cache/ecs/desired-image) && rm -f $(cat /var/cache/ecs/desired-image) /var/cache/ecs/desired-image' From 57a060b18ebb08e664e5452d9ea561b2cfff1d81 Mon Sep 17 00:00:00 2001 From: Noah Meyerhans Date: Wed, 24 Jan 2018 16:18:43 -0800 Subject: [PATCH 06/17] systemd: update to load agent 1.16.2 --- integration/systemd/ecs-agent.service | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration/systemd/ecs-agent.service b/integration/systemd/ecs-agent.service index eeba9b3f..3af92df7 100644 --- a/integration/systemd/ecs-agent.service +++ b/integration/systemd/ecs-agent.service @@ -30,7 +30,7 @@ After=docker.service WantedBy=multi-user.target [Service] -Environment=AGENT_TAG=v1.16.1 +Environment=AGENT_TAG=v1.16.2 Type=simple # Load an updated agent, if it exists: ExecStartPre=-/bin/sh -c 'test -f /var/cache/ecs/desired-image && docker load $(cat /var/cache/ecs/desired-image) && rm -f $(cat /var/cache/ecs/desired-image) /var/cache/ecs/desired-image' From 92ef111d16adadd93a37e40b6cf5f87b29e32975 Mon Sep 17 00:00:00 2001 From: Noah Meyerhans Date: Thu, 8 Feb 2018 16:40:47 -0800 Subject: [PATCH 07/17] Update unit file for agent 1.17.0 --- integration/systemd/ecs-agent.service | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration/systemd/ecs-agent.service b/integration/systemd/ecs-agent.service index 3af92df7..a327e6cd 100644 --- a/integration/systemd/ecs-agent.service +++ b/integration/systemd/ecs-agent.service @@ -30,7 +30,7 @@ After=docker.service WantedBy=multi-user.target [Service] -Environment=AGENT_TAG=v1.16.2 +Environment=AGENT_TAG=v1.17.0 Type=simple # Load an updated agent, if it exists: ExecStartPre=-/bin/sh -c 'test -f /var/cache/ecs/desired-image && docker load $(cat /var/cache/ecs/desired-image) && rm -f $(cat /var/cache/ecs/desired-image) /var/cache/ecs/desired-image' From 3c04c5ad819c79d0fa6c5c9c09847bd0682674cd Mon Sep 17 00:00:00 2001 From: Jason Swindle Date: Fri, 23 Mar 2018 10:37:38 -0700 Subject: [PATCH 08/17] Merging our systemd unit files. --- integration/systemd/ecs-agent.service | 142 ++++++++++++++++++-------- 1 file changed, 99 insertions(+), 43 deletions(-) diff --git a/integration/systemd/ecs-agent.service b/integration/systemd/ecs-agent.service index a327e6cd..bbcb47b8 100644 --- a/integration/systemd/ecs-agent.service +++ b/integration/systemd/ecs-agent.service @@ -1,4 +1,4 @@ -# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# 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 @@ -11,10 +11,11 @@ # 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 does an unconditional pull of the latest ECS Agent from # Docker Hub at startup. # 2. The unit file does not currently handle the Agent's self-upgrade @@ -30,52 +31,107 @@ After=docker.service WantedBy=multi-user.target [Service] -Environment=AGENT_TAG=v1.17.0 +# The logic around the ECS Agent restart: +# - Restart on failure +# - Wait 15 seconds between restart +# - If the ECS Agent restarts more then 10 times in 5 minutes, +# it will stay failed Type=simple -# Load an updated agent, if it exists: -ExecStartPre=-/bin/sh -c 'test -f /var/cache/ecs/desired-image && docker load $(cat /var/cache/ecs/desired-image) && rm -f $(cat /var/cache/ecs/desired-image) /var/cache/ecs/desired-image' -# If we don't have an agent, load from disk, if possible, or Docker Hub: -ExecStartPre=/bin/sh -c "docker inspect amazon/amazon-ecs-agent || docker load < /var/cache/ecs/ecs-agent.tar || docker pull amazon/amazon-ecs-agent:${AGENT_TAG}" +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=v1.17.2 + +ExecStartPre=-/usr/bin/echo "Amazon ECS Agent systemd unit file version 1.0.0" + +# Load an updated ECS Agent, if it exists: +ExecStartPre=-/bin/sh -c 'test -f /var/cache/ecs/desired-image && \ + docker load $(cat /var/cache/ecs/desired-image) \ + && rm -f $(cat /var/cache/ecs/desired-image) /var/cache/ecs/desired-image' + +# If we don't have an ECS Agent, load from disk, if possible, or Docker Hub: +ExecStartPre=/bin/sh -c "docker inspect amazon/amazon-ecs-agent \ + || docker load --quiet < /var/cache/ecs/ecs-agent.tar \ + || docker pull amazon/amazon-ecs-agent:${ECS_AGENT_VERSION}" + +# Add the IPTable rules needed to enable IAM Roles for Tasks. 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 + -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 -ExecStartPre=/sbin/sysctl -w net.ipv4.conf.all.route_localnet=1 + -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 51679 + +# Allow the port proxy to route traffic using loopback addresses +ExecStartPre=/sbin/sysctl --quiet --write net.ipv4.conf.all.route_localnet=1 + +# Stop the ECS Agent if it was running. Docker stop is used +# as it will send a SIGTEM and wait 10 seconds before sending SIGKILL +ExecStartPre=-/usr/bin/docker stop --time 10 ecs-agent + +# Remove the container named "ecs-agent" ExecStartPre=-/usr/bin/docker rm ecs-agent -ExecStartPre=-/bin/mkdir -p /var/lib/ecs/dhclient + +# Create the directories needed for the ECS Agent. +ExecStartPre=-/bin/mkdir -p /var/lib/ecs/dhclient /var/ecs-data + +# The ECS Agent is started via docker run ExecStart=/usr/bin/docker run --name ecs-agent \ - --init \ - --restart=on-failure:10 \ - --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 \ - --net=host \ - --env ECS_LOGFILE=/log/ecs-agent.log \ - --env ECS_DATADIR=/data \ - --env ECS_UPDATES_ENABLED=false \ - --env ECS_AVAILABLE_LOGGING_DRIVERS='["json-file","syslog","awslogs"]' \ - --env ECS_ENABLE_TASK_IAM_ROLE=true \ - --env ECS_ENABLE_TASK_IAM_ROLE_NETWORK_HOST=true \ - --env ECS_UPDATES_ENABLED=true \ - --env ECS_ENABLE_TASK_ENI=true \ - --env-file=/etc/ecs/ecs.config \ - --cap-add=sys_admin \ - --cap-add=net_admin \ - amazon/amazon-ecs-agent:${AGENT_TAG} -ExecStop=/usr/bin/docker stop 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 \ + --env ECS_UPDATES_ENABLED=false \ + --env ECS_DATADIR=/data \ + --env ECS_ENABLE_TASK_IAM_ROLE=true \ + --env ECS_ENABLE_TASK_IAM_ROLE_NETWORK_HOST=true \ + --env ECS_ENABLE_TASK_ENI=true \ + --env ECS_LOGFILE=/log/ecs-agent.log \ + --env ECS_AVAILABLE_LOGGING_DRIVERS=["json-file","syslog","awslogs","none"] \ + --env ECS_CGROUP_PREFIX=ecs \ + --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 +ExecStop=/usr/bin/docker stop --time 10 ecs-agent + +# 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 + -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 + -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 -w net.ipv4.conf.all.route_localnet=$(/sbin/sysctl -q -n net.ipv4.conf.default.route_localnet)" -Restart=on-failure -RestartPreventExitStatus=5 + "/sbin/sysctl --quiet --write net.ipv4.conf.all.route_localnet=$(/sbin/sysctl \ + -q -n net.ipv4.conf.default.route_localnet)" From 72495ad5b0334b7ff8f44b56926c034231a210ad Mon Sep 17 00:00:00 2001 From: Jason Swindle Date: Fri, 23 Mar 2018 10:40:18 -0700 Subject: [PATCH 09/17] Example ecs.config for the systemd unit file. --- integration/systemd/ecs.config | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 integration/systemd/ecs.config diff --git a/integration/systemd/ecs.config b/integration/systemd/ecs.config new file mode 100644 index 00000000..9205a3c6 --- /dev/null +++ b/integration/systemd/ecs.config @@ -0,0 +1,2 @@ +ECS_LOGLEVEL=info +ECS_CLUSTER=default From 67ef172de79fd4df76f75b4dd6fc0d1dc0066f34 Mon Sep 17 00:00:00 2001 From: Jason Swindle Date: Fri, 23 Mar 2018 10:51:41 -0700 Subject: [PATCH 10/17] Rename to match the naming standard of other ... Amazon systemd unit files. --- .../systemd/{ecs-agent.service => amazon-ecs-agent.service} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename integration/systemd/{ecs-agent.service => amazon-ecs-agent.service} (100%) diff --git a/integration/systemd/ecs-agent.service b/integration/systemd/amazon-ecs-agent.service similarity index 100% rename from integration/systemd/ecs-agent.service rename to integration/systemd/amazon-ecs-agent.service From 51e10c708c76596dee0a9710a037ae9d971251e4 Mon Sep 17 00:00:00 2001 From: Jason Swindle Date: Fri, 23 Mar 2018 12:18:24 -0700 Subject: [PATCH 11/17] Cleaned up output of unit, and agent logging ... ... driver is now journald. The ECS Agent still logs into the amazon-ecs-agent unit and writes to the file system. --- integration/systemd/amazon-ecs-agent.service | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/integration/systemd/amazon-ecs-agent.service b/integration/systemd/amazon-ecs-agent.service index bbcb47b8..ef548433 100644 --- a/integration/systemd/amazon-ecs-agent.service +++ b/integration/systemd/amazon-ecs-agent.service @@ -62,12 +62,12 @@ ExecStartPre=-/usr/bin/echo "Amazon ECS Agent systemd unit file version 1.0.0" # Load an updated ECS Agent, if it exists: ExecStartPre=-/bin/sh -c 'test -f /var/cache/ecs/desired-image && \ - docker load $(cat /var/cache/ecs/desired-image) \ + docker load --quiet --input=/var/cache/ecs/desired-image \ && rm -f $(cat /var/cache/ecs/desired-image) /var/cache/ecs/desired-image' # If we don't have an ECS Agent, load from disk, if possible, or Docker Hub: -ExecStartPre=/bin/sh -c "docker inspect amazon/amazon-ecs-agent \ - || docker load --quiet < /var/cache/ecs/ecs-agent.tar \ +ExecStartPre=/bin/sh -c "`docker inspect amazon/amazon-ecs-agent &>/dev/null` \ + || docker load --quiet -input=/var/cache/ecs/ecs-agent.tar \ || docker pull amazon/amazon-ecs-agent:${ECS_AGENT_VERSION}" # Add the IPTable rules needed to enable IAM Roles for Tasks. @@ -81,10 +81,10 @@ ExecStartPre=/sbin/sysctl --quiet --write net.ipv4.conf.all.route_localnet=1 # Stop the ECS Agent if it was running. Docker stop is used # as it will send a SIGTEM and wait 10 seconds before sending SIGKILL -ExecStartPre=-/usr/bin/docker stop --time 10 ecs-agent +ExecStartPre=-/bin/sh -c "`docker stop --time 10 ecs-agent &>/dev/null`" # Remove the container named "ecs-agent" -ExecStartPre=-/usr/bin/docker rm ecs-agent +ExecStartPre=-/bin/sh -c "`docker rm ecs-agent &>/dev/null`" # Create the directories needed for the ECS Agent. ExecStartPre=-/bin/mkdir -p /var/lib/ecs/dhclient /var/ecs-data @@ -118,12 +118,13 @@ ExecStart=/usr/bin/docker run --name ecs-agent \ --env ECS_LOGFILE=/log/ecs-agent.log \ --env ECS_AVAILABLE_LOGGING_DRIVERS=["json-file","syslog","awslogs","none"] \ --env ECS_CGROUP_PREFIX=ecs \ + --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 -ExecStop=/usr/bin/docker stop --time 10 ecs-agent +ExecStartPre=-/bin/sh -c "`docker stop --time 10 ecs-agent &>/dev/null`" # Remove the IPTable rules needed to enable IAM Roles for Tasks. ExecStopPost=-/sbin/iptables -t nat -D PREROUTING -d 169.254.170.2/32 \ From cedc64b8a04796c24a7fb06534fd0adc7c7a9b1b Mon Sep 17 00:00:00 2001 From: Jason Swindle Date: Fri, 23 Mar 2018 12:19:09 -0700 Subject: [PATCH 12/17] Delete ecs.config --- integration/systemd/ecs.config | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 integration/systemd/ecs.config diff --git a/integration/systemd/ecs.config b/integration/systemd/ecs.config deleted file mode 100644 index 9205a3c6..00000000 --- a/integration/systemd/ecs.config +++ /dev/null @@ -1,2 +0,0 @@ -ECS_LOGLEVEL=info -ECS_CLUSTER=default From 1a2e19454ba4ca7f6ea86c8cf3a72bbda17f4727 Mon Sep 17 00:00:00 2001 From: Jason Swindle Date: Fri, 23 Mar 2018 12:48:30 -0700 Subject: [PATCH 13/17] Typo in restart logic comment. --- integration/systemd/amazon-ecs-agent.service | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration/systemd/amazon-ecs-agent.service b/integration/systemd/amazon-ecs-agent.service index ef548433..6999393e 100644 --- a/integration/systemd/amazon-ecs-agent.service +++ b/integration/systemd/amazon-ecs-agent.service @@ -33,7 +33,7 @@ WantedBy=multi-user.target [Service] # The logic around the ECS Agent restart: # - Restart on failure -# - Wait 15 seconds between restart +# - Wait 5 seconds between restart # - If the ECS Agent restarts more then 10 times in 5 minutes, # it will stay failed Type=simple From 9c8e50d4fa15348665539851c313f58c4b96bcf8 Mon Sep 17 00:00:00 2001 From: Jason Swindle Date: Mon, 26 Mar 2018 15:13:48 -0700 Subject: [PATCH 14/17] Updated from feedback - ECS Agent only downloads from S3. -- Will download from region as needed. - MD5 checks the downloaded file. - Moved ENV to ecs.config so they can over-written. --- integration/systemd/amazon-ecs-agent.service | 63 +++++++++++--------- 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/integration/systemd/amazon-ecs-agent.service b/integration/systemd/amazon-ecs-agent.service index 6999393e..4b76def9 100644 --- a/integration/systemd/amazon-ecs-agent.service +++ b/integration/systemd/amazon-ecs-agent.service @@ -56,38 +56,55 @@ StartLimitBurst=10 # 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=v1.17.2 +Environment=ECS_AGENT_VERSION=latest +Environment=DOWNLOAD_LOCATION=/var/cache/ecs ExecStartPre=-/usr/bin/echo "Amazon ECS Agent systemd unit file version 1.0.0" -# Load an updated ECS Agent, if it exists: -ExecStartPre=-/bin/sh -c 'test -f /var/cache/ecs/desired-image && \ - docker load --quiet --input=/var/cache/ecs/desired-image \ - && rm -f $(cat /var/cache/ecs/desired-image) /var/cache/ecs/desired-image' - -# If we don't have an ECS Agent, load from disk, if possible, or Docker Hub: -ExecStartPre=/bin/sh -c "`docker inspect amazon/amazon-ecs-agent &>/dev/null` \ - || docker load --quiet -input=/var/cache/ecs/ecs-agent.tar \ - || docker pull amazon/amazon-ecs-agent:${ECS_AGENT_VERSION}" +# 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 'touch -a /etc/ecs/ecs.config' + +# Set the varable REGION for the ECS Agnet download from S3. +ExecStartPre=/bin/sh -c "REGION=$(curl -s 169.254.169.254/latest/meta-data/placement/availability-zone | sed 's/.$//')" + +# Download ECS Agent from S3. +ExecStartPre=/usr/bin/echo "Downloading the ECS Agent from S3, if missing" +ExecStartPre=/bin/sh -c '\ +case $$REGION in \ + cn-north-1) \ + wget https://s3.${REGION}.amazonaws.com.cn/amazon-ecs-agent/ecs-agent-${ECS_AGENT_VERSION}.{tar,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,tar.md5} --directory-prefix=${DOWNLOAD_LOCATION} --no-clobber --quiet ;; \ + *) \ + wget https://s3.amazonaws.com/amazon-ecs-agent/ecs-agent-${ECS_AGENT_VERSION}.{tar,tar.md5} --directory-prefix=${DOWNLOAD_LOCATION} --no-clobber --quiet ;; \ +esac' + +# # Check the MD5 Sum of the downloaded ECS Agent. +ExecStartPre=/usr/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=/usr/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=/usr/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=/usr/bin/echo "Modifying the attributes of the kernel" ExecStartPre=/sbin/sysctl --quiet --write net.ipv4.conf.all.route_localnet=1 -# Stop the ECS Agent if it was running. 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`" - # Remove the container named "ecs-agent" -ExecStartPre=-/bin/sh -c "`docker rm ecs-agent &>/dev/null`" - -# Create the directories needed for the ECS Agent. -ExecStartPre=-/bin/mkdir -p /var/lib/ecs/dhclient /var/ecs-data +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 \ @@ -110,21 +127,13 @@ ExecStart=/usr/bin/docker run --name ecs-agent \ --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 \ - --env ECS_UPDATES_ENABLED=false \ - --env ECS_DATADIR=/data \ - --env ECS_ENABLE_TASK_IAM_ROLE=true \ - --env ECS_ENABLE_TASK_IAM_ROLE_NETWORK_HOST=true \ - --env ECS_ENABLE_TASK_ENI=true \ - --env ECS_LOGFILE=/log/ecs-agent.log \ - --env ECS_AVAILABLE_LOGGING_DRIVERS=["json-file","syslog","awslogs","none"] \ - --env ECS_CGROUP_PREFIX=ecs \ --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`" +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 \ From f469cc2c9b454fad2a2a5b6cb326b0851969fe6c Mon Sep 17 00:00:00 2001 From: Jason Swindle Date: Mon, 26 Mar 2018 15:27:20 -0700 Subject: [PATCH 15/17] Forgot to update some of the comments. - Changed docs to HTTPS vs HTTP. --- integration/systemd/amazon-ecs-agent.service | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/integration/systemd/amazon-ecs-agent.service b/integration/systemd/amazon-ecs-agent.service index 4b76def9..7c0d157c 100644 --- a/integration/systemd/amazon-ecs-agent.service +++ b/integration/systemd/amazon-ecs-agent.service @@ -16,14 +16,15 @@ # attempts to duplicate the functionality of the `ecs-init` Golang package. The # notable differences currently are: # -# 1. The unit file does an unconditional pull of the latest ECS Agent from -# Docker Hub at startup. +# 1. The unit file downloads 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=http://docs.aws.amazon.com/AmazonECS/latest/developerguide/ECS_agent.html +Documentation=https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ECS_agent.html Requires=docker.service After=docker.service From 076e07a312bfbcd6ffdd76ebf90db50d8e6c8274 Mon Sep 17 00:00:00 2001 From: Jason Swindle Date: Mon, 26 Mar 2018 15:32:09 -0700 Subject: [PATCH 16/17] Added ecs.config, as the unit file needs it. --- integration/systemd/ecs.config | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 integration/systemd/ecs.config 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 From e23371782eaf4a7a39d62089a719b96cc7fbd360 Mon Sep 17 00:00:00 2001 From: Jason Swindle Date: Tue, 27 Mar 2018 12:09:34 -0700 Subject: [PATCH 17/17] Fixed.... - A echo to work on Ubuntu as well. - Fixed the case logic (Tested in us-gov-west-1 on Ubuntu 16.04 instance) - Fixed test logic to be more POSIX. - Typo --- integration/systemd/amazon-ecs-agent.service | 36 +++++++++++--------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/integration/systemd/amazon-ecs-agent.service b/integration/systemd/amazon-ecs-agent.service index 7c0d157c..d56b0d5f 100644 --- a/integration/systemd/amazon-ecs-agent.service +++ b/integration/systemd/amazon-ecs-agent.service @@ -16,7 +16,7 @@ # attempts to duplicate the functionality of the `ecs-init` Golang package. The # notable differences currently are: # -# 1. The unit file downloads latest ECS Agent from +# 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. @@ -60,48 +60,52 @@ StartLimitBurst=10 Environment=ECS_AGENT_VERSION=latest Environment=DOWNLOAD_LOCATION=/var/cache/ecs -ExecStartPre=-/usr/bin/echo "Amazon ECS Agent systemd unit file version 1.0.0" +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 'touch -a /etc/ecs/ecs.config' - -# Set the varable REGION for the ECS Agnet download from S3. -ExecStartPre=/bin/sh -c "REGION=$(curl -s 169.254.169.254/latest/meta-data/placement/availability-zone | sed 's/.$//')" +ExecStartPre=/bin/sh -c 'test -f /etc/ecs/ecs.config || touch /etc/ecs/ecs.config' # Download ECS Agent from S3. -ExecStartPre=/usr/bin/echo "Downloading the ECS Agent from S3, if missing" +ExecStartPre=/bin/echo "Downloading the ECS Agent from S3, if missing from instance" ExecStartPre=/bin/sh -c '\ -case $$REGION in \ +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,tar.md5} --directory-prefix=${DOWNLOAD_LOCATION} --no-clobber --quiet ;; \ + 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,tar.md5} --directory-prefix=${DOWNLOAD_LOCATION} --no-clobber --quiet ;; \ + 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,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=/usr/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" +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=/usr/bin/echo "Loading ECS Agent into Docker" +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=/usr/bin/echo "Applying IPTables rules" +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=/usr/bin/echo "Modifying the attributes of the kernel" +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"