Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merging our systemd unit files. #1

Open
wants to merge 17 commits into
base: systemd
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 152 additions & 0 deletions integration/systemd/amazon-ecs-agent.service
Original file line number Diff line number Diff line change
@@ -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
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have data to back up this restart policy?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not. The default RestartSec time for systemd is 100ms, which I feel is way too fast and will clobber docker trying to restart the agent over and over.

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)"
9 changes: 9 additions & 0 deletions integration/systemd/ecs.config
Original file line number Diff line number Diff line change
@@ -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
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure that it makes sense for this file to be here. There's nothing systemd-specific about it, so at the very least it probably shouldn't be in the systemd subdirectory.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call-out, fixing now.

43 changes: 43 additions & 0 deletions integration/systemd/load-and-verify-agent.sh
Original file line number Diff line number Diff line change
@@ -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