Deploy Docker Swarm on AWS EC2 via cloud-formation templates - Step 3 - Roles
In this step we create the IAM roles and policies needed by the EC2 instances.
This post is part of a thread that includes these steps:
- Network Setup
- Storage
- Roles (this post)
- Manager Instance
- Worker Launch Template
- Worker Instances
- Docker Swarm
- Cleanup
Identity and Access Management (AWS IAM)
Start in the project directory:
cloud-formation Template
We need to create IAM Role and Instance Profile for two types of instances:
- Manager - this will be used by the Manager instance
- Worker - this will be used by the Worker instances
Manager
Create a folder iam
and a iam-manager.yml
file in it.
Copy and paste this code into iam-manager.yml
:
Description: IAM role and instance profile for the Manager instance
Parameters:
Prefix:
Description: An environment name that is prefixed to resource names
Type: String
# Permissions for the Manager instance
Resources:
Role:
Type: AWS::IAM::Role
Properties:
# categories:
- Key: Name
Value: !Sub ${Prefix}-iam-role-manager
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service: ec2.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly
Policies:
- PolicyName: root
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- ec2:DescribeTags
- ec2:AttachVolume
- ec2:DetachVolume
- ecr:DescribeRegistry
- route53:*
Resource: '*'
InstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Roles:
- !Ref Role
Outputs:
InstanceProfile:
Description: A reference to the created InstanceProfile
Value: !Ref InstanceProfile
Worker
Create a file iam/iam-worker.yml
Copy and paste this code into iam-worker.yml
:
Description: IAM role and instance profile for the Worker instances
Parameters:
Prefix:
Description: An environment name that is prefixed to resource names
Type: String
# Permissions for the Worker instance(s)
Resources:
Role:
Type: AWS::IAM::Role
Properties:
# categories:
- Key: Name
Value: !Sub ${Prefix}-iam-role-worker
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service: ec2.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly
Policies:
- PolicyName: root
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- ec2:DescribeTags
- ec2:AttachVolume
- ec2:DetachVolume
- ecr:DescribeRegistry
- route53:*
Resource: '*'
InstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Roles:
- !Ref Role
Outputs:
InstanceProfile:
Description: A reference to the created InstanceProfile
Value: !Ref InstanceProfile
Scripts
Manager
Add a script iam/deploy-iam-manager.sh
and paste this code in it:
#!/usr/bin/env bash
# switch to parent directory
script_path=`dirname ${BASH_SOURCE[0]}`
pushd $script_path/..
source config/names.sh
echo
echo "Deploying $stack_iam_manager stack via cloud-formation:"
echo 'https://us-west-2.console.aws.amazon.com/cloudformation/home'
echo
set -x
# NOTE: `--capabilities CAPABILITY_IAM` is needed because the `iam.yml` cloud-formation template creates roles and instance profiles.
aws cloudformation deploy \
--capabilities CAPABILITY_IAM \
--template-file iam/iam-manager.yml \
--stack-name $stack_iam_manager \
--parameter-overrides Prefix=$prefix
popd
Worker
Add a script iam/deploy-iam-worker.sh
and paste this code in it:
#!/usr/bin/env bash
# switch to parent directory
script_path=`dirname ${BASH_SOURCE[0]}`
pushd $script_path/..
source config/names.sh
echo
echo "Deploying $stack_iam_worker stack via cloud-formation:"
echo 'https://us-west-2.console.aws.amazon.com/cloudformation/home'
echo
set -x
# NOTE: `--capabilities CAPABILITY_IAM` is needed because the `iam.yml` cloud-formation template creates roles and instance profiles.
aws cloudformation deploy \
--capabilities CAPABILITY_IAM \
--template-file iam/iam-worker.yml \
--stack-name $stack_iam_worker \
--parameter-overrides Prefix=$prefix
popd
Let's also add clean up scripts. First the rm-iam-manager.sh
:
#!/usr/bin/env bash
# switch to parent directory
script_path=`dirname ${BASH_SOURCE[0]}`
pushd $script_path/..
source config/names.sh
echo
echo "Removing $stack_iam_manager stack via cloud-formation:"
echo 'https://us-west-2.console.aws.amazon.com/cloudformation/home'
echo
set -x
aws cloudformation delete-stack \
--stack-name $stack_iam_manager
aws cloudformation wait stack-delete-complete \
--stack-name $stack_iam_manager
popd
and another one for the worker - rm-iam-worker.sh
:
#!/usr/bin/env bash
# switch to parent directory
script_path=`dirname ${BASH_SOURCE[0]}`
pushd $script_path/..
source config/names.sh
echo
echo "Removing $stack_iam_worker stack via cloud-formation:"
echo 'https://us-west-2.console.aws.amazon.com/cloudformation/home'
echo
set -x
aws cloudformation delete-stack \
--stack-name $stack_iam_worker
aws cloudformation wait stack-delete-complete \
--stack-name $stack_iam_worker
popd
Make all scripts executable:
chmod +x iam/deploy-iam-manager.sh
chmod +x iam/rm-iam-manager.sh
chmod +x iam/deploy-iam-worker.sh
chmod +x iam/rm-iam-worker.sh
Deploy
Finally let's run the "deploy" scripts to create the IAM roles. First for the Manager:
You should see output similar to this:
Deploying swift-swarm-iam-manager stack via cloud-formation:
https://us-west-2.console.aws.amazon.com/cloudformation/home
+ aws cloudformation deploy --capabilities CAPABILITY_IAM --template-file iam/iam-manager.yml --stack-name swift-swarm-iam-manager --parameter-overrides Prefix=swift-swarm
Waiting for changeset to be created..
Waiting for stack create/update to complete
Successfully created/updated stack - swift-swarm-iam-manager
then for the Worker:
You should see output similar to this:
Deploying swift-swarm-iam-worker stack via cloud-formation:
https://us-west-2.console.aws.amazon.com/cloudformation/home
+ aws cloudformation deploy --capabilities CAPABILITY_IAM --template-file iam/iam-worker.yml --stack-name swift-swarm-iam-worker --parameter-overrides Prefix=swift-swarm
Waiting for changeset to be created..
Waiting for stack create/update to complete
Successfully created/updated stack - swift-swarm-iam-worker
At this point your project structure should look like this:
.
├── config
│ └── names.sh
├── ebs
│ ├── deploy-ebs.sh
│ ├── ebs.yml
│ └── rm-ebs.sh
├── iam
│ ├── deploy-iam-manager.sh
│ ├── deploy-iam-worker.sh
│ ├── iam-manager.yml
│ ├── iam-worker.yml
│ ├── rm-iam-manager.sh
│ └── rm-iam-worker.sh
└── vpc
├── deploy-vpc.sh
├── rm-vpc.sh
└── vpc.yml
Congratulations!
We are done with Step 3. Roles
.
Next step is: Step 4. Manager Instance