<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Ardhendu's blog]]></title><description><![CDATA[Ardhendu's blog]]></description><link>https://ardhendushekhar.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Wed, 23 Sep 2026 07:43:36 GMT</lastBuildDate><atom:link href="https://ardhendushekhar.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Learnings with Ansible: Chapter 5]]></title><description><![CDATA[Introduction
The 2nd of February is the day Punxsutawney Philis is going to predict winter or early spring in the eyes of many believers. Today, Bill Murray too might find himself in a time loop with the same day going over and over(!). And it’s also...]]></description><link>https://ardhendushekhar.hashnode.dev/learnings-with-ansible-chapter-5</link><guid isPermaLink="true">https://ardhendushekhar.hashnode.dev/learnings-with-ansible-chapter-5</guid><category><![CDATA[ansible]]></category><category><![CDATA[ansible-playbook]]></category><category><![CDATA[configuration management]]></category><category><![CDATA[Devops]]></category><category><![CDATA[#Devopscommunity]]></category><dc:creator><![CDATA[Ardhendu Shekhar]]></dc:creator><pubDate>Thu, 01 Feb 2024 18:30:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1707376332923/6b380316-6bac-434d-a663-c24215981798.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>The 2nd of February is the day <a target="_blank" href="https://en.wikipedia.org/wiki/Punxsutawney_Phil">Punxsutawney Philis</a> is going to predict winter or early spring in the eyes of many believers. Today, Bill Murray too might find himself in a time loop with the same day going over and over(!). And it’s also when we rendezvous for the next chapter of our Ansible Safari. Very fancy!</p>
<p>So where were we? Yes. We were going ad-hoc! So, let’s talk about the important built-in module called <em>ansible.builtin.copy.</em> Of course, with the proper arguments as the name suggests, this module is going to help us copy files from the control machine to one or many of the target machines.</p>
<h3 id="heading-copy-modules-in-ansible"><strong>Copy Modules in Ansible</strong></h3>
<p>Let’s first create a temporary text file for getting hands-on. We’ll call it index.html using vim {filename.ext} and populate it with some text. In this case, it’ll be an <strong>index.html</strong> file with the text “Ansible test file”.</p>
<p>After getting into our target machine, the command for achieving this would look something like this:</p>
<pre><code class="lang-bash">ansible rmwebservers -m ansible.builtin.copy -a <span class="hljs-string">"src=index.html dest=/var/www/html/index.html"</span> -i inventory --become
</code></pre>
<p>which should hopefully lead to this:</p>
<p><img src="https://miro.medium.com/v2/resize:fit:875/1*EUfl38WM-OYf3jEx2TmVog.png" alt /></p>
<p>Let’s talk about what happened here.</p>
<ol>
<li><p>First, we must take into account that since we’re copying files here we have to have <strong>a source</strong> and <strong>a destination</strong>. The important thing to remember is the way we give values to these arguments, in this case, “src” and “dest”. src contains index.html precisely because we’re executing the command from the same directory that contains the index.html file. On the other hand, dest contains an absolute path to be resolved in the target machine(s), in this case, the machines in the rmwebservers group.</p>
</li>
<li><p>Secondly, there’s a lot of beautiful amazing information in the output that we just got. The thing that is going to help us in the future is the “owner” field. Remember this!</p>
</li>
</ol>
<p>Obviously, if I rerun the command I should get something like this:</p>
<p><img src="https://miro.medium.com/v2/resize:fit:875/1*dlz6uG_GsWkJntRNwOasLw.png" alt /></p>
<p>signifying the <strong>idempotent</strong> (maintenance of state) nature of configuration tools, in our case, Ansible. An exercise on this would be to make any changes in the text file and rerun the command.</p>
<p>Well, all this has been a sneak attack (a little project). We’ve copied (overridden) the file into the httpd (Tomcat) server’s default webpage location and if you log into any one of EC2 instances, you’ll find this:</p>
<p><img src="https://miro.medium.com/v2/resize:fit:875/1*pBkcjQsdZjktjQfJb0dvNA.png" alt="Contents of the index.html file we copied" /></p>
<h1 id="heading-ansible-playbooks"><strong>Ansible Playbooks</strong></h1>
<p>What????? REALLY??? Not a dream. I can stretch a joke only so far. We’ll create a new one in this chapter or the next. Anyway, this is going to be just an overview so <em>calm down</em>.</p>
<h3 id="heading-what-are-playbooks">What are Playbooks?</h3>
<p>These are books we play with. Actually, no. Close though. These are books that contain plays. Plays on the other hand contain tasks which we, you and me, want to perform on the remote machines. If the reader has a little bit high level of Docker-compose this is going to be super duper easy. For the rest, we’ll manage with super easy.</p>
<p>So, let’s learn by example.</p>
<pre><code class="lang-yaml"><span class="hljs-meta">---</span>

