Skip to content

Instantly share code, notes, and snippets.

@zrierc
Last active August 21, 2023 13:45
Show Gist options
  • Save zrierc/6cedd86223ddd0474286dd1d6b89f67a to your computer and use it in GitHub Desktop.
Save zrierc/6cedd86223ddd0474286dd1d6b89f67a to your computer and use it in GitHub Desktop.
Simple script for setup docker swarm and [portainer](https://www.portainer.io/) on Amazon EC2 Instances. To set-up swarm node worker/manager, simply add tag to EC2 Instances called 'SWARM_NODE_TYPE' with 'worker', 'manager', or 'leader' as value.
#!/bin/bash
set -e
# environment variable
AWS_ID=123456789012 # Change to your AWS ID
AWS_REGION=ap-southeast-1 # Change to your region
TZ=Asia/Jakarta # Change to your timezone
USER=ubuntu # Default user AMI Ubuntu 22.04/20.04
# get instance tag for swarm node type
get_node_type() {
instance_id=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
node_type=$(aws ec2 describe-tags --filters "Name=resource-id,Values=$instance_id" | grep "SWARM_NODE_TYPE" | awk '{ print $5}')
echo "$node_type"
}
# get value from ssm parameter name
get_parameter() {
key=$1
parameter_value=$(aws ssm get-parameter --name "/sandbox/swarm/$key" --with-decryption | awk '{ print $7 }')
echo "$parameter_value"
}
# put parameter to ssm parameter store
set_parameter() {
key=$1; value=$2; type=$3;
aws ssm put-parameter \
--name "/sandbox/swarm/$key" \
--value "$value" \
--type "$type" \
--overwrite > /dev/null
}
# set timezone
timedatectl set-timezone $TZ
# update deps
apt-get update && \
apt-get install -y \
ca-certificates \
curl \
gnupg \
lsb-release \
jq \
git \
wget \
zip \
unzip
# environment variable
LOCAL_IP=$(curl -s http://169.254.169.254/latest/meta-data/local-ipv4)
IAM_ROLE_NAME=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/ | awk '{ print $1}')
# install aws cli
curl -sL "https://awscli.amazonaws.com/awscli-exe-linux-$(uname -m).zip" -o "${HOME}/awscliv2.zip"
unzip -d "$HOME" "$HOME"/awscliv2.zip
"$HOME"/aws/install --bin-dir /usr/local/bin --install-dir /usr/local/aws-cli --update
# Configure AWS CLI
export AWS_PROFILE=default
aws configure set role_arn "arn:aws:iam::${AWS_ID}:role/${IAM_ROLE_NAME}" --profile $AWS_PROFILE
aws configure set credential_source "Ec2InstanceMetadata" --profile $AWS_PROFILE
aws configure set region "$AWS_REGION" --profile $AWS_PROFILE
aws configure set output "text" --profile $AWS_PROFILE
# Add Docker's official GPG key and setup repository
mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
# install docker engine
apt-get update && \
apt-get install -y \
docker-ce \
docker-ce-cli \
containerd.io \
docker-compose-plugin
# post installation config
groupadd -f docker
usermod -aG docker $USER
systemctl enable docker.service
systemctl enable containerd.service
# check node type
SWARM_NODE_TYPE=$(get_node_type)
if [[ $SWARM_NODE_TYPE == 'leader' ]]; then
# enable docker swarm
docker swarm init --advertise-addr "$LOCAL_IP" > "$HOME"/worker-credentials.txt
# Get token for worker
SWARM_TOKEN=$(grep "\-\-token" "$HOME"/worker-credentials.txt | awk '{print $5}')
SWARM_PORT=$(grep "\-\-token" "$HOME"/worker-credentials.txt | awk 'BEGIN { FS=":" } {print $2}')
# Get Token for manager
docker swarm join-token manager > "$HOME"/manager-credentials.txt
SWARM_TOKEN_MANAGER=$(grep "\-\-token" "$HOME"/manager-credentials.txt | awk '{print $5}')
# Store swarm credentials to aws parameter store
set_parameter "token-worker" "$SWARM_TOKEN" "SecureString"
set_parameter "token-manager" "$SWARM_TOKEN_MANAGER" "SecureString"
set_parameter "manager-ip" "$LOCAL_IP" "String"
set_parameter "manager-port" "$SWARM_PORT" "String"
# Deploy Portainer
curl -sL https://downloads.portainer.io/ce2-16/portainer-agent-stack.yml -o "${HOME}"/portainer-agent-stack.yml
docker stack deploy -c "$HOME"/portainer-agent-stack.yml portainer
elif [[ $SWARM_NODE_TYPE == 'manager' ]]; then
# join swarm node
MANAGER_TOKEN=$(get_parameter token-manager)
MANAGER_IP=$(get_parameter manager-ip)
MANAGER_PORT=$(get_parameter manager-port)
docker swarm join \
--token "$MANAGER_TOKEN" \
"${MANAGER_IP}:${MANAGER_PORT}"
elif [[ $SWARM_NODE_TYPE == 'worker' ]]; then
# join swarm node
WORKER_TOKEN=$(get_parameter token-worker)
MANAGER_IP=$(get_parameter manager-ip)
MANAGER_PORT=$(get_parameter manager-port)
docker swarm join \
--token "$WORKER_TOKEN" \
"${MANAGER_IP}:${MANAGER_PORT}"
else
echo "Unable to retrieve 'SWARM_NODE_TYPE'. Please add or check again 'SWARM_NODE_TYPE' in your instance tags."
exit 1
fi
# clean-up storage - remove unused container and dangling image
docker system prune -af
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment