AWS_EN

Ansible on Private Subnet

スポンサーリンク
Ansible on Private subnet. AWS_EN
スポンサーリンク
スポンサーリンク

Configuring instances in private subnet to run AWS-ApplyAnsiblePlaybooks document

In the following page, we have introduced four ways to initialize process on an EC2 instance (Amazon Linux 2).

In this article, we will delve into one of those methods, using Ansible. In the previous page, the configuration was that the instance was installed in a public subnet. In this article, we will cover how to run the AWS-ApplyAnsiblePlaybooks document in a configuration where the instance is located in a private subnet. I will introduce the following two patterns.

  • The pattern using a NAT gateway
  • Pattern using VPC endpoints

Environment

Diagram of Ansible on Private Subnet.

EC2 instance 1 is the pattern for running Ansible via a NAT gateway, and EC2 instance 2 is the pattern for running Ansible via VPC endpoints.
The content of the playbook will be the same for both instances, and will be placed in an S3 bucket.

CloudFormation template files

We will build the above configuration using CloudFormation. We have placed the CloudFormation template at the following URL

awstut-fa/025 at main · awstut-an-r/awstut-fa
Contribute to awstut-an-r/awstut-fa development by creating an account on GitHub.

Explanation of key points of template files

This page only describes the resources related to AWS-ApplyAnsiblePlaybooks document. For more information about the basics of running AWS-ApplyAnsiblePlaybooks documentation, configuration for NAT gateways, and how to run yum in a private subnet, see the following page

AWS-ApplyAnsiblePlaybooks Document Execution (1) (via NAT gateway)

First, let’s check the configuration for running AWS-ApplyAnsiblePlaybooks document via NAT gateway. Define the SSM related resources in fa-025-ssm.yaml.

<meta charset="utf-8">Resources: ApplyAnsiblePlaybooksAssociation1: Type: AWS::SSM::Association DependsOn: - RunShellScriptAssociation Properties: AssociationName: !Sub ${Prefix}-apply-ansible-playbook-association1 Name: AWS-ApplyAnsiblePlaybooks OutputLocation: S3Location: OutputS3BucketName: !Ref PlaybookBucket OutputS3KeyPrefix: !Sub "${Prefix}/playbook-association-log" Parameters: Check: - "False" ExtraVariables: - SSM=True InstallDependencies: - "True" PlaybookFile: - !Ref PlaybookFileName SourceInfo: - !Sub '{"path": "https://${PlaybookBucket}.s3.${AWS::Region}.amazonaws.com/${Prefix}/${PlaybookPackageName}"}' SourceType: - S3 Verbose: - -v Targets: - Key: InstanceIds Values: - !Ref Instance1 WaitForSuccessTimeoutSeconds: !Ref WaitForSuccessTimeoutSeconds
Code language: YAML (yaml)

The settings are the same as those described above when the instance is installed in a public subnet. In this case, the instance is installed in a private subnet, but since it can access the Internet via a NAT gateway, the same settings as for a public subnet will work.
In this configuration, the setting of particular interest is the InstallDependencies property. This option is used to install packages that are dependencies on running the AWS-ApplyAnsiblePlaybooks document. To begin with, Ansible is not installed on Amazon Linux 2 by default. So enable this option and let Ansible be installed at document runtime.

AWS-ApplyAnsiblePlaybooks Document Execution (2) (via VPC endpoints)

Next, let’s check the configuration for running AWS-ApplyAnsiblePlaybooks document via VPC endpoints.
This time, we will create the following two resources.

  • AWS-RunShellScript: to be run to install Ansible.
  • AWS-ApplyAnsiblePlaybooks: To run the contents of the Ansible Playbook.

The reason for defining the process in two separate documents is that the instance is located on a private subnet, so Ansible cannot be successfully installed using the options described above. This is due to the fact that the instance is on a private subnet and thus cannot communicate freely to the Internet.
The workaround for this is to install Ansible with the AWS-RunShellScript document first and then run the AWS-ApplyAnsiblePlaybooks document.

AWS-RunShellScript

Resources: RunShellScriptAssociation: Type: AWS::SSM::Association Properties: AssociationName: !Sub ${Prefix}-run-shellscript-association Name: AWS-RunShellScript OutputLocation: S3Location: OutputS3BucketName: !Ref PlaybookBucket OutputS3KeyPrefix: !Sub "${Prefix}/shellscript-association-log" Parameters: commands: - "sudo amazon-linux-extras install -y ansible2" Targets: - Key: InstanceIds Values: - !Ref Instance2 WaitForSuccessTimeoutSeconds: !Ref WaitForSuccessTimeoutSeconds
Code language: YAML (yaml)

Execute the commands for the Ansible installation in the commands property. In this case, we will use Amazon Linux Extras for the installation.

Extras is a mechanism in Amazon Linux 2 to enable the consumption of new versions of application software on a stable operating system that is supported until June 30, 2023.

Examples of extras include Ansible 2.4.2, memcached 1.5, nginx 1.12, Postgresql 9.6, MariaDB 10.2, Go 1.9, Redis 4.0, R 3.4, Rust 1.22.1.

Amazon Linux Extras

AWS-ApplyAnsiblePlaybooks