<span class="hljs-bullet">-</span> <span class="hljs-attr">hosts:</span> <span class="hljs-string">rmwebservers</span>
  <span class="hljs-attr">tasks:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Install</span> <span class="hljs-string">Apache</span> <span class="hljs-string">App</span> <span class="hljs-string">Server</span>
      <span class="hljs-attr">yum:</span>
        <span class="hljs-attr">name:</span> <span class="hljs-string">httpd</span>
        <span class="hljs-attr">state:</span> <span class="hljs-string">latest</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Deploy</span> <span class="hljs-string">config</span>
      <span class="hljs-attr">copy:</span> 
        <span class="hljs-attr">src:</span> <span class="hljs-string">file/httpd.conf</span>
        <span class="hljs-attr">dest:</span> <span class="hljs-string">/etc/httpd.conf</span>

<span class="hljs-bullet">-</span> <span class="hljs-attr">hosts:</span> <span class="hljs-string">rmdbservers</span>
  <span class="hljs-attr">tasks:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Install</span> <span class="hljs-string">PostgreSQL</span>
      <span class="hljs-attr">yum:</span> 
        <span class="hljs-attr">name:</span> <span class="hljs-string">postgresql</span>
        <span class="hljs-attr">state:</span> <span class="hljs-string">latest</span>
</code></pre>
<p><em>Note: Revise Python lists and dictionaries, it’ll come in handy.</em></p>
<p>As mentioned, a playbook is a list of <strong>plays</strong>. You must be aware that a list in YAML is denoted by the (-) symbol.</p>
<p>Let’s dive deeper into this sample playbook:</p>
<ol>
<li><p>The ( — -) symbol denotes that whatever comes next has to be treated as YAML or a part of YAML.</p>
</li>
<li><p>We have a list of two plays (python dictionaries) with corresponding key-value pairs. An easy way to segregate the plays is through hostnames or just by looking at the indentation levels.</p>
</li>
</ol>
<p>For elaboration, we could look at this in this way:</p>
<pre><code class="lang-python"><span class="hljs-comment">## List and Dictionary representation of the above Playbook</span>

