{"id":856,"date":"2021-07-12T01:21:00","date_gmt":"2021-07-12T01:21:00","guid":{"rendered":"https:\/\/blog.ngocha.biz\/?p=856"},"modified":"2021-07-12T01:21:00","modified_gmt":"2021-07-12T01:21:00","slug":"setup-ansible-aws-dynamic-inventory","status":"publish","type":"post","link":"https:\/\/blog.ngocha.biz\/?p=856","title":{"rendered":"How to Setup Ansible AWS Dynamic Inventory"},"content":{"rendered":"<p>When you are using Ansible with AWS, maintaining the inventory file will be a hectic task as AWS has frequently changed IPs, autoscaling instances, and much more.<\/p>\n<p>However, there is an easy solution called ansible dynamic inventory. Dynamic inventory is an ansible plugin that makes an API call to AWS to get the instance information in the run time. It gives you the ec2 instance details dynamically to manage the AWS infrastructure.<\/p>\n<figure class=\"kg-card kg-image-card kg-card-hascaption\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/ansiblee-inventory-1.png\" class=\"kg-image\" alt=\"AWS dynamic inventory workflow\" loading=\"lazy\" width=\"1109\" height=\"713\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/ansiblee-inventory-1.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/ansiblee-inventory-1.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/ansiblee-inventory-1.png 1109w\" sizes=\"auto, (min-width: 720px) 720px\"><figcaption><span style=\"white-space: pre-wrap;\">Click to view in HD<\/span><\/figcaption><\/figure>\n<p>When I started using the Dynamic inventory, it was just a Python file. Later it became an Ansible plugin.<\/p>\n<p>I will talk more about how to manage the AWS dynamic inventory later in this article.<\/p>\n<p>Dynamic inventory is not limited to just AWS. It supports most of the public and private cloud platforms. Here is the article on <a href=\"https:\/\/devopscube.com\/ansible-dymanic-inventry-google-cloud\/\" rel=\"noreferrer noopener\">managing GCP resources using Ansible Dynamic inventory.<\/a><\/p>\n<h2 id=\"setup-ansible-aws-dynamic-inventory\">Setup Ansible AWS Dynamic Inventory<\/h2>\n<p>In this tutorial, you will learn how to set up a dynamic inventory on AWS using boto and the AWS ec2 Ansible plugin.<\/p>\n<p>Follow the steps carefully for the setup.<\/p>\n<p><strong>Step 1:<\/strong> Ensure you have <code>python3 <\/code>&amp; <code>pip3<\/code> installed in your <a href=\"https:\/\/devopscube.com\/install-configure-ansible-server-nodes\/\">Ansible server<\/a>.<\/p>\n<p>Most Linux operating system comes with phyton3. You can validate it using the following command.<\/p>\n<pre><code>python3 --version<\/code><\/pre>\n<p>If you don&#8217;t have python3, you can install it using the following command.<\/p>\n<p>For centos, Redhat,<\/p>\n<pre><code>sudo yum install python3 -y\nsudo yum \u2013y install python3-pip<\/code><\/pre>\n<p>For Debian, Ubuntu,<\/p>\n<pre><code>sudo apt-get install python3 -y\nsudo apt-get install python3-pip -y<\/code><\/pre>\n<p><strong>Step 2:<\/strong> Install the boto3 library. Ansible uses the boot core to make API calls to AWS to retrieve ec2 instance details.<\/p>\n<pre><code>sudo pip3 install boto3<\/code><\/pre>\n<p>If you have used the Ansible ppa for installation, install pip using the following command.<\/p>\n<pre><code>sudo apt-get install python-boto3<\/code><\/pre>\n<p>or else you might see the following error.<\/p>\n<pre><code>ERROR! The ec2 dynamic inventory plugin requires boto3 and botocore.<\/code><\/pre>\n<p><strong>Step 3:<\/strong> Create an inventory directory under <code>\/opt<\/code> and cd into the directory.<\/p>\n<pre><code>sudo mkdir -p \/opt\/ansible\/inventory\ncd \/opt\/ansible\/inventory<\/code><\/pre>\n<p><strong>Step 4:<\/strong>  Create a  file named <strong><code>aws_ec2.yaml<\/code><\/strong> in the inventory directory.<\/p>\n<pre><code>sudo vi aws_ec2.yaml<\/code><\/pre>\n<p>Copy the following configuration to the file. If you are running an ansible server outside the AWS environment, replace add your AWS access key and secret to the config file.<\/p>\n<div class=\"kg-card kg-callout-card kg-callout-card-grey\">\n<div class=\"kg-callout-text\"><b><strong style=\"white-space: pre-wrap;\">Important Note:<\/strong><\/b> Never commmit this file to public git repos.<\/div>\n<\/div>\n<pre><code>---\nplugin: aws_ec2\naws_access_key: &lt;YOUR-AWS-ACCESS-KEY-HERE&gt;\naws_secret_key: &lt;YOUR-AWS-SECRET-KEY-HERE&gt;\nkeyed_groups:\n  - key: tags\n    prefix: tag<\/code><\/pre>\n<p>If your ansible server is running inside the AWS environment, attach an <strong>ec2 instance role<\/strong> with the required AWS ec2 permissions (Mostly describe instances). This way you don&#8217;t have to add the access and secret key in the configuration. Ansible will automatically use the attached role to make the AWS API calls.<\/p>\n<p><strong>Step 5:<\/strong> Open <strong><code>\/etc\/ansible\/ansible.cfg<\/code><\/strong> file.<\/p>\n<pre><code>sudo vi \/etc\/ansible\/ansible.cfg<\/code><\/pre>\n<p>Find the <code>[inventory]<\/code> section and add the following line to enable the ec2 plugin.<\/p>\n<pre><code>enable_plugins = aws_ec2<\/code><\/pre>\n<p>It should look something like this.<\/p>\n<pre><code>[inventory]\nenable_plugins = aws_ec2<\/code><\/pre>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-25-33.png\" class=\"kg-image\" alt=\"add ansible ec2 inventory plugin to ansible.cfg\" loading=\"lazy\" width=\"551\" height=\"278\"><\/figure>\n<p><strong>Step 6: <\/strong>Now let&#8217;s test the dynamic inventory configuration by listing the ec2 instances.<\/p>\n<pre><code>ansible-inventory -i \/opt\/ansible\/inventory\/aws_ec2.yaml --list<\/code><\/pre>\n<p>The above command returns the list of ec2 instances with all its parameters in JSON format.<\/p>\n<p>If you want to use the dynamic inventory as a default Ansible inventory, edit the <code><strong>\/etc\/ansible\/ansible.cfg<\/strong><\/code> file and search for inventory parameters under <code>defaults<\/code>. Change the inventory parameter value as shown below.<\/p>\n<pre><code>inventory      = \/opt\/ansible\/inventory\/aws_ec2.yaml<\/code><\/pre>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-26-31.png\" class=\"kg-image\" alt=\"add ec2 dynamic inventory as default inventory.\" loading=\"lazy\" width=\"554\" height=\"219\"><\/figure>\n<p>Now if you run the inventory list command without passing the inventory file, Ansible looks for the default location and picks up the <code>aws_ec2.yaml<\/code> inventory file.<\/p>\n<p><strong>Step 6:<\/strong> Execute the following command to test if Ansible is able to ping all the machines returned by the dynamic inventory.<\/p>\n<pre><code>ansible all -m ping<\/code><\/pre>\n<h2 id=\"grouping-ec2-resources-with-anisble-dynamic-inventory\">Grouping EC2 Resources With Anisble Dynamic Inventory<\/h2>\n<hr>\n<p>The primary use case of AWS Ansible dynamic inventory is to execute Ansible playbooks or ad-hoc commands against a single or group of categorized or grouped instances based on tags, regions, or other ec2 parameters.<\/p>\n<p>You can group instances using tags, instances type, instance names, custom filters, and more. Take a look at all supported filters and keyed groups <a href=\"https:\/\/docs.ansible.com\/ansible\/latest\/plugins\/inventory\/aws_ec2.html?ref=devopscube.com\" rel=\"noreferrer noopener\">from here<\/a>.<\/p>\n<p>Here is a minimal configuration for <code>aws_ec2.yaml<\/code> that uses a few keyed_groups and filters.<\/p>\n<pre><code>---\nplugin: aws_ec2\n\naws_access_key: &lt;YOUR-AWS-ACCESS-KEY-HERE&gt;\naws_secret_key: &lt;YOUR-AWS-SECRET-KEY-HERE&gt;\n\nregions:\n  - us-west-2\n\nkeyed_groups:\n  - key: tags\n    prefix: tag\n  - prefix: instance_type\n    key: instance_type\n  - key: placement.region\n    prefix: aws_region<\/code><\/pre>\n<p>Execute the following command to list the dynamic inventory groups.<\/p>\n<pre><code>ansible-inventory --graph<\/code><\/pre>\n<p>You will see an output like the following with all instances grouped under tags, zones, and regions with dynamic group names like  <code>aws_region_us_west_2<\/code> , <code>instance_type_t2_micro<\/code>, <code>tag_Name_Ansible<\/code><\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/aws-inventory-grouping-min-1.png\" class=\"kg-image\" alt=\"ansible AWS ec2 dynamic inventory graph\" loading=\"lazy\" width=\"530\" height=\"496\"><\/figure>\n<p>Now you can execute Ansible ad-hoc commands or playbook against these groups.<\/p>\n<h2 id=\"execute-ansible-commands-with-ec2-dynamic-inventory\">Execute Ansible Commands With ec2 Dynamic Inventory<\/h2>\n<p>Let&#8217;s test the ec2 dynamic inventory by executing few ansible ad-hoc commands.<\/p>\n<div class=\"kg-card kg-callout-card kg-callout-card-grey\">\n<div class=\"kg-callout-text\"><b><strong style=\"white-space: pre-wrap;\">Note: <\/strong><\/b>Make sure you have the SSH keys or user\/password setup in your ansible configuration for Ansible to connect to it for executing the commands.<\/div>\n<\/div>\n<h3 id=\"execute-ping\">Execute Ping<\/h3>\n<p>I am going to execute the ping command with all instances in the region <code>us_west_2<\/code>. As per my configuration, the dynamic group name is <code>aws_region_us_west_2<\/code>.<\/p>\n<pre><code>ansible aws_region_us_west_2 -m ping<\/code><\/pre>\n<p>If you have all the right configurations, you should see an output like the following.<\/p>\n<pre><code>ec2-54-218-105-53.us-west-2.compute.amazonaws.com | SUCCESS =&gt; {\n    \"ansible_facts\": {\n        \"discovered_interpreter_python\": \"\/usr\/bin\/python3\"\n    },\n    \"changed\": false,\n    \"ping\": \"pong\"\n}<\/code><\/pre>\n<h2 id=\"using-dynamic-inventory-inside-playbook\">Using Dynamic Inventory Inside Playbook<\/h2>\n<p>If you want to use dynamic inventory inside the playbook, you just need to mention the group name in the hosts variable as shown below.<\/p>\n<pre><code>---\n- name: Ansible Test Playbook\n  gather_facts: false\n  hosts: aws_region_us_west_2\n  tasks:\n\n    - name: Run Shell Command\n      command: echo \"Hello World\"<\/code><\/pre>\n<p>You checkout the <a href=\"https:\/\/devopscube.com\/ansible-playbook-examples\/\">ansible playbook examples<\/a> if you want to test more playbooks.<\/p>\n<hr>\n<p><strong>Ngu\u1ed3n:<\/strong> <a href=\"https:\/\/devopscube.com\/setup-ansible-aws-dynamic-inventory\/\" target=\"_blank\" rel=\"noopener noreferrer\">How to Setup Ansible AWS Dynamic Inventory \u2014 DevOpsCube<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Source: https:\/\/devopscube.com\/setup-ansible-aws-dynamic-inventory\/<\/p>\n","protected":false},"author":1,"featured_media":857,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-856","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-devops"],"_links":{"self":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts\/856","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=856"}],"version-history":[{"count":0,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts\/856\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/media\/857"}],"wp:attachment":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=856"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=856"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=856"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}