{"id":792,"date":"2020-06-20T06:00:00","date_gmt":"2020-06-20T06:00:00","guid":{"rendered":"https:\/\/blog.ngocha.biz\/?p=792"},"modified":"2020-06-20T06:00:00","modified_gmt":"2020-06-20T06:00:00","slug":"ansible-dymanic-inventry-google-cloud","status":"publish","type":"post","link":"https:\/\/blog.ngocha.biz\/?p=792","title":{"rendered":"How To Setup Ansible Dynamic Inventory on Google Cloud"},"content":{"rendered":"<p>The best way to manage and orchestrate VM instances in Google cloud using <a href=\"https:\/\/devopscube.com\/install-configure-ansible-server-nodes\/\" rel=\"noopener noreferrer\">Ansible<\/a> is through Dynamic inventory plugin. It is an ansible google cloud module that authenticates GCP in run time and returns the instance details.<\/p>\n<p>With dynamic inventory, you don&#8217;t need to manage a static inventory file, instead, you can group instances based on <strong>instance labels, zones, and network tags<\/strong>. Even you can group instances based on names.<\/p>\n<h2 id=\"ansible-dynamic-inventory-google-cloud-configuration\">Ansible Dynamic Inventory Google Cloud Configuration<\/h2>\n<hr>\n<p>Let&#8217;s get started.<\/p>\n<p><strong>Prerequisites:<\/strong><\/p>\n<ol>\n<li>You should have pip installed<\/li>\n<li>Ansible installed<\/li>\n<li>Google Service Account JSON with permissions to provision GCP resources.<\/li>\n<\/ol>\n<p>Follow the steps given below to configure Ansible dynamic inventroy GCP plugin,<\/p>\n<p><strong>Step 1: <\/strong>Install google-auth module using pip.<\/p>\n<pre><code>sudo pip install requests google-auth<\/code><\/pre>\n<p><strong>Step 2:<\/strong> Create a dedicated inventory directory<\/p>\n<pre><code>sudo mkdir -p \/opt\/ansible\/inventory<\/code><\/pre>\n<p><strong>Step 3:<\/strong> Create a <a href=\"https:\/\/cloud.google.com\/iam\/docs\/creating-managing-service-accounts?ref=devopscube.com\" rel=\"noreferrer noopener\">Google IAM service account<\/a>. It will be used by the Ansible server to authenticate against google cloud for dynamic inventory. A service account json will look like the following.<\/p>\n<pre><code>{\n  \"type\": \"service_account\",\n  \"project_id\": \"devopscube-sandbox\",\n  \"private_key_id\": \"sdfkjhsadfkjansdf9asdf87eraksd\",\n  \"private_key\": \"-----BEGIN PRIVATE KEY-----\\nMIIEvQIBADANBaksdhfjkasdljf sALDIFUHW8klhklSDGKAPISD GIAJDGHIJLSDGJAFSHGJN;MLASDKJHFGHAILFN DGALIJDFHG;ALSDN J Lkhawu8a2 87356801w tljasdbjkh=\\n-----END PRIVATE KEY-----\\n\",\n  \"client_email\": \"ansible-provisioning@devopscube-sandbox.iam.gserviceaccount.com\",\n  \"client_id\": \"32453948568273645823\",\n  \"auth_uri\": \"https:\/\/accounts.google.com\/o\/oauth2\/auth\",\n  \"token_uri\": \"https:\/\/accounts.google.com\/o\/oauth2\/token\",\n  \"auth_provider_x509_cert_url\": \"https:\/\/www.googleapis.com\/oauth2\/v1\/certs\",\n  \"client_x509_cert_url\": \"https:\/\/www.googleapis.com\/robot\/v1\/metadata\/x509\/ansible-provisioning%40devopscube-sandbox.iam.gserviceaccount.com\"\n} <\/code><\/pre>\n<p><strong>Step 5:<\/strong> Save the service account file as<code> service-account.json<\/code> inside <code>\/opt\/ansible\/inventory<\/code> folder.<\/p>\n<p><strong>Step 6: <\/strong> Create a file named gcp.yaml inside \/opt\/ansible\/inventory directory and add the following content.<\/p>\n<pre><code>---\nplugin: gcp_compute\nprojects:\n  - &lt;gcp-project-id&gt;\nauth_kind: serviceaccount\nservice_account_file: \/opt\/ansible\/inventory\/service-account.json<\/code><\/pre>\n<p>Replace &lt;gcp-project-id&gt; with your google cloud project id. You can get the id from the GCP dashboard.<\/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\/gcp-project-id-min-1.png\" class=\"kg-image\" alt=\"gcp project id for ansible dynamic inventory\" loading=\"lazy\" width=\"555\" height=\"340\"><figcaption><span style=\"white-space: pre-wrap;\">Click to view in HD<\/span><\/figcaption><\/figure>\n<p>There are more configuration<\/p>\n<p><strong>Step 4<\/strong>: Change the inventory folder&#8217;s permission to 755.<\/p>\n<pre><code>sudo chmod -R 755 \/opt\/ansible<\/code><\/pre>\n<p><strong>Step 5: <\/strong>Now we have all the required configurations for gcp dynamic inventory. Lets test it by listing out all the instances using the <code>ansible-inventory<\/code> command. Make sure you are running this command from <code>\/opt\/ansible\/inventory<\/code> directory.<\/p>\n<pre><code>ansible-inventory --list -i gcp.yaml<\/code><\/pre>\n<p>The above command should give a JSON output with all the instance details. Which means, now Ansible is able to communicate to GCP via service account.<\/p>\n<p>Here is an example output.<\/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\/anisble-gcp-inventory-min-1.png\" class=\"kg-image\" alt=\"Ansible GCP  dynamic inventory instance list\" loading=\"lazy\" width=\"581\" height=\"513\"><figcaption><span style=\"white-space: pre-wrap;\">Click to view in HD<\/span><\/figcaption><\/figure>\n<p><strong>Step 5:<\/strong> Open<code> \/etc\/ansible\/ansible.cfg<\/code> file Add the dynamic inventory config path under default configs.<\/p>\n<pre><code>[defaults]\n\n# some basic default values...\n\ninventory      = \/opt\/ansible\/inventory\/gcp.yaml<\/code><\/pre>\n<p>With this configuration, by default all the ansible action will consider the gcp config as its inventory file.<\/p>\n<p>You can verify the default inventory configuration by executing the inventory list command.<\/p>\n<pre><code>ansible-inventory --list<\/code><\/pre>\n<p>You should get the similar output you got in step 4.<\/p>\n<h2 id=\"grouping-gcp-resources\">Grouping GCP Resources<\/h2>\n<hr>\n<p>Now we have al the configurations for Ansible to interact with GCP. But it is not enough. We need to group resources to execute ansible commands or playbooks against all the servers in that group.<\/p>\n<p>Now, here is the cool feature!<\/p>\n<p>GCP Ansible module automatically groups your resources based on a few standard parameters.<\/p>\n<p>Ansible GCP module supports grouping using labels, zones, and network tags. Grouping with labels is the best way to manage resources using Ansible. It would be best if you had a standard and consistent labeling standard across all your environments.<\/p>\n<p>Here is the inventory file example where I have added grouping using labels and Zone. Also, there are two groups named &#8220;development&#8221; and &#8220;staging&#8221;. These will return all VMS, which matches the filter.<\/p>\n<pre><code>---\nplugin: gcp_compute\nprojects:\n  - devopscube-262115\nauth_kind: serviceaccount\nservice_account_file: \/opt\/ansible\/inventory\/service-account.json\nkeyed_groups:\n  - key: labels\n    prefix: label\n  - key: zone\n    prefix: zone\ngroups:\n  development: \"'env' in (labels|list)\"\n  staging: \"'jenkins' in name\"<\/code><\/pre>\n<p>Modify your inventory file with the above keyed_groups &amp; groups and execute the following command to list the groups.<\/p>\n<pre><code>ansible-inventory --graph<\/code><\/pre>\n<p>The following output shows all the machines grouped as per the labels and group filters as shown below.<\/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\/ansible-dynamic-inventory-grouping-min-1.png\" class=\"kg-image\" alt=\"\" loading=\"lazy\"><figcaption><span style=\"white-space: pre-wrap;\">Click to view in HD<\/span><\/figcaption><\/figure>\n<p>Now, you can use the group names to execute remote commands on all the machines which comes under the group.<\/p>\n<h2 id=\"execute-ansible-commands-with-dynamic-inventory-on-gcp\">Execute Ansible Commands With Dynamic Inventory On GCP<\/h2>\n<hr>\n<p>Now, let&#8217;s test our configuration by running a few ansible ad-hoc remote commands.<\/p>\n<p>I have added the default remote private key and remote user in ansible.cfg file so that Ansible can communicate to the remote host via ssh.<\/p>\n<p>The following are the parameters required for the remote connection. Replace the values accordingly.<\/p>\n<pre><code>remote_user = bibin.w\nhost_key_checking = False\nprivate_key_file = \/home\/bibin.w\/.ssh\/id_rsa<\/code><\/pre>\n<h3 id=\"execute-remote-ping\">Execute Remote Ping<\/h3>\n<p>In my dynamic inventory configuration, I have added a group named staging, which groups all machines with &#8220;jenkins&#8221; in the instance name.<\/p>\n<p>I am going to execute a ping command against the staging group.<\/p>\n<pre><code>ansible staging -m ping<\/code><\/pre>\n<p>It successfully executes ping command on an instance which matches the staging group. Here is the output.<\/p>\n<pre><code>root@ansible-inventory:\/etc\/ansible# ansible staging -m ping\n35.192.72.62 | SUCCESS =&gt; {\n    \"ansible_facts\": {\n        \"discovered_interpreter_python\": \"\/usr\/bin\/python3\"\n    },\n    \"changed\": false,\n    \"ping\": \"pong\"\n}<\/code><\/pre>\n<h3 id=\"execute-a-remote-shell-command\">Execute a Remote Shell Command<\/h3>\n<p>Following ansible ad-hoc command executes an echo command on all servers which belong to the staging group.<\/p>\n<pre><code>ansible staging -m shell -a 'echo \"Hello World\"'<\/code><\/pre>\n<p>Here is the output.<\/p>\n<pre><code>root@ansible-inventory:\/etc\/ansible# ansible staging -m shell -a 'echo \"Hello World\"'\n35.192.72.62 | CHANGED | rc=0 &gt;&gt;\nHello 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 the dynamic inventory by executing playbooks.<\/p>\n<h2 id=\"few-best-practices\">Few Best Practices<\/h2>\n<p>When you are using the Ansible dynamic inventory on google cloud, follow the best practices given below.<\/p>\n<ol>\n<li>Use labels to group the instances.<\/li>\n<li>Have a standard instance labeling strategy and naming schemes.<\/li>\n<li>Do not commit the GCP service account JSON to Github or any other SCM.<\/li>\n<li>Always dry run ansible playbooks before you execute directly on the VMs.<\/li>\n<\/ol>\n<hr>\n<p><strong>Ngu\u1ed3n:<\/strong> <a href=\"https:\/\/devopscube.com\/ansible-dymanic-inventry-google-cloud\/\" target=\"_blank\" rel=\"noopener noreferrer\">How To Setup Ansible Dynamic Inventory on Google Cloud \u2014 DevOpsCube<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Source: https:\/\/devopscube.com\/ansible-dymanic-inventry-google-cloud\/<\/p>\n","protected":false},"author":1,"featured_media":793,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-792","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\/792","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=792"}],"version-history":[{"count":0,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts\/792\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/media\/793"}],"wp:attachment":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=792"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=792"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=792"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}