playbook = [
    {
        <span class="hljs-string">'hosts'</span>: <span class="hljs-string">'rmwebservers'</span>,
        <span class="hljs-string">'tasks'</span>: [
            {
                <span class="hljs-string">'name'</span>: <span class="hljs-string">'Install Apache App Server'</span>,
                <span class="hljs-string">'yum'</span>: {
                    <span class="hljs-string">'name'</span>: <span class="hljs-string">'httpd'</span>,
                    <span class="hljs-string">'state'</span>: <span class="hljs-string">'latest'</span>
                }
            },
            {
                <span class="hljs-string">'name'</span>: <span class="hljs-string">'Deploy config'</span>,
                <span class="hljs-string">'copy'</span>: {
                    <span class="hljs-string">'src'</span>: <span class="hljs-string">'file/httpd.conf'</span>,
                    <span class="hljs-string">'dest'</span>: <span class="hljs-string">'/etc/httpd.conf'</span>
                }
            }
        ]
    },
    {
        <span class="hljs-string">'hosts'</span>: <span class="hljs-string">'rmdbservers'</span>,
        <span class="hljs-string">'tasks'</span>: [
            {
                <span class="hljs-string">'name'</span>: <span class="hljs-string">'Install PostgreSQL'</span>,
                <span class="hljs-string">'yum'</span>: {
                    <span class="hljs-string">'name'</span>: <span class="hljs-string">'postgresql'</span>,
                    <span class="hljs-string">'state'</span>: <span class="hljs-string">'latest'</span>
                }
            }
        ]
    }
]
</code></pre>
<blockquote>
<p><em>Here, playbook is a list containing two dictionaries. Each dictionary corresponds to a block in the original YAML data. Each dictionary has a</em><code>'hosts'</code><em>key and a</em><code>'tasks'</code><em>key. The</em><code>'tasks'</code><em>key contains a list of dictionaries representing the tasks specified under each host. Each task dictionary contains keys such as</em><code>'name'</code><em>and</em><code>'yum'</code><em>where the former describes the name of the task and the latter is containing another dictionary having two key-value pairs, name (of the package) and state (the target state, latest). State as ‘<strong><strong>Latest</strong></strong>’ means in addition to installation, it will go ahead and update if it is not of the latest available version.</em></p>
</blockquote>
<p>The descriptions of them are as follows:</p>
<ul>
<li><p><strong>hosts</strong>: Pretty self-explanatory. Hosts or the remote machines this particular play is going to act on. Defines a particular play.</p>
</li>
<li><p><strong>tasks</strong>: Can contain many fields but in the most basic form, we have to have a name for the task, the module it’s going to make use of and the action it’s going to take with the target states mentioned as arguments.</p>
</li>
</ul>
<p>If you go ahead and execute this right now by googling things, it won’t work. The why behind that is a secret sauce for the next chapter.</p>
<h1 id="heading-what-next"><strong>What next?</strong></h1>
<p>Now that the joke is over (sadly), we’ll dive much deeper into playbooks. Like a deep ocean dive if you will. It’ll be so much playbook this and playbook that. Almost like</p>
<p><img src="https://miro.medium.com/v2/resize:fit:768/1*2kPDHlFR5lWYyR0f-5Uw2A.jpeg" alt class="image--center mx-auto" /></p>
<p>You thought I wouldn’t use this legend of a meme TODAY? Think again!</p>
<p>Stay tuned.</p>
<p>Connect with me on <a target="_blank" href="http://www.linkedin.com/in/shekhardhendu">Linkedin</a>.</p>
<p><em>Originally published at</em><a target="_blank" href="https://medium.com/@ardhendushekharwork/learnings-with-ansible-chapter-5-7f189ab077b8">https://medium.com</a><em>on February 2, 2024.</em></p>
]]></content:encoded></item><item><title><![CDATA[Learnings with Ansible: Chapter 4]]></title><description><![CDATA[Introduction
Do you notice how unplanned trips or getaways in today's monotonous life always turn out to be the best? If you do, you'll love what we'll get into today.
Google defines ad hoc as

made or happening only for a particular purpose or need,...]]></description><link>https://ardhendushekhar.hashnode.dev/learnings-with-ansible-chapter-4</link><guid isPermaLink="true">https://ardhendushekhar.hashnode.dev/learnings-with-ansible-chapter-4</guid><category><![CDATA[Devops]]></category><category><![CDATA[ansible]]></category><category><![CDATA[ansible-module]]></category><category><![CDATA[ansible-playbook]]></category><category><![CDATA[configuration management]]></category><dc:creator><![CDATA[Ardhendu Shekhar]]></dc:creator><pubDate>Thu, 25 Jan 2024 18:34:13 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1706207133563/fc05f3df-9c2c-4dc1-90ca-16b70869d8ba.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>Do you notice how unplanned trips or getaways in today's monotonous life always turn out to be the best? If you do, you'll love what we'll get into today.</p>
<p>Google defines ad hoc as</p>
<blockquote>
<p>made or happening only for a particular purpose or need, not planned before it happens</p>
</blockquote>
<p>and rightfully so. We do encounter such situations almost daily and our guy Ansible isn't someone who likes to stay out of action. Hence, we have tons of ad hoc commands to practice, learn, and love hopefully.</p>
<p>It's super important that you refer to the documentation, especially for this lesson, and here's the <a target="_blank" href="https://docs.ansible.com/ansible/latest/command_guide/intro_adhoc.html">link</a> for that.</p>
<p>As always, there are some important things to remember before we begin:</p>
<ol>
<li><p><strong>Ansible uses states</strong> to perform actions/tasks. We give Ansible a task along with a target state we wish to achieve on the target machine.</p>
</li>
<li><p>Ansible has a lot of extremely helpful <strong>built-in modules</strong>.</p>
</li>
</ol>
<h2 id="heading-commands">Commands</h2>
<h3 id="heading-installation-using-package-management">Installation using Package management</h3>
<p>The first command we execute will use the built-in module called <em>ansible.builtin.yum</em> with the proper arguments. You can read more on Yum <a target="_blank" href="https://www.redhat.com/sysadmin/how-manage-packages">here</a>. The command would look like:</p>
<pre><code class="lang-bash">ansible remotemachine01 -m ansible.builtin.yum -a <span class="hljs-string">"name=httpd state=present"</span> -i inventory
</code></pre>
<p>The interesting part is that when we execute this, it'll throw an error which would look something like:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1706203581079/f93372ff-f4fd-4e3c-bac0-4f6b54adc826.png" alt class="image--center mx-auto" /></p>
<p>We spoke about the "changed" field, right? Here's when it shines. What's happening here is</p>
<blockquote>
<p>We have asked ansible to execute a yum install command (internally through python scripts ofcourse) for installing httpd web server on the target machine with the host name remotemachine01, along with (read carefully), the target state of the machine with regards to the change we desire. Here,</p>
<p>change = installation of httpd and</p>
<p>state = present</p>
<p>which means in a plain sense, that we want such a state where httpd is present.</p>
</blockquote>
<p>Alright. But what about the error Mr. Layman? Well, there's the amazing "msg" field for saving ourselves from endless troubleshooting. Let's read it. It says "This command has to be run under the root user."</p>
<p><em>Note: I'm assuming that you're aware of users, sudo, and privilege escalation basics in Linux. If you aren't, I do have some resources for you in the end.</em></p>
<p>The "ec2-user" user that we are using does have the sudo privilege (is a sudoer) but needs an instruction to exercise that power. This means that we're going to have to modify our ad hoc command a little bit. Like:</p>
<pre><code class="lang-bash">ansible remotemachine01 -m ansible.builtin.yum -a <span class="hljs-string">"name=httpd state=present"</span> -i inventory --become
</code></pre>
<p>where --become serves the purpose of asking the user we're using to log in to the target machine to execute commands using sudo. Let's execute this and hope that it looks like:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1706204843558/13131afe-12fb-4e50-8a74-4ed363c1d482.png" alt class="image--center mx-auto" /></p>
<p>Happily so, our "changed" field says true which means that the present state of the target machine (here, remotemachine01) is indeed, changed. The "results" field describes the changes made (here, httpd installation).</p>
<p>Let's try something more interesting. We'll change the host from a single host to a group in our commands and explore more.</p>
<pre><code class="lang-bash">ansible rmwebservers -m ansible.builtin.yum -a <span class="hljs-string">"name=httpd state=present"</span> -i inventory --become
</code></pre>
<p>When we execute this, we'll see:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1706205341042/3b1fa038-6990-4a34-a527-163cfba90080.png" alt class="image--center mx-auto" /></p>
<p>Now, the already updated (the machine with the changed state) status has the changed field as false while the other one is updated with the desired state. Here, remotemachine02 was not in the same state and hence, it applied the changes. And now let's run this command once again.</p>
<p>If we re-run the command we'll see something like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1706206093641/b5149e00-1912-4209-b56e-84e41e2e8fd9.png" alt class="image--center mx-auto" /></p>
<p>What we see above, is <strong>configuration management</strong> using target/desired states and is greatly used in the DevOps world.</p>
<p><em>Note: A fun exercise for you all would be changing the state as absent in the above commands and analyzing the output.</em></p>
<h3 id="heading-starting-and-enabling-installed-services">Starting and Enabling installed Services</h3>
<p>For starting and enabling (so that it starts at boot time. Read about systemd and symlinks for more on this) a service, we can use another built-in command called ansible.builtin.service. The command would look like:</p>
<pre><code class="lang-bash">ansible rmwebservers -m ansible.builtin.service -a <span class="hljs-string">"name=httpd state=started enabled=yes"</span> -i inventory --become
</code></pre>
<p>and it should give us</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1706206833937/ab592e25-3da3-45d1-ad3a-342ab582f7c5.png" alt class="image--center mx-auto" /></p>
<p>where we've successfully changed the target state of the machines, enabled the httpd service, and started it as well.</p>
<p>So, that's a lot for you all to think about and a little exercise for you would most definitely be another module called ansible.builtin.copy. We'll discuss it in the next one before jumping onto playbooks (yes, it's gonna be funny for as long as I WANT!).</p>
<h2 id="heading-what-next">What next?</h2>
<p>The above-mentioned module, its corresponding ad hoc commands, a little project, and the basics of Ansible playbooks are what we'll get into next. And to address the playbook situation, I think I'm borderline funny. OR MAYBE--</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1706207317563/6230b534-57ed-49e2-b48f-88776423d519.jpeg" alt class="image--center mx-auto" /></p>
<p><strong>Connect with me on</strong><a target="_blank" href="https://www.linkedin.com/in/shekhardhendu/"><strong>My LinkedIn</strong></a><strong>.</strong></p>
]]></content:encoded></item><item><title><![CDATA[Learnings with Ansible: Chapter 3]]></title><description><![CDATA[Hello! Did you miss me? (I definitely miss watching Sherlock). So, did you fall for Ansible? If you didn't, we'll try more.
We reached the world of "ad-hoc" commands by the end of the last chapter. We also executed our first command. If you need to r...]]></description><link>https://ardhendushekhar.hashnode.dev/learnings-with-ansible-chapter-3</link><guid isPermaLink="true">https://ardhendushekhar.hashnode.dev/learnings-with-ansible-chapter-3</guid><category><![CDATA[ansible]]></category><category><![CDATA[ansible-module]]></category><category><![CDATA[Devops]]></category><category><![CDATA[#Devopscommunity]]></category><dc:creator><![CDATA[Ardhendu Shekhar]]></dc:creator><pubDate>Fri, 19 Jan 2024 18:23:43 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1705688520079/501a4cd2-76b3-4ff3-a9ad-873ccf23204a.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hello! Did you miss me? (I definitely miss watching Sherlock). So, did you fall for Ansible? If you didn't, we'll try more.</p>
<p>We reached the world of "ad-hoc" commands by the end of the last chapter. We also executed our first command. If you need to revise, here you go.</p>
<p>Here's a little refresher.</p>
<pre><code class="lang-bash">ansible remotemachine01 -m ping -i inventory
</code></pre>
<p>where ansible is our best friend, remotemachine01 is the name for our target one (refer inventory), the -m flag is followed by the module we want to work with, here it's ping, and -i goes with the inventory file.</p>
<p>So, as promised we'll dive deeper into two things in this chapter. They are:</p>
<ol>
<li><p>The inventory file.</p>
</li>
<li><p>The output of our first ad-hoc command.</p>
</li>
</ol>
<h2 id="heading-groups-in-ansible-inventory">Groups in Ansible Inventory</h2>
<p>The official documentation refers to ansible inventory as:</p>
<blockquote>
<p>a list or group of lists to automate tasks on managed nodes or “hosts” in your infrastructure</p>
</blockquote>
<p>Through the Ansible inventory file, Ansible knows where to look for (ansible_host, ansible_user, etc) and what to look with (ansible_ssh_private_key_file) because as mentioned before, Ansible uses established connections specific to specific operating systems, in this case, SSH, to form connections.</p>
<p>Let's understand its structure. As mentioned above, it's a list of groups. But what's important to note is:</p>
<ul>
<li><p>Each <strong>group</strong> has <strong>children</strong> which can be or cannot be defined.</p>
</li>
<li><p>In most cases, this is used in conjunction with a <strong>hierarchical</strong> structure.</p>
</li>
</ul>
<p>Let's see our inventory file, shall we?</p>
<pre><code class="lang-yaml"><span class="hljs-attr">all:</span>
  <span class="hljs-attr">hosts:</span>
    <span class="hljs-attr">remotemachine01:</span>
      <span class="hljs-attr">ansible_host:</span> <span class="hljs-number">172.31</span><span class="hljs-number">.18</span><span class="hljs-number">.192</span>         <span class="hljs-string">//will</span> <span class="hljs-string">be</span> <span class="hljs-string">different</span> <span class="hljs-string">for</span> <span class="hljs-string">you</span> <span class="hljs-string">obviously</span>
      <span class="hljs-attr">ansible_user:</span> <span class="hljs-string">ec2-user</span>                     <span class="hljs-string">//amazon</span> <span class="hljs-string">does</span> <span class="hljs-string">this</span> <span class="hljs-string">for</span> <span class="hljs-string">RHEL</span> <span class="hljs-string">OS</span>
      <span class="hljs-attr">ansible_ssh_private_key_file:</span> <span class="hljs-string">clientkey.pem</span>     <span class="hljs-string">//our</span> <span class="hljs-string">private</span> <span class="hljs-string">key</span> <span class="hljs-string">for</span> <span class="hljs-string">SSH</span>
