The Geeky Way - DevOps//thegeekyway.com/2019-08-24T00:58:20+05:30Ansible?2019-08-24T00:58:20+05:302019-08-24T00:58:20+05:30storymode7tag:thegeekyway.com,2019-08-24:/ansible/<div style="text-align:center">
<p><img alt="Ansible Logo" src="//thegeekyway.com/uploads/images/2019/08/ansible_logo.png"></p>
</div>
<p>Hearing about Ansible lately? Everyone's using it! But what's the buzz about, what is ansible actually? And why should you use it? Lot's of questions and lot's of answers. Let's dive!</p>
<!--more-->
<h2>What is it?</h2>
<p>Well Ansible is a tool to automate the setup of an EC2 instance, a vagrant box …</p><div style="text-align:center">
<p><img alt="Ansible Logo" src="//thegeekyway.com/uploads/images/2019/08/ansible_logo.png"></p>
</div>
<p>Hearing about Ansible lately? Everyone's using it! But what's the buzz about, what is ansible actually? And why should you use it? Lot's of questions and lot's of answers. Let's dive!</p>
<!--more-->
<h2>What is it?</h2>
<p>Well Ansible is a tool to automate the setup of an EC2 instance, a vagrant box, and almost anything that you can ssh into.</p>
<h2>What's the usecase?</h2>
<p>Imagine you've to setup an instance and use it as a server using nginx. Simple, right? Just ssh into it, do the nginx conf and leave it running. But wait, you did the setup on say an Ubuntu instance, but for some reasons, you have to change your server OS, to something like a Fedora may be? Or an Amazon linux? Now, you need to repeat all the steps you just did for ubuntu setup to perform the exactly same task. Another usecase is to setup multiple instances automatically, all you need to define is the tasks, roles etc. for Ansible. We'll be getting to it shortly.</p>
<h2>Installing Ansible</h2>
<p><code>sudo apt-get install ansible</code> should do just fine. Or <code>dnf</code> in place of <code>apt-get</code> for RHEL. Interestingly, you don't need to install ansible on the target machine! You just install it on your local machine once. And just exploit it using the tasks you define. This is because Ansible basically just SSH into your remote machine, and executes task if required.</p>
<h2>Getting started</h2>
<p>We'll start with doing everything in a get it done way. And then move to the way of how it should be done. Firstly you define the target(s) to act upon. This is called the inventory. You can name this file anything, inventory, hosts, instances, etc. it's upto you. In this file, type in the IPs of the instances you wish to control in format:</p>
<div class="highlight"><pre><span></span><code><span class="k">[name]</span>
<span class="na">0.0.0.1 ansible_user</span><span class="o">=</span><span class="s">'ubuntu' ansible_ssh_private_key_file='path/to/privateKey/for/server'</span>
<span class="na">0.0.1.2 ansible_user</span><span class="o">=</span><span class="s">'userName_to_login_as' ansible_ssh_private_key_file='path/to/private/key'</span>
</code></pre></div>
<p>You can access these IPs using the *name* you provided. If you want to test this on vagrant, write an inventory file in the format:</p>
<div class="highlight"><pre><span></span><code><span class="k">[vag]</span>
<span class="na">127.0.0.1 ansible_port</span><span class="o">=</span><span class="s">2222 ansible_user='vagrant' ansible_ssh_private_key_file='/path/toVagrantfile/.vagrant/machines/default/virtualbox/private_key'</span>
</code></pre></div>
<p>If you wish, you can follow along by performing the commands on your machine instead of a server too.
Using localhost:</p>
<div class="highlight"><pre><span></span><code><span class="k">[me]</span>
<span class="na">localhost ansible_connection</span><span class="o">=</span><span class="s">local</span>
</code></pre></div>
<p>Now, if you wish to use localhost, just use <code>me</code> in place of <code>vag</code>/<code>groupName</code>.<br>
If the inventory is ready we can begin executing the commands!</p>
<p><strong>Note</strong>: Though most of the commands used in this blog are non destructive and would not change anything in your PC to cause problems. Caution should be excercised when hacking through the different commands on your own. Especially if the target machine hosts important data, or you are performing all the commands on your localhost</p>
<p><strong>Note</strong>: If you get an error/warning related to usage of python2 interpreter, you can create a file <code>ansible.cfg</code> and specify python3 interpreter by writing this in the file:</p>
<div class="highlight"><pre><span></span><code><span class="k">[defaults]</span>
<span class="na">interpreter_python</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">/usr/bin/python3</span>
</code></pre></div>
<h2>Executing some commands</h2>
<p>Ansible can work only when the target machine is ready to ssh, and the credentials provided in the inventory file are correct. Now that ansible knows how to authenticate itself to the machines, it'll have no problems executing any commands.</p>
<p>A little idea about Modules and arguments, and we are ready to go.</p>
<p>Modules are small pieces of python code, that ansible uses to handle resources on the target machine. And some modules require arguments to act upon. Let's see first an example that doesn't require an argument.</p>
<p>Ping module. Since we have already provided the inventory file, we don't need to provide ansible with the IPs of the instances to ping.</p>
<p>We can simply do:</p>
<div class="highlight"><pre><span></span><code>ansible -i inventory_file groupName -m ping
</code></pre></div>
<p>groupName, like we provided <code>vag</code> in the inventory file example above. It's just a collection of IPs or domains along with their options under one name.</p>
<p><code>-m</code>: states that we're going to use a module Whose name in this case is ping</p>
<p>If you've provided inventory file and group name correctly you should get an output like:<br>
<code>default | SUCCESS => { "changed": false, "ping": "pong" }</code><br>
Congratulations, you just executed your first command using ansible.</p>
<p>Now let's try one example which takes an argument. How about a Hello World sample? For this we're going to use <code>shell</code> module.</p>
<div class="highlight"><pre><span></span><code>ansible -i inventory groupName -m "shell" -a "echo Hello World!"
</code></pre></div>
<p>Output comes out to be:<br>
<code>default | SUCCESS | rc=0 >> Hello World!</code><br>
Let's try one last thing, installing a package. We'll be using apt module.</p>
<div class="highlight"><pre><span></span><code>ansible -i inventory groupName -m apt -a "name=nginx state=present update_cache=true"
</code></pre></div>
<p>The argument here is self explanatory. apt module, takes arguments name, state mainly. Name states which package to act upon, and state tells what action is needed to be performed if any. This makes sure idempotence is there. Means, the same action performed repeatedly should not alter the state of the resource. state can be absent, present, latest, etc.</p>
<p>Update_cache is suggested because most of the images used to setup an instance would require you to update repository cache before you install anything.</p>
<p>This command should give you an error<br>
<code>default | FAILED! => { "changed": false, "msg": "Failed to lock apt for exclusive operation" }</code><br>
And that is because the default user doesn't have enough privileges. For privilege escalation, we need to supply another flag. <code>-b</code> .</p>
<div class="highlight"><pre><span></span><code>ansible -i inventory groupName -b -m apt -a "name=nginx state=present update_cache=true"
</code></pre></div>
<p><code>-b</code> or <code>--become</code> tells ansible whether to activate or deactivate privilege escalation. Default for privilege escalation is root, and hence the command will be executed as root. But you can also specify another user, as whom you'd like to execute the command. This can be done using <code>--become-user userName</code> . Note that, if you the target system has requires a password, you need to pass <code>-K</code> flag to ask for become pass.</p>
<p>Now the terminal will take time depending on the internet connection available to the target machine and will generate output like: </p>
<div class="highlight"><pre><span></span><code>default | SUCCESS => {
"cache_update_time": 1526681063,
"cache_updated": true,
"changed": true,
"stderr": "",
"stderr_lines": [],
...
}
</code></pre></div>
<p>In every output the value for</p>
<div class="highlight"><pre><span></span><code>"changed"
</code></pre></div>
<p>variable is the gist of success or failure. This and the color of the output are enough to denote unchanged, changed, failure.</p>
<p>But ansible can do a lot more. This method is easy if you need to run one single module. But this is often not the case. You'd almost always require a collection of modules to setup a target machine. To see how many modules ansible provides head on to <a href="http://docs.ansible.com/ansible/latest/modules/modules_by_category.html">this</a> page. In that case giving arguments to ansible command wont be the best choice. Now enters ansible playbook.</p>
<h2>Ansible playbook</h2>
<p>Playbook is like a collection of ansible commands put together in a single YAML file. We performed 3 tasks all unrelated, but in case of a setup used to install and configure a single package inside the target machine, like setting up nginx, would require more tasks. And it'd be more logical to group all of them in a single playbook. Let's create a simple playbook, to say hello world, and then we'll move to installing nginx using playbook.</p>
<h3>A bit of YAML</h3>
<p>Before typing out your first YAML, let's just get a basic idea of it's syntax. These syntax basics have nothing specific with ansible. These basics will be same in every YAML file, so if you are already familiar with it's syntax, feel free to skip to the playbook part.</p>
<p>A YAML file can optionally begin with <code>---</code> (triple dash) and end with <code>...</code> (triple dot)<br>
<code>#</code> before any line comments it.<br>
A list is represented by lines starting with a <code>-</code> at same indentation level. For example:</p>
<div class="highlight"><pre><span></span><code>---
numbers:
- one
- two
- three
- four
...
</code></pre></div>
<p>And a dictionary is represented like:</p>
<div class="highlight"><pre><span></span><code>---
name_of_dictionary:
key1: value1
key2: value2
...
</code></pre></div>
<p>Now there can be combinations of keys, dictionaries. Let's do one example of list of dictionary that is used in playbooks.</p>
<div class="highlight"><pre><span></span><code>---
- dictionary1:
key1: value1
key2: value2
key3:
- one
- two
- dictionary2:
key4: value4
key5: value5
key6:
- foo
- bar
...
</code></pre></div>
<p>Here we have a list of dictionaries, dictionary1 and dictionary2. In these dictionaries, some of the values are themselves a list. Like key3 in dictionary1 and key6 in dictionary2.</p>
<p>If you're a pythonista, there's another format that'd be more familiar to you:</p>
<div class="highlight"><pre><span></span><code>---
dictionary1: {key1: value1, key2: value2}
list1: ['one', 'two', 'three']
...
</code></pre></div>
<p>There's whole lot of other details that you might like to have a glance. They are available with the <a href="http://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html">ansible documentation</a>.</p>
<h3>Back to the playbooks</h3>
<p>Let's create the playbook 'nginx.yml' now, and then we'll see that in detail:</p>
<div class="highlight"><pre><span></span><code>---
- hosts: vag
become: yes
tasks:
- name: Install Nginx
apt:
name: nginx
state: present
update_cache: true
</code></pre></div>
<p>This is just the playbook version of the bash command we performed earlier using ansible to install nginx.</p>
<p>First let's see what each key means and then we'll run this playbook.</p>
<p>We can perform a lot of tasks for different hosts defined in the inventory, inside a single playbook. We can have a list of dictionaries, and depending upon the hosts specified, the tasks will be executed for that specific host. If you want to perform the tasks for all the hosts defined in the inventory file, you can also give the value <code>all</code> for hosts key. Here we are considering the host <code>vag</code> we defined previously in the inventory.</p>
<p><code>become</code> is required to use apt. Otherwise, we'd come across an error (as we did while executing directly using bash). Note that, <code>yes</code> is just one of the ways to provide a boolean value. You can specify <code>True</code>, <code>TRUE</code>, <code>yes</code> and so on...</p>
<p><code>tasks</code> is again a list of dictionaries defining the tasks we want to perform against the target machine.<br>
Inside tasks, the first key is <code>name</code> , we can name it anything, this will be shown when we run the playbook, so keep the name quite descriptive.<br>
Secondly we specify the module to use for this first task. Here <code>apt</code> is used.<br>
Now we are supplying arguments to <code>apt</code> using YAML syntax, values are same as we did while executing from terminal. The arguments are just key value pair, where the module name acts as dictionary name.</p>
<p>You can also specify <code>latest</code> as a value to <code>state</code> key. This will update the package too, if an update comes. Whereas <code>present</code> would just ensure that the package is installed on the target machine.</p>
<p>Run the playbook using:</p>
<div class="highlight"><pre><span></span><code>ansible-playbook nginx.yml -i inventory
</code></pre></div>
<p>This is same as the single line command we performed earlier, just that we have a named task here. Output here will be similar to this:
(If you are trying this on your local machine, you might need to pass a : <code>--ask-become-pass</code> or <code>-K</code> as a flag to <code>ansible-playbook</code> command.)</p>
<pre>PLAY [me] **********...
TASK [Gathering Facts] **********...
<font color="#4E9A06">ok: [vag]</font>
TASK [Install Nginx] **********...
<font color="#C4A000">changed: [vag]</font>
PLAY RECAP **********...
<font color="#C4A000">vag</font> : <font color="#4E9A06">ok=2 </font> <font color="#C4A000">changed=1 </font> unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
</pre>
<p>Now you got a playbook running, you can add more tasks, find more modules and hack through.
Bigger projects even have a playbook spread over folders, where, tasks, defaults, vars, etc. all have a separate folder and a main.yml in each of them. </p>
<p>Hope this will get you started on ansible.</p>
<p>Thanks a lot for reading!</p>Blue-Green Deployment2018-02-15T17:11:00+05:302018-02-15T17:11:00+05:30GeekyShacklebolttag:thegeekyway.com,2018-02-15:/blue-green-deployment/<p>A few glimpse of past reminds us that application deployment on clouds was really a cumbersome task. Not only because the rollback was a pretty much complex operation to carry out, but also, because of huge outage or downtime, which inevitably used to disappoint users. But as we can see …</p><p>A few glimpse of past reminds us that application deployment on clouds was really a cumbersome task. Not only because the rollback was a pretty much complex operation to carry out, but also, because of huge outage or downtime, which inevitably used to disappoint users. But as we can see nowadays, there are some simpler and more efficient ways to perform the same. We are going to discuss one such technique, that is called "Blue-Green Deployment".<!--more--></p>
<div style="text-align:center">
<p><img alt="" src="//thegeekyway.com/uploads/images/2018/02/Blue-green-deployment.png" title="Blue-Green Deployment"></p>
</div>
<p>Before we jump on to understand Blue-Green Deployment, let's first discuss some relevant terms in brief.</p>
<h3>Deployment:</h3>
<p>This term is often get confused with the word "release" due to their versatile usage. Thus, their definition may vary with the context of talk. But here, "release" is just a version number of an application, that always doesn't need to deploy. However, "deployment" is the process of installation and configuration of an application on a targeted hardware.</p>
<h3>Downtime or Outage:</h3>
<p>This is the period of time in which the system fails or it remains unavailable to reply to client's requests. This is either a manifestation of the system crash or during routine maintenance.</p>
<h3>Load Balancer:</h3>
<p>This can be a hardware device or a software component. It's main feature is to spread the traffic over the server pool, such that, no server is overly burdened while others remain idle. This can also be used to divert network traffic from one server pool to another. We'll see its usage in blue-green deployment. <a href="http://docs.aws.amazon.com/elasticloadbalancing/latest/userguide/what-is-load-balancing.html">Elastic load balancing</a> is also available to handle multiple elastic clouds.</p>
<p>Let's understand about Blue-Green Deployment technique now.</p>
<h2>Blue-Green Deployment:</h2>
<p>This is also known as <strong>Red-Black Deployment</strong>. This is a technique used in application deployment which reduces the risk of downtime and also facilitates the rollback (moving to the previous state). Let us see how it exactly happens.</p>
<p><strong>Workflow of blue-green deployment using a load balancer:</strong><br>
For this technique, we need 2 identically configured hardware components or server pools. Out of which:-<br>
- one is termed as <strong>"blue"</strong> that is going to be an <strong>active</strong> environment<br>
- another one is termed as <strong>"green"</strong> that would be an <strong>idle</strong> environment.</p>
<p>Initially, some applications <strong>(e.i app1 ver1, app2 ver1)</strong> are running in our blue environment. As shown in the picture.</p>
<div style="text-align:center">
<p><img alt="" src="//thegeekyway.com/uploads/images/2018/02/Active-blue-env.png" title="Active blue environment"></p>
</div>
<p>Suppose, now we come up with different versions of applications <strong>(i.e. app1 ver2, app2 ver2)</strong>. We want them to deploy and then test these applications. If everything goes right, we'll use these versions in future, but if not, then we would go for the "rollback".</p>
<p>Let's accomplish this using blue-green deployment:</p>
<p>1. Deploy new versions of application in idle environment<br>
2. Here a testing team may test the working of these new versions.<br>
3. Gradually, using load balancer we start diverting the traffic to this green environment. As shown in the picture. With this live testing is also possible.</p>
<div style="text-align:center">
<p><img alt="" src="//thegeekyway.com/uploads/images/2018/02/Active-blue-green-env.png" title="Diverting traffic from blue to green environment"></p>
</div>
<p>4. If now, these versions fail or crash due to any possible reason. We can quickly roll back to the previous versions in the blue environment using the load balancer.<br>
5. If new versions are found to be perfectly interacting with the user's traffic, then this <strong>"green"</strong> environment is kept to be <strong>active</strong> and <strong>"blue"</strong> becomes <strong>idle</strong>.</p>
<div style="text-align:center">
<p><img alt="" src="//thegeekyway.com/uploads/images/2018/02/Active-green-env.png" title="Active green environment"></p>
</div>
<p>After successful blue-green deployment, the idle environment is either used to deploy the next version of the application or is simply destroyed.</p>
<p><em><u></em><em>Some points to ponder:</em><em></u></em></p>
<ul>
<li>Blue-green deployment is widely used nowadays to get minimum or zero downtime. It is used by different cloud service providers like AWS (Amazon Web Services), DigitalOcean, etc.</li>
<li>Using load balancer is not the only way to implement blue-green environments. Different methods are also available like elastic IPs, DNS routing, etc.</li>
</ul>
<h5>Advantages of blue-green deployment:</h5>
<p>1. Fast rollback<br>
2. Reduced downtime<br>
3. Allow testing in a live production environment without affecting 100% user base.</p>
<h5>Disadvantages of blue-green deployment:</h5>
<p>1. Database dependent:<br>
Implementing blue-green deployment become complex with the database, especially if, the database schema is changed in the new version.<br>
2. Increasingly more difficult at scale</p>
<p>If you've any questions about Blue Green Deployment, please let us know in the comments section below.</p>