Automate provisioning and configuration of Amazon EC2 instances using Infrastructure as Code
Using AWS Systems Manager to securely run Ansible playbooks on Amazon EC2 instances.
TL;DR
AWS Systems Manager offers a secure and simple means of managing and connecting to Amazon EC2 instances. This can be used in combination with Ansible playbooks to automate provisioning and configuration by using an SSM association of type “AWS-ApplyAnsiblePlaybooks”.
Scenario background
When deploying applications via Amazon EC2 instances, it is often required to perform various configuration management tasks, potentially across multiple servers. This process should be automated and controlled through Infrastructure as Code (IaC).
Ansible is one such tool that can automate software provisioning, configuration management and application deployment.
Typically when performing these tasks, you may connect to target instances via SSH. However, this requires a specific network setup to enable you to issue commands. For example, you may need an internet gateway with a NAT gateway in a public subnet in order to reach a target host in a private subnet or, you must configure your Virtual Private Cloud (VPC) and associated network routes to allow traffic from corporate networks/other VPCs. You will also need to allow SSH traffic on the instance (security group and network access control list access) as well as manage an SSH key to authenticate access to the instance.
This can be complex to set up especially when considering keeping access locked down.
AWS Systems Manager for secure and simple access
An alternative approach is to instead use AWS Systems Manager (SSM), which can perform a variety of tasks including using VPC endpoints to allow access to instances in a private subnet, without the need for you to deploy a public subnet, NAT gateway and internet gateway for network accessibility or for additional network routes to be added and controlled. This is achieved by the endpoints providing access via the AWS network. Further, SSM does not require you to launch the target instance with an SSH key, so the requirement to manage this is removed.
This means you can use SSM to access and control instances in private subnets without needing to set up additional networking routes and without needing to add security groups for SSH access.
Prerequisites for using SSM
In order to use SSM to manage and connect to your EC2 instances, there are certain prerequisites.
-
Using a supported operating system
-
Installing SSM agent
-
Connectivity to ec2messages, ssm and ssmmessages endpoints from the instances
-
An IAM instance profile attached to the instance with the AmazonSSMManagedInstanceCore (or equivalent) IAM policy
Running Ansible Playbooks from SSM
Typically, you may have your Ansible related code under an automation/ directory in your project, containing the relevant IaC files. In order to run these with SSM, you can zip the contents of the directory and upload to Amazon S3 (or you can use GitHub as a source).
- Create an SSM association with the name ‘AWS-ApplyAnsiblePlaybooks’
- Pass arguments to tell SSM to look at your S3 bucket to retrieve the playbook. This is the SourceInfo path argument and for S3 sources uses the S3 url of the object.
- Pass the path of the playbook under the automation/ folder for the PlaybookFile option.
- To define which EC2 instances the association runs against, you can use tag based selection. In this example, we look for EC2 instances that have a tag with key Role and value target tag value, you can define this options as you see fit.
You can create this via the AWS console or by using the AWS cli as below:
aws ssm create-association --name "AWS-ApplyAnsiblePlaybooks" --association-name <your_association_name> --parameters '{"SourceType":["S3"], "SourceInfo":["{\"path\": <your_s3_url_to_automation_zip_file>}"], "InstallDependencies": ["True"], "PlaybookFile": [<path_to_playbook_yaml>]}' --targets '[{"Key": "tag:Role", "Values": [<target_tag_value>]}]'
Note
When retrieving the playbooks from S3, the IAM instance profile associated with the EC2 instances must also allow S3 get permissions in order to be able to retrieve the automation content.
Once the association is created, it will run the playbook and it can also be run on a repeated schedule.
Further Reading
You can see more details on the ssm create-association command here and see further details on creating Ansible playbook associations here.