</code></pre>
<p>I'm assuming that you know how to structure YAML configuration files. Equal spaces, indentation, and no tabs. That's how you avoid mistakes in such files.</p>
<p>Let's modify this.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">all:</span>
  <span class="hljs-attr">hosts:</span>
    <span class="hljs-attr">remotemachine01:</span>
      <span class="hljs-attr">ansible_host:</span> <span class="hljs-number">172.31</span><span class="hljs-number">.26</span><span class="hljs-number">.104</span>
      <span class="hljs-attr">ansible_user:</span> <span class="hljs-string">ec2-user</span>
      <span class="hljs-attr">ansible_ssh_private_key_file:</span> <span class="hljs-string">clientkey.pem</span>
    <span class="hljs-attr">remotemachine02:</span>
      <span class="hljs-attr">ansible_host:</span> <span class="hljs-number">172.31</span><span class="hljs-number">.18</span><span class="hljs-number">.151</span>
      <span class="hljs-attr">ansible_user:</span> <span class="hljs-string">ec2-user</span>
      <span class="hljs-attr">ansible_ssh_private_key_file:</span> <span class="hljs-string">clientkey.pem</span>
    <span class="hljs-attr">remotedb01:</span>
      <span class="hljs-attr">ansible_host:</span> <span class="hljs-number">172.31</span><span class="hljs-number">.29</span><span class="hljs-number">.220</span>
      <span class="hljs-attr">ansible_user:</span> <span class="hljs-string">ec2-user</span>
      <span class="hljs-attr">ansible_ssh_private_key_file:</span> <span class="hljs-string">clientkey.pem</span>

  <span class="hljs-attr">children:</span>
    <span class="hljs-attr">rmwebservers:</span>
      <span class="hljs-attr">hosts:</span>
        <span class="hljs-attr">remotemachine01:</span>
        <span class="hljs-attr">remotemachine02:</span>
    <span class="hljs-attr">rmdbservers:</span>
      <span class="hljs-attr">hosts:</span>
        <span class="hljs-attr">remotedb01:</span>
