Last active
July 3, 2024 21:35
-
-
Save andrewodri/1403c0e28503051e26b24428f1ae49b9 to your computer and use it in GitHub Desktop.
Connect Fargate instance to SSM Session Manager
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
INSTANCE_NAME=acme-development | |
AWS_REGION="$(aws configure get region)" | |
################################################################################ | |
# The section below obtains an activation code and ID from SSM, and then uses it | |
# to register the current agent. _This should only be done on the basis of | |
# tightly controlled roles granted to ECS._ Note that it is registered with two | |
# tags: | |
# | |
# Name: While the name is set via --default-instance-name, the name will | |
# only show up when queries are performed in the CLI. The "Name" | |
# tag is required for the name to be visible in the AWS console. | |
# Type: This acts a flag, so that only offline Fargate instances get | |
# cleaned up. | |
# | |
# The SSM agent is then started. Output is redirected to STDOUT and the process | |
# is sent to the background. Both of these actions are require to prevent the | |
# agent from blocking the script. | |
################################################################################ | |
read -r ACTIVATION_CODE ACTIVATION_ID <<< $(aws ssm create-activation --default-instance-name "${INSTANCE_NAME}" --iam-role "SSMServiceRole" --registration-limit 1 --tags "Key=Name,Value=${INSTANCE_NAME}" "Key=Type,Value=fargate" --query "join(' ', [ActivationCode, ActivationId])" --output text) | |
amazon-ssm-agent -register -code "${ACTIVATION_CODE}" -id "${ACTIVATION_ID}" -region "${AWS_REGION}" -clear -y | |
amazon-ssm-agent >&1 & | |
# Manage the logs by redirecting output to CloudWatch log groups... |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
FROM debian:10-slim | |
RUN apt-get update -y && \ | |
apt-get install -y awscli curl gnupg && \ | |
apt-key adv --fetch-keys "https://nginx.org/keys/nginx_signing.key" && \ | |
echo "deb http://nginx.org/packages/debian buster nginx" > /etc/apt/sources.list.d/nginx.list | |
RUN curl --silent --show-error --location --output /tmp/amazon-ssm-agent.deb "https://s3.us-east-1.amazonaws.com/amazon-ssm-us-east-1/latest/debian_amd64/amazon-ssm-agent.deb" && \ | |
dpkg -i /tmp/amazon-ssm-agent.deb | |
COPY docker-entrypoint.sh / | |
EXPOSE 80 | |
ENTRYPOINT [ "/docker-entrypoint.sh" ] | |
CMD [ "nginx" ] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const { SSM } = require('aws-sdk'); | |
const ssm = new SSM(); | |
exports.handler = async (event, context, callback) => { | |
const { InstanceInformationList } = await ssm.describeInstanceInformation({ | |
Filters: [ | |
{ Key: 'tag:Type', Values: [ 'fargate' ] }, | |
] | |
}).promise(); | |
const offlineInstanceIds = InstanceInformationList.reduce(( accumulator, { InstanceId, PingStatus } ) => { | |
if(PingStatus != 'Online') accumulator.push(InstanceId); | |
return accumulator; | |
}, []); | |
const totalOfflineInstances = offlineInstanceIds.length; | |
const deregisteredOfflineInstances = 0; | |
for (var offlineInstanceId of offlineInstanceIds) { | |
try { | |
await ssm.deregisterManagedInstance({ InstanceId: offlineInstanceId }).promise() | |
deregisteredOfflineInstances++; | |
} catch (e) {} | |
} | |
console.log(`Deregistered ${ deregisteredOfflineInstances } of ${ totalOfflineInstances } offline Fargate instances`); | |
callback(null); | |
}; |
awesome work above!! AWS must have read this and taken note!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Disclaimer: I know there are better ways to run services in Docker... This will get more polished as it settles into my workflow.
How does this work?
What this is going to do is set up a managed instance in a hybrid environment... What does that mean in non-AWS English? AWS will let you manage on-premises servers/containers via SSM. All this does is register your Fargate instance with SSM as if it were an on-premises managed server.
In
Dockerfile
we download and install the SSM agent. This happens in the build phase, so we don't need to worry about stopping it.In
docker-entrypoint.sh
we first request an activation, so that we can attach our "on-premises" server (i.e. Fargate instance) to SSM. An activation code and ID are provided with a default lifespan of 24 hours. That means you have 24 hours to register that instance with SSM, which is what we do next. Finally, we run the agent. If you've followed the steps below, you should be on your way to session managing your Fargate instances!The
index.js
file is intended to be a quick 'n nasty Lambda function for cleaning up left-over Fargate managed instances. It lists all the instances that are tagged with "fargate", then filters out any that are actually online. Then, it deregisters whatever it has found, hopefully mitigating 💸.What do you need to do to get this running?
Here is a bit of to-do list you'll need to consider before this is going to start working:
index.js
into it. You will also need to create an IAM role that allows you describe and de-register instances. (The specific actions to allow this aressm:DeregisterManagedInstance
andssm:DescribeInstanceInformation
) Finally, create a scheduled CloudWatch event rule that calls your function at whatever duration you feel is neccessary.What do I need to do to make this better?