Resources: ApplyAnsiblePlaybooksAssociation2: Type: AWS::SSM::Association DependsOn: - RunShellScriptAssociation Properties: AssociationName: !Sub ${Prefix}-apply-ansible-playbook-association2 Name: AWS-ApplyAnsiblePlaybooks OutputLocation: S3Location: OutputS3BucketName: !Ref PlaybookBucket OutputS3KeyPrefix: !Sub "${Prefix}/playbook-association-log" Parameters: Check: - "False" ExtraVariables: - SSM=True InstallDependencies: #- "True" - "False" PlaybookFile: - !Ref PlaybookFileName SourceInfo: - !Sub '{"path": "https://${PlaybookBucket}.s3.${AWS::Region}.amazonaws.com/${Prefix}/${PlaybookPackageName}"}' SourceType: - S3 Verbose: - -v Targets: - Key: InstanceIds Values: - !Ref Instance2 WaitForSuccessTimeoutSeconds: !Ref WaitForSuccessTimeoutSeconds
Code language: YAML (yaml)

Notice the InstallDependencies property. Specify “False”. This is because we have already installed Ansible by running the AWS-RunShellScript document, so there is no need to resolve any dependencies.

(Reference) Ansible Playbook

For your reference, here is the content of the Playbook that we will run.

- hosts: all gather_facts: no become: yes tasks: - name: update yum yum: name=* - name: install the latest version of Apache yum: name=httpd state=latest - name: start and enable Apache service: name=httpd state=started enabled=yes - name: make index.html shell: ec2-metadata -i > /var/www/html/index.html
Code language: YAML (yaml)

This is the content of writing the instance ID to index.html after installing Apache. This time, we will access and run this one Playbook via a NAT gateway and via VPC endpoints.

Architecting

We will use CloudFormation to build this environment and check the actual behavior.

Preparing Ansible Playbook

Before creating the CloudFormation stack, we will prepare Ansible. Specifically, we will zip up the Playbook and place it in an S3 bucket. For specific commands, please refer to the aforementioned page.

Create CloudFormation stack and check resources in stacks

Create a CloudFormation stack.
Please refer to the following page for information on how to create a stack and check each stack.

After checking the resources in each stack, the information for the main resources created this time is as follows

  • Instance1: i-0a2d78121ee6dfd1f
  • Instance2: i-057dde56603eebcf4

We will also check the resource creation status from the AWS Management Console. First, we will check the EC2 instances.

The two instances have been created successfully.

You can see that two instances have been created. Next, check the execution status of the SSM document in the SSM State Manager.

The SSM Association has been successfully created for the two instances.

You can see that a total of three associations have been created for the two instances, and the Status is “Success”, which indicates that they were executed successfully.

Operation check (1)

Now that everything is ready, let’s access the instances. First, let’s look at instance 1. We will use the SSM Session Manager to access the instance. For details, please refer to the following page.

% aws ssm start-session --target i-0a2d78121ee6dfd1f Starting session with SessionId: root-0f62c0c5edc7d8e07 sh-4.2$
Code language: Bash (bash)

Access yourself with curl.

sh-4.2$ curl http://localhost instance-id: i-0a2d78121ee6dfd1f
Code language: Bash (bash)

You can see that the contents of the Ansible Playbook have been successfully executed.
For reference, here is an excerpt from the log of the Playbook execution

Amazon Linux release 2 (Karoo) ... Installed: epel-release.noarch 0:7-14 ... Installed: ansible.noarch 0:2.9.27-1.el7 ... PLAY [all] ********************************************************************* TASK [update yum] ************************************************************** ... TASK [install the latest version of Apache] ************************************ ... TASK [start and enable Apache] ************************************************* ... TASK [make index.html] ********************************************************* ... PLAY RECAP ********************************************************************* localhost : ok=4 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Code language: plaintext (plaintext)

You can see that we have installed Ansible to resolve the dependencies before executing the contents of the Playbook.

Operation check (2)

Next is instance 2.

% aws ssm start-session --target i-057dde56603eebcf4 Starting session with SessionId: root-083a1d2a50de3e64a sh-4.2$ sh-4.2$ curl http://localhost instance-id: i-057dde56603eebcf4
Code language: Bash (bash)

This also returned its own ID, so you can see that the contents of the Ansible Playbook were executed successfully.
Let’s check the runtime logs for this one as well, starting with the AWS-RunShellScript log.

Loaded plugins: extras_suggestions, langpacks, priorities, update-motd ... Installed: ansible.noarch 0:2.9.23-1.amzn2 ... Complete!
Code language: plaintext (plaintext)

Next is the AWS-ApplyAnsiblePlaybooks log, which shows the installation of Ansible as specified in the template file.

PLAY [all] ********************************************************************* TASK [update yum] ************************************************************** ... TASK [install the latest version of Apache] ************************************ ... TASK [start and enable Apache] ************************************************* ... TASK [make index.html] ********************************************************* ... PLAY RECAP ********************************************************************* localhost : ok=4 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Code language: plaintext (plaintext)

This one does not install Ansible, but runs the Playbook from the beginning.

Summary

We have now seen how to run the AWS-ApplyAnsiblePlaybooks document in a private subnet.
Specifically, we used either a NAT gateway or VPC endpoints.

タイトルとURLをコピーしました