</code></pre>
<p>Now to understand this one needs to know that:</p>
<ol>
<li><p>In Ansible, the "<strong>all</strong>" at the top of your inventory file is a special keyword that represents the top-level group, taking into account all hosts defined in the inventory. It essentially groups together all the hosts listed below it. This allows you to address all hosts in your inventory collectively or apply configurations to all hosts.</p>
</li>
<li><p>In this inventory file, the "<strong>all</strong>" group contains three hosts: <code>remotemachine01</code>, <code>remotemachine02</code>, and <code>remotedb01</code>. It also defines two child groups (<code>rmwebservers and rmdbservers</code>. This structure allows you to organize your hosts into different groups and apply configurations selectively.</p>
</li>
</ol>
<p>We're now ready to execute commands. We can now, perform host-based, as well as, group-based ad-hoc commands. Execute the following commands:</p>
<pre><code class="lang-bash">ansible remotedb01 -m ping -i inventory
ansible rmwebservers -m ping -i inventory
</code></pre>
<p>What did you see? Is it respectively like this? (ignore the host names, mine are different)</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705686725890/8308c9d6-68a4-464d-b3b0-ad6d626716fe.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705686793552/ebc3f3a7-51ab-48f8-be08-17f404ff21c9.png" alt class="image--center mx-auto" /></p>
<p>YAY! We now have a basic understanding of groups in Ansible inventory files.</p>
<p>Regarding the output, there are three sections here:</p>
<ol>
<li><p>The <strong>facts</strong> gathered by Ansible about the target machine it connected to. There's an amazing module Ansible executes first before any other module, whether ad-hoc or through a playbook. We'll get to it soon. Here, it's just the interpreter used for this particular script's execution on the target machine.</p>
</li>
<li><p><strong>Changes</strong> made by Ansible on the target made. In this case, it's false because we're just pinging the target machine but we'll see it becoming true very soon.</p>
</li>
<li><p><strong>Ping and pong</strong>. Modules usually have corresponding responses which we'll see soon but this is just for fun.</p>
</li>
</ol>
<p>These and many more fields in Ansible outputs will be your friends for life. They'll help you with details, debugging, and generating test cases.</p>
<h2 id="heading-what-next">What next?</h2>
<p>You already know it! I guess not. We'll finish the hierarchical structure of this inventory file and apart from that, the next chapter will wholly be dedicated to a lot of ad-hoc commands. Buckle up!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705688238500/5a868197-d18b-4f80-b1c1-e2fd5aac00d0.jpeg" alt class="image--center mx-auto" /></p>
<p><strong>Connect with me on</strong> <a target="_blank" href="https://www.linkedin.com/in/shekhardhendu/">LinkedIn</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Learnings with Ansible: Chapter 2]]></title><description><![CDATA[Hi! We're back with Chapter 2 of riding the high tides of Ansible. Let's begin.
Again, let's begin with another praise for Ansible. I love Ansible's documentation for how easy it is to navigate it. I already am doing it so at this point, you the read...]]></description><link>https://ardhendushekhar.hashnode.dev/learnings-with-ansible-chapter-2</link><guid isPermaLink="true">https://ardhendushekhar.hashnode.dev/learnings-with-ansible-chapter-2</guid><category><![CDATA[ansible]]></category><category><![CDATA[ansible-module]]></category><category><![CDATA[Devops]]></category><category><![CDATA[#Devopscommunity]]></category><dc:creator><![CDATA[Ardhendu Shekhar]]></dc:creator><pubDate>Sun, 14 Jan 2024 19:43:26 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1705261231593/e2de1f9f-8a44-4cd9-af9c-9c996c89c52c.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hi! We're back with Chapter 2 of riding the high tides of Ansible. Let's begin.</p>
<p>Again, let's begin with another praise for Ansible. I love Ansible's documentation for how easy it is to navigate it. I already am doing it so at this point, you the reader don't have to. I got you.</p>
<h2 id="heading-ansible-installation">Ansible Installation</h2>
<p>A little assumption from my side is that you have a machine at your disposal that you could use. We could do with:</p>
<ol>
<li><p>A virtual machine on your system (using Vagrant maybe) or</p>
</li>
<li><p>An EC2 instance preferably (t2.micro would work. Make sure you edit the security group for SSH inbound traffic from your IP)</p>
</li>
</ol>
<p>Just make sure you have compute resources as well. Now, navigate to <a target="_blank" href="https://docs.ansible.com/ansible/latest/installation_guide/installation_distros.html">https://docs.ansible.com/ansible/latest/installation_guide/installation_distros.html</a> and select the favorite OS and distro of your choice. Statistics and my personal bias say that Linux and Ubuntu respectively are the best for this.</p>
<p>You must execute the following commands in the CLI of your choice (mine is Git Bash) to install Ansible on the machine</p>
<pre><code class="lang-bash">$ sudo apt update
$ sudo apt install software-properties-common
$ sudo add-apt-repository --yes --update ppa:ansible/ansible
$ sudo apt install ansible
</code></pre>
<p>and finally, we will validate our installation with a <code>ansible --version</code> command.</p>
<p>Great. We're now done with the installation of Ansible. This machine which now holds your Ansible power will henceforth be referred to as the "Control Machine".</p>
<h2 id="heading-ansible-architecture">Ansible Architecture</h2>
<p>The architecture consists of a <strong>Control Machine</strong>, where we write the code and specify what we want to do and how we want to do it, a set of <strong>Target Machines</strong> we want to automate or "change", a configuration file, and an inventory file.</p>
<p>There are in essence, three important things one needs to know here.</p>
<ol>
<li><p><strong>Ansible loves Python</strong>.</p>
<p> Both Python 2 and Python 3 interpreters are used by Ansible to execute remote and local automation. We have different modules in Ansible that we are going to use and different modules, use different Python interpreters and different Python versions. Some modules make this distinction very clear and we'll get into those soon.</p>
</li>
<li><p><strong>The Target Machine is where the magic happens.</strong></p>
<p> All the code that we are going to run or write will be translated into Python scripts. And those Python scripts will run on the client (target) machine, and not on the control machine. Although the magic (in this case YAML scripts) is written on the control machine, it happens (executes) on the target machine. Hence, we achieve automation.</p>
</li>
<li><p><strong>Understanding Ansible inventory makes or breaks things.</strong></p>
<p> I know we haven't talked about this and that's exactly what we'll do.</p>
</li>
</ol>
<h2 id="heading-ansible-inventory">Ansible Inventory</h2>
<p>Ansible in order to perform automation needs to know where it has to do so. The inventory file defines that along with a few very important things. According to the official Ansible documentation</p>
<blockquote>
<p>The simplest inventory is a single file with a list of hosts and groups. The default location for this file is <code>/etc/ansible/hosts</code>. You can specify a different inventory file at the command line using the <code>-i &lt;path&gt;</code> option or in configuration using <code>inventory</code>.</p>
</blockquote>
<p>Another thing I'd like to emphasize is how essential the usage of environmental variables is in the world of Ansible (or in automation in general). I'd encourage you to explore them while going through the documentation (which you must).</p>
<p>For our exercise, the environment variables we'll use are</p>
<ul>
<li><p><strong>ansible_host</strong></p>
</li>
<li><p><strong>ansible_user</strong></p>
</li>
<li><p><strong>ansible_ssh_private_key_file</strong></p>
</li>
</ul>
<p>Before writing our inventory file, we have to set up a few things. These are:</p>
<ol>
<li><p>We should have an understanding of YAML (Yet Another Markup Language) and of Vim/Vi editor.</p>
</li>
<li><p>We should set up at least four EC2 instances (or Vagrant VMs). Three CentOS (RHEL) and one Ubuntu (Debian).</p>
</li>
<li><p>We must modify a few defaults before attempting to use an Ansible module.</p>
</li>
</ol>
<p>Now, while I leave the first two points up to you, I'd like to get my hands dirty on the third.</p>
<p>Firstly, we have to create a file called clientkey.pem (a private key for OpenSSH from AWS) through Vim and paste the RSA content which can be found in the key you downloaded when you created a keypair while creating EC2 instances into it. This will validate the SSH connection that our control machine will make with our target machines.</p>
<p>Secondly, we'll get into modifying default configurations. We have to generate our own Ansible configuration file while overriding the default ansible.cfg file at /etc/ansible/ansible.cfg using</p>
<p><code>ansible-config init --disabled all &gt; .ansible.cfg</code></p>
<p>This will generate an extensive ansible configuration. Open it through the Vim editor, search the keywords "host_key_checking" using / operator, uncomment, and disable it. This will disable the host key checking prompt and make the connection non-interactive, exactly as we want.</p>
<p>Thirdly, we want to modify permissions to avoid an "UNPROTECTED PRIVATE KEY FILE" using</p>
<pre><code class="lang-bash">chmod 400 clientkey.pem
</code></pre>
<p>A typical inventory file for our exercise in order to broaden our understanding further would look something like this. Make sure you name it inventory. The interpretation of this will extensively be covered in the next chapter.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">all:</span>
  <span class="hljs-attr">hosts:</span>
    <span class="hljs-attr">remotemachine01:</span>
      <span class="hljs-attr">ansible_host:</span> <span class="hljs-number">172.31</span><span class="hljs-number">.18</span><span class="hljs-number">.192</span>
      <span class="hljs-attr">ansible_user:</span> <span class="hljs-string">ec2-user</span>
      <span class="hljs-attr">ansible_ssh_private_key_file:</span> <span class="hljs-string">clientkey.pem</span>
</code></pre>
<p>And for the showdown, we execute our first "ad-hoc" command. I'll leave it up to you to go through the output and we'll pick it from there in the next chapter.</p>
<p>The command uses a test module in Ansible named ping (as the name suggests it pings the target machine and returns a JSON output).</p>
<pre><code class="lang-bash">ansible remotemachine01 -m ping -i inventory
</code></pre>
<h2 id="heading-what-next">What next?</h2>
<p>Next, we'll deep dive into Ansible configuration, followed by an introduction to groups of hosts and our very own playbook.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705260694122/d00efc81-7a6b-46be-9601-92a09d9d215e.jpeg" alt class="image--center mx-auto" /></p>
<p><strong>Connect with me on</strong> <a target="_blank" href="https://www.linkedin.com/in/shekhardhendu/"><strong>My LinkedIn</strong></a><strong>.</strong></p>
]]></content:encoded></item><item><title><![CDATA[Learnings with Ansible: 
Chapter 1 of many]]></title><description><![CDATA[Hi. I'm Ardhendu and I'm learning DevOps.
We begin this with the reason I've taken this tool up. It's because I see it EVERYWHERE. My ever-alive need to stay up to the standard while learning DevOps has brought me to Ansible.
Let's start.
What is Ans...]]></description><link>https://ardhendushekhar.hashnode.dev/ansible-chapter-1</link><guid isPermaLink="true">https://ardhendushekhar.hashnode.dev/ansible-chapter-1</guid><category><![CDATA[ansible]]></category><category><![CDATA[automation]]></category><category><![CDATA[Devops]]></category><category><![CDATA[Python]]></category><category><![CDATA[ansible-playbook]]></category><dc:creator><![CDATA[Ardhendu Shekhar]]></dc:creator><pubDate>Fri, 12 Jan 2024 18:00:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1705081193950/59fdc8c3-e5e3-484a-926b-1e9d3d98b0e4.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hi. I'm Ardhendu and I'm learning DevOps.</p>
<p>We begin this with the reason I've taken this tool up. It's because I see it EVERYWHERE. My ever-alive need to stay up to the standard while learning DevOps has brought me to Ansible.</p>
<p>Let's start.</p>
<h2 id="heading-what-is-ansible">What is Ansible?</h2>
<p>Whenever we speak about DevOps, we think of automation, and rightly so. There have been innumerable attempts to make things as automated as possible. The simplest of those would be Ansible.</p>
<p>Ansible as a tool can be categorized in automation, server management, provisioning, and configuration management and it would pass with flying colors as all of the above. The reason is the ability to adapt through regular integrations with ever-evolving technologies.</p>
<h2 id="heading-what-makes-ansible-different">What makes Ansible different?</h2>
<ol>
<li><p>When overseeing the administration of a network comprising many (say 100) servers via configuration management tools such as Puppet, Chef, or Salt Stack the conventional approach involves installing agents on each of these machines. However, with Ansible, this step is no longer required. Ansible uses established connections specific to specific operating systems; for Linux environments, it employs SSH, while for Windows systems, it uses winRM. This makes it simpler and easy to use.</p>
</li>
<li><p>Another plus point would be its "no residual software" policy which in simple terms is that when we write Ansible code, specifically playbooks, the process involves generating Python scripts. These scripts are then executed on a custom target, making desired changes. There is no residual or left-out software residue on either the target system or the control machine (the machine on which Ansible is running), making Ansible clean and efficient in execution.</p>
</li>
<li><p>And since it's based essentially on Python libraries, we can simply get started with a <code>pip install</code> command, along with other ways of course. This along with YAML being the standard in writing Ansible playbooks (a list of tasks) makes it a very "friendly" tool.</p>
</li>
</ol>
<h2 id="heading-what-next">What next?</h2>
<p>Next, there's action. We'll get into installation, Ansible architecture, inventory and configuration files, and Ansible ad-hoc commands followed by writing our very own Ansible playbook.</p>
<p><strong>Since this is my first post, I'd be grateful if you could share this. It ain't much but it's honest work. Thanks for reading and stay tuned.</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705082314640/819c8adc-f50d-4dff-9fcf-c4e0bfbcd5b6.jpeg" alt class="image--center mx-auto" /></p>
<p><strong>Connect with me on</strong> <a target="_blank" href="https://www.linkedin.com/in/shekhardhendu/"><strong>My LinkedIn</strong></a><strong>.</strong></p>
]]></content:encoded></item></channel></rss>