Allan DenotJekyll2019-04-26T21:32:23+10:00https://allandenot.com/Allan Denothttps://allandenot.com/adenot at gmailhttps://allandenot.com/devops/2015/12/24/autoscaling-wordpress-with-ansible-and-cloudformation2015-12-24T00:00:00+11:00T00:00:00-00:00Allan Denothttps://allandenot.comadenot at gmail
<h2 id="the-goal">The Goal</h2>
<ul>
<li>A WordPress site running in EC2 hosts and an RDS database.</li>
<li>EC2 hosts inside an autoscaling group</li>
<li>Easily deploy configuration changes</li>
</ul>
<h2 id="how-it-works">How it works</h2>
<p>User runs Ansible playbook:</p>
<p><img src="/images/blog-ansible-autoscaling-wordpress.png" alt="blog-ansible-autoscaling-wordpress.png" /></p>
<p>Notes:</p>
<ul>
<li>Baking server exists as a template for the AMI that will be used in CloudFormation.</li>
<li>Baking server is an Ubuntu with Ansible and local playbooks are copied into it.</li>
<li>We choose to use baked AMIs to speedup the bootup process when autoscaling is creating new instances. Upon boot, these instances run their local Ansible playbooks and the webserver is configured.</li>
</ul>
<h2 id="how-can-i-use-it">How can I use it</h2>
<p>Fork my repository: <a href="https://github.com/adenot/blog-ansible-autoscaling-wordpress">https://github.com/adenot/blog-ansible-autoscaling-wordpress</a></p>
<p>Edit file:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>group_vars/all
</code></pre></div></div>
<p>Set variables from your EC2 account.</p>
<p>Running:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ansible-playbook -vv stack-wordpress.yml
</code></pre></div></div>
<h3 id="what-is-happening">What is happening?</h3>
<p>First time it runs:</p>
<ul>
<li>a baking server is created</li>
<li>local playbooks are copied into baking server (from local_wordpress/ansible)</li>
<li>an AMI is created from the baking server</li>
<li>a CloudFormation stack is created</li>
</ul>
<p>Second time it runs:</p>
<ul>
<li>local playbooks are copied into baking server (from local_wordpress/ansible)</li>
<li>an AMI is created from the baking server</li>
<li>CloudFormation stack is updated with new AMI</li>
<li>Autoscaling group replaces EC2 instances with new ones using new AMI, one by one</li>
</ul>
<p><a href="https://allandenot.com/devops/2015/12/24/autoscaling-wordpress-with-ansible-and-cloudformation.html">Autoscaling Wordpress with Ansible and CloudFormation</a> was originally published by Allan Denot at <a href="https://allandenot.com">Allan Denot</a> on December 24, 2015.</p>https://allandenot.com/devops/2015/11/15/what-s-new-in-ansible-2-02015-11-15T00:00:00+11:00T00:00:00-00:00Allan Denothttps://allandenot.comadenot at gmail
<p align="center"><iframe src="//www.slideshare.net/slideshow/embed_code/key/1TxMP1LZuIR26D" width="595" height="485" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen=""> </iframe> <div style="margin-bottom:5px"> <strong> <a href="//www.slideshare.net/allandenot/whats-new-in-ansible-20" title="What's new in Ansible 2.0" target="_blank">What's new in Ansible 2.0</a> </strong> from <strong><a href="//www.slideshare.net/allandenot" target="_blank">Allan Denot</a></strong> </div></iframe></p>
<p><a href="https://allandenot.com/devops/2015/11/15/what-s-new-in-ansible-2-0.html">What's new in Ansible 2.0 (slides)</a> was originally published by Allan Denot at <a href="https://allandenot.com">Allan Denot</a> on November 15, 2015.</p>https://allandenot.com/devops/2015/05/11/faux-service-discovery-with-ansible-and-aws2015-05-11T00:00:00+10:00T00:00:00-00:00Allan Denothttps://allandenot.comadenot at gmail
<p>In a dynamic environment, servers are created and destroyed all the time. When a new server comes to life, depending on its purpose, you might need to update configuration files from other servers to tell how to access it.
A simple example would be updating your load balancer configuration by adding a new webserver or removing a webserver that was destroyed.</p>
<p>This article will demonstrate how to achieve this with ansible and AWS - using dynamic inventory. Updating a haproxy load balancer with information of webservers (EC2 hosts).</p>
<h2 id="setup-dynamic-inventory">Setup Dynamic Inventory</h2>
<p>The setup will require a dynamic inventory to retrieve information about EC2 hosts.</p>
<p>If you haven’t setup already, take your time and check <a href="http://docs.ansible.com/intro_dynamic_inventory.html#example-aws-ec2-external-inventory-script">Ansible documentation on this subject</a>. Also check <a href="http://allandenot.com/devops/2015/01/16/ansible-with-multiple-inventory-files.html">my post</a> where I describe how to use static and dynamic inventories together.</p>
<p>To test you can run ./ec2.py and should see a json with all your EC2 infrastructure there.</p>
<h2 id="identifying-instances">Identifying Instances</h2>
<p>To identify which EC2 hosts are going to be automatically added to haproxy, let’s use EC2 tagging.
Add a tag to your webservers called: Type = webserver</p>
<p><img src="/images/ansiblediscovery-tag.png" alt="ansiblediscovery-tag.png" /></p>
<p>Ansible EC2 dynamic inventory (ec2.py) automatically creates groups for each EC2 tag. So in the example above, your servers will be available in a group called <em>tag_Type_webserver</em>.</p>
<h2 id="haproxy-configuration">HAproxy configuration</h2>
<p>Now we need a role which will deploy /etc/haproxy/haproxy.cfg</p>
<p>Role is composed by 2 files:</p>
<p><strong>roles/haproxy/tasks/main.yml:</strong></p>
<figure class="highlight"><pre><code class="language-yaml" data-lang="yaml"><span class="nn">---</span>
<span class="pi">-</span> <span class="na">template</span><span class="pi">:</span> <span class="s">src=haproxy.cfg.j2 dest=/etc/haproxy/haproxy.cfg</span></code></pre></figure>
<p><strong>roles/haproxy/templates/haproxy.cfg.j2:</strong></p>
<figure class="highlight"><pre><code class="language-yaml" data-lang="yaml"><span class="s">global</span>
<span class="s">log 127.0.0.1 local0 notice</span>
<span class="s">maxconn 2000</span>
<span class="s">user haproxy</span>
<span class="s">group haproxy</span>
<span class="s">defaults</span>
<span class="s">log global</span>
<span class="s">mode http</span>
<span class="s">option httplog</span>
<span class="s">option dontlognull</span>
<span class="s">retries 3</span>
<span class="s">option redispatch</span>
<span class="s">timeout connect 5000</span>
<span class="s">timeout client 10000</span>
<span class="s">timeout server 10000</span>
<span class="s">listen appname 0.0.0.0:80</span>
<span class="s">mode http</span>
<span class="s">balance roundrobin</span>
<span class="s">option httpclose</span>
<span class="s">option forwardfor</span>
<span class="s">{% for item in groups['tag_Type_webserver'] %}</span>
<span class="s">server {{hostvars[item].ec2_tag_Name}} {{hostvars[item].ec2_ip_address}}:80 check</span>
<span class="s">{% endfor %}</span></code></pre></figure>
<p>Note the section with {% for item in groups[‘tag_Type_webserver’] %} that will loop through the group of servers with Type=webserver EC2 tag before and write the configuration file with each server found as a entry at haproxy.cfg.</p>
<h2 id="wrapping-up">Wrapping Up</h2>
<p>Now you need a playbook to run the <em>haproxy</em> role, a simple example would be:</p>
<figure class="highlight"><pre><code class="language-yaml" data-lang="yaml"><span class="nn">---</span>
<span class="pi">-</span> <span class="na">hosts</span><span class="pi">:</span> <span class="s">tag_Type_loadbalancer</span>
<span class="na">roles</span><span class="pi">:</span>
<span class="pi">-</span> <span class="s">haproxy</span></code></pre></figure>
<p>tag_Type_loadbalance will apply this playbook on EC2 hosts with the tag Type = loadbalancer, making it easier than having to maintain an inventory file with fixed IP addresses of your servers on it.</p>
<p><a href="https://allandenot.com/devops/2015/05/11/faux-service-discovery-with-ansible-and-aws.html">Faux Service Discovery with Ansible and AWS</a> was originally published by Allan Denot at <a href="https://allandenot.com">Allan Denot</a> on May 11, 2015.</p>https://allandenot.com/startups/2015/04/21/startup-update2015-04-21T00:00:00+10:002015-04-21T00:00:00+10:00Allan Denothttps://allandenot.comadenot at gmail
<p>My friends and family always ask me “How’s your startup?” and my answer has been the same over the past few weeks: “Still building the product”. Since this answer is boring, I will try to describe in a more interesting way here.</p>
<h2 id="21042015">21/04/2015</h2>
<p>As the first update, it is a bit long to give some background. The idea is to record the moment so I can check how crazy I was in the past.</p>
<p>Quit my job for almost 2 weeks now, and since the start of this year I’ve been switching from working full-time, part-time and taking unpaid leave, just to work on this product.</p>
<p>My <a href="http://www.spikenode.com">product</a> is a hard one to design, it’s something different from what’s in the market so every decision I have to make is completely based on my experiences and biases, which are prone to mistakes.</p>
<p>Problems that bug me:</p>
<ul>
<li>Not sure if choosing nodejs/mongo was the best choice. It did take me out of my confort zone (python, php, laravel, mysql, pgsql) and has been painful sometimes, but so far I haven’t encounter anything I couldn’t do, so the light is still green.</li>
<li>Interface design/UI - I’m not a designer but I can do things that doesn’t look too bad. The problem is that it takes me too much time to iterate over the design until I reach something I like. I wish I could just get it right at the first attempt.</li>
<li>What to cut? - As a lean startup, the biggest challenge is to cut features otherwise it will never launch.</li>
</ul>
<p>Things I’m happy with:</p>
<ul>
<li>The product is simple, hopefully it won’t need much time for our users to learn</li>
<li>The product is slowly looking better. I think it’s important that people enjoy using it so UI is a bit priority for me.</li>
<li>My wife’s support. Yes, that’s very important!</li>
</ul>
<h3 id="funding">Funding</h3>
<p>I did not get funded to build this product. It’s completely bootstrapped. My strategy was to invest my time to build the company and use savings to pay for my cost of living. This gives me a limited timeframe to “experiment”, but there are some routes I can take when the money start to run out.</p>
<p><a href="https://allandenot.com/startups/2015/04/21/startup-update.html">Startup Update</a> was originally published by Allan Denot at <a href="https://allandenot.com">Allan Denot</a> on April 21, 2015.</p>https://allandenot.com/devops/2015/01/31/provisioning-ec2-hosts-with-ansible2015-01-31T00:00:00+11:00T00:00:00-00:00Allan Denothttps://allandenot.comadenot at gmail
<p>Looking to build EC2 hosts with more consistency? Using Ansible you can easily provision EC2 hosts and put some logic on it to adjust EC2 parameters based on the type of host you are building.</p>
<p>The easiest way to start is to create a playbook calling the <em>ec2</em> module with the parameters you want to pass to AWS to create your host. In this post I will show a little more scalable way to do this, where the parameters are variables and you can easily have multiple types of hosts sharing the same playbook and role.</p>
<p>The solution is organized in 3 parts:</p>
<ol>
<li>A generic Ansible role that uses <em>ec2</em> module to provision</li>
<li>Yaml files with variables that will be used as parameters for each type of EC2 host</li>
<li>Playbook that combines the variables file with the role</li>
</ol>
<p>All code is in a GitHub repository: <a href="https://github.com/adenot/blog-ansible-provision-ec2">https://github.com/adenot/blog-ansible-provision-ec2</a></p>
<h2 id="setup-environment">Setup Environment</h2>
<p>Ansible’s EC2 module uses python-boto library to call AWS API, and boto needs AWS credentials in order to function.</p>
<p>There are many ways to set your AWS credentials. One of them is to create a file under your user home folder:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>touch ~/.boto
</code></pre></div></div>
<p>Then edit the file and add the following:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[Credentials]
aws_access_key_id = REDACTED
aws_secret_access_key = REDACTED
</code></pre></div></div>
<p>For more information, <a href="http://boto.readthedocs.org/en/latest/boto_config_tut.html">check Boto documentation</a>.
To learn how to create AWS credentials, <a href="http://docs.aws.amazon.com/IAM/latest/UserGuide/ManagingCredentials.html#Using_CreateAccessKey">check this documentation</a>.</p>
<h2 id="ansible-role">Ansible Role</h2>
<p>Create a folder for the role:
mkdir -p roles/provision-ec2/tasks</p>
<p>Name the file below as <em>main.yml</em> and add to the folder <em>roles/provision-ec2/tasks/main.yml</em></p>
<figure class="highlight"><pre><code class="language-yaml" data-lang="yaml"><span class="nn">---</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Provision EC2 Box</span>
<span class="na">local_action</span><span class="pi">:</span>
<span class="na">module</span><span class="pi">:</span> <span class="s">ec2</span>
<span class="na">key_name</span><span class="pi">:</span> <span class="s2">"</span><span class="s">{{</span><span class="nv"> </span><span class="s">ec2_keypair</span><span class="nv"> </span><span class="s">}}"</span>
<span class="na">group_id</span><span class="pi">:</span> <span class="s2">"</span><span class="s">{{</span><span class="nv"> </span><span class="s">ec2_security_group</span><span class="nv"> </span><span class="s">}}"</span>
<span class="na">instance_type</span><span class="pi">:</span> <span class="s2">"</span><span class="s">{{</span><span class="nv"> </span><span class="s">ec2_instance_type</span><span class="nv"> </span><span class="s">}}"</span>
<span class="na">image</span><span class="pi">:</span> <span class="s2">"</span><span class="s">{{</span><span class="nv"> </span><span class="s">ec2_image</span><span class="nv"> </span><span class="s">}}"</span>
<span class="na">vpc_subnet_id</span><span class="pi">:</span> <span class="s2">"</span><span class="s">{{</span><span class="nv"> </span><span class="s">ec2_subnet_ids|random</span><span class="nv"> </span><span class="s">}}"</span>
<span class="na">region</span><span class="pi">:</span> <span class="s2">"</span><span class="s">{{</span><span class="nv"> </span><span class="s">ec2_region</span><span class="nv"> </span><span class="s">}}"</span>
<span class="na">instance_tags</span><span class="pi">:</span> <span class="s1">'</span><span class="s">{"Name":"{{ec2_tag_Name}}","Type":"{{ec2_tag_Type}}","Environment":"{{ec2_tag_Environment}}"}'</span>
<span class="na">assign_public_ip</span><span class="pi">:</span> <span class="s">yes</span>
<span class="na">wait</span><span class="pi">:</span> <span class="no">true</span>
<span class="na">count</span><span class="pi">:</span> <span class="s">1</span>
<span class="na">volumes</span><span class="pi">:</span>
<span class="pi">-</span> <span class="na">device_name</span><span class="pi">:</span> <span class="s">/dev/sda1</span>
<span class="na">device_type</span><span class="pi">:</span> <span class="s">gp2</span>
<span class="na">volume_size</span><span class="pi">:</span> <span class="s2">"</span><span class="s">{{</span><span class="nv"> </span><span class="s">ec2_volume_size</span><span class="nv"> </span><span class="s">}}"</span>
<span class="na">delete_on_termination</span><span class="pi">:</span> <span class="no">true</span>
<span class="na">register</span><span class="pi">:</span> <span class="s">ec2</span>
<span class="pi">-</span> <span class="na">debug</span><span class="pi">:</span> <span class="s">var=item</span>
<span class="na">with_items</span><span class="pi">:</span> <span class="s">ec2.instances</span>
<span class="pi">-</span> <span class="na">add_host</span><span class="pi">:</span> <span class="s">name={{ item.public_ip }} ></span>
<span class="s">groups=tag_Type_{{ec2_tag_Type}},tag_Environment_{{ec2_tag_Environment}}</span>
<span class="s">ec2_region={{ec2_region}}</span>
<span class="s">ec2_tag_Name={{ec2_tag_Name}}</span>
<span class="s">ec2_tag_Type={{ec2_tag_Type}}</span>
<span class="s">ec2_tag_Environment={{ec2_tag_Environment}}</span>
<span class="s">ec2_ip_address={{item.public_ip}}</span>
<span class="na">with_items</span><span class="pi">:</span> <span class="s">ec2.instances</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Wait for the instances to boot by checking the ssh port</span>
<span class="na">wait_for</span><span class="pi">:</span> <span class="s">host={{item.public_ip}} port=22 delay=60 timeout=320 state=started</span>
<span class="na">with_items</span><span class="pi">:</span> <span class="s">ec2.instances</span></code></pre></figure>
<h2 id="variables-files">Variables Files</h2>
<p>These are YAML files that will be included by the playbook before calling the role above. It needs to fill all variables used in the <em>provision-ec2</em> role otherwise it will fail.</p>
<p>Create a folder for the variables:
mkdir ec2-vars</p>
<p>In this example we will have a webservers.yml file to simulate provisioning a webserver host in AWS.</p>
<p>ec2-vars/webservers.yml:</p>
<figure class="highlight"><pre><code class="language-yaml" data-lang="yaml"><span class="na">ec2_keypair</span><span class="pi">:</span> <span class="s2">"</span><span class="s">REDACTED"</span>
<span class="na">ec2_security_group</span><span class="pi">:</span> <span class="s2">"</span><span class="s">REDACTED"</span>
<span class="na">ec2_instance_type</span><span class="pi">:</span> <span class="s2">"</span><span class="s">m3.medium"</span>
<span class="na">ec2_image</span><span class="pi">:</span> <span class="s2">"</span><span class="s">ami-9eaa1cf6"</span>
<span class="na">ec2_subnet_ids</span><span class="pi">:</span> <span class="pi">[</span><span class="s1">'</span><span class="s">subnet-REDACTED'</span><span class="pi">,</span><span class="s1">'</span><span class="s">subnet-REDACTED'</span><span class="pi">,</span><span class="s1">'</span><span class="s">subnet-REDACTED'</span><span class="pi">]</span>
<span class="na">ec2_region</span><span class="pi">:</span> <span class="s2">"</span><span class="s">us-east-1"</span>
<span class="na">ec2_tag_Name</span><span class="pi">:</span> <span class="s2">"</span><span class="s">Webserver"</span>
<span class="na">ec2_tag_Type</span><span class="pi">:</span> <span class="s2">"</span><span class="s">webserver"</span>
<span class="na">ec2_tag_Environment</span><span class="pi">:</span> <span class="s2">"</span><span class="s">production"</span>
<span class="na">ec2_volume_size</span><span class="pi">:</span> <span class="s">16</span></code></pre></figure>
<p>Change the <strong>REDACTED</strong> values above to your AWS account ones. You can easily find by inspecting a EC2 host (using AWS console) that you want to automate it’s provisioning.</p>
<p>You can have multiple variable files, one for each type of EC2 host.</p>
<h2 id="playbook">Playbook</h2>
<p>Create a playbook inside ansible playbooks root folder called <em>provision-ec2.yml</em>, with the contents:</p>
<figure class="highlight"><pre><code class="language-yaml" data-lang="yaml"><span class="nn">---</span>
<span class="pi">-</span> <span class="na">hosts</span><span class="pi">:</span> <span class="s">localhost</span>
<span class="na">connection</span><span class="pi">:</span> <span class="s">local</span>
<span class="na">gather_facts</span><span class="pi">:</span> <span class="no">false</span>
<span class="na">user</span><span class="pi">:</span> <span class="s">root</span>
<span class="na">pre_tasks</span><span class="pi">:</span>
<span class="pi">-</span> <span class="na">include_vars</span><span class="pi">:</span> <span class="s">ec2_vars/{{type}}.yml</span>
<span class="na">roles</span><span class="pi">:</span>
<span class="pi">-</span> <span class="s">provision-ec2</span> </code></pre></figure>
<p>Notice that the <em>type</em> variable above is not defined. Depending on the value of the parameter, Ansible will include different a variables file, thus populating the parameters used in the <em>provision-ec2</em> role.</p>
<p>The type will be defined at run time.</p>
<h2 id="running">Running</h2>
<p>Call <em>ansible-playbook</em> passing the <em>type</em> parameter as an argument:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ansible-playbook -vv -i localhost, -e "type=webservers" provision-ec2.yml
</code></pre></div></div>
<p>If your variables are correct, you should see a new host at your AWS console.</p>
<h2 id="github">GitHub</h2>
<p>All code is available at:</p>
<p><a href="https://github.com/adenot/blog-ansible-provision-ec2">https://github.com/adenot/blog-ansible-provision-ec2</a></p>
<p><a href="https://allandenot.com/devops/2015/01/31/provisioning-ec2-hosts-with-ansible.html">Provisioning EC2 Hosts with Ansible</a> was originally published by Allan Denot at <a href="https://allandenot.com">Allan Denot</a> on January 31, 2015.</p>https://allandenot.com/devops/2015/01/16/ansible-with-multiple-inventory-files2015-01-16T00:00:00+11:002015-01-16T00:00:00-00:00Allan Denothttps://allandenot.comadenot at gmail
<p>The power of Ansible always surprises me. In this post I will be sharing the way you can use multiple inventory files when running your playbooks and how to organize them.</p>
<p><strong>TL;DR: Inventory can be a folder. Create a folder, add as many inventory files inside this folder and instruct Ansible to use this folder as the inventory (with -i folder_name or in your ansible.cfg file). All inventory files inside the folder will be merged into one (including scripts like ec2.py).</strong></p>
<h2 id="inventory-as-a-folder">Inventory as a folder</h2>
<p>Inside your playbooks folder, create a folder called <em>inventory</em>.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkdir inventory
</code></pre></div></div>
<p>Now move your current inventory file (often called <em>hosts</em>) into this folder</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mv hosts inventory/
</code></pre></div></div>
<p>To tell ansible to use the new inventory, there are 2 options:</p>
<h4 id="using-ansiblecfg">Using ansible.cfg</h4>
<p>Create a file ansible.cfg within the same folder as your playbooks and add the lines:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[defaults]
hostfile = inventory
</code></pre></div></div>
<h4 id="command-line-argument">Command line argument</h4>
<p>Next time you run your playbook, simply add <em>-i inventory</em>:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ansible-playbook -i inventory my_playbook.yml
</code></pre></div></div>
<p>And that’s it to start.
Now the fun part.</p>
<h2 id="dynamic-and-static-inventories-together">Dynamic and static inventories together</h2>
<p>Here’s the trick, add both your static and dynamic inventories to the folder and you can run playbooks targeting both as same time.</p>
<h4 id="example-group-ec2-hosts-by-country">Example: Group EC2 hosts by country</h4>
<p>EC2 hosts from both us-east-1 and us-west-1 need to belong to a <strong>USA</strong> group, and both eu-west-1 and eu-central-1 to belong to <strong>Europe</strong> group.</p>
<p>Add your <em>ec2.py</em> to the inventory folder and make sure it’s executable.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cp /usr/local/lib/python2.7/dist-packages/ansible/module_utils/ec2.py inventory/
chmod +x inventory/ec2.py
</code></pre></div></div>
<p><em><a href="http://docs.ansible.com/intro_dynamic_inventory.html#example-aws-ec2-external-inventory-script">Check ansible documentation for help to setup ec2.py</a></em></p>
<p>Create new file <em>countries</em> and add to inventory folder.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>touch inventory/countries
</code></pre></div></div>
<p><em>countries</em> file contents:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code># Declaring country groups
[USA]
[Europe]
# Attaching EC2 groups as children
[USA:children]
us-east-1
us-west-1
[Europe:children]
eu-west-1
eu-central-1
</code></pre></div></div>
<p>Now when you run:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ansible-playbook -i inventory --limit "Europe" my_playbook.yml
</code></pre></div></div>
<p>Will run <em>my_playbook.yml</em> only to your european servers.</p>
<p><a href="https://allandenot.com/devops/2015/01/16/ansible-with-multiple-inventory-files.html">Ansible with multiple inventory files</a> was originally published by Allan Denot at <a href="https://allandenot.com">Allan Denot</a> on January 16, 2015.</p>https://allandenot.com/development/2015/01/11/blogging-like-a-dev-jekyll-github-prose-io2015-01-11T00:00:00+11:002015-01-11T00:00:00-00:00Allan Denothttps://allandenot.comadenot at gmail
<p>You want a blog that is fully customizable and is sick of WordPress mess and insecurity? One solution is to use Jekyll to build a blog where all posts are in markdown format, is hosted in github and I can edit using a browser with prose.io.</p>
<p>Summary of benefits:</p>
<ul>
<li>No database, only Markdown files</li>
<li>Hosted for free by GitHub Pages</li>
<li>Version controlled</li>
<li>In browser rich editor with Prose.io</li>
<li>Highly customizable and themeable</li>
<li>Cool factor</li>
</ul>
<h2 id="step-1-forking-from-another-blog">Step 1: Forking from another blog</h2>
<p>The easiest way to do is to fork a jekyll theme in your GitHub account. Best ones I could find are:</p>
<ul>
<li><a href="https://github.com/hmfaysal/Notepad">Notepad</a> - used by this very blog</li>
<li><a href="https://github.com/IronSummitMedia/startbootstrap-clean-blog-jekyll">Clean Blog theme by Start Bootstrap</a></li>
<li>More themes in <a href="http://jekyllthemes.org/">http://jekyllthemes.org/</a></li>
</ul>
<hr />
<p><em>This tutorial will install and customize the Notepad theme, but instructions should be similar for other themes</em></p>
<hr />
<p>After forking, click on Settings:</p>
<p><img src="/images/howtoblog-githubsettings.png" alt="howtoblog-githubsettings.png" /></p>
<ul>
<li>Rename your forked repository to <em>yourusername</em>.github.io, that’s the way to tell GitHub Pages to build your repository into a website.</li>
<li>Set the Default branch to <strong>master</strong>, unless described otherwise by theme developer.</li>
</ul>
<p><strong>Some theme repositories use gh-pages as the default branch and others use master. You must check in the theme docs which one is correct. For Notepad is master.</strong></p>
<h2 id="step-2-preparing-your-environment">Step 2: Preparing your environment</h2>
<p>Requirements are: Ruby, Gem and GIT.
From there you can install jekyll by running:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>gem install jekyll
</code></pre></div></div>
<p>Optionally you can create a blank site, by following <a href="http://jekyllrb.com/docs/quickstart/">jekyll documentation</a>, but that’s not the method we will describe in this post.</p>
<h2 id="step-3-cloning-your-repository">Step 3: Cloning your repository</h2>
<p>If you forked correctly, you will have a repository on github.com/<em>yourusername</em>/<em>yourusername</em>.github.io</p>
<p><em>It’s not necessary to clone the repository, but depending how much you will need to customize, it’s much easier to do from your local filesystem. Also, some themes (such as Notepad) ships with a lot of unecessary files that you need to cleanup. This will be described in the Customize section below.</em></p>
<p>Cloning it in your dev machine:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone git@github.com:adenot/adenot.github.io.git
cd adenot.github.io
</code></pre></div></div>
<p><em>replace adenot with your github username</em></p>
<p>Now run your blog locally with:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>jekyll serve
</code></pre></div></div>
<p>If all goes right, you should see the following page:</p>
<p><img src="/images/howtoblog-notepadinitial.png" alt="howtoblog-notepadinitial.png" /></p>
<p>Your blogging platform is now running. Let’s learn how to edit posts and customize it.</p>
<hr />
<h1 id="editing-with-proseio">Editing with Prose.io</h1>
<p>Prose.io is basically an in browser markdown editor connected to GitHub. To setup:</p>
<ol>
<li>Go to <a href="http://prose.io/">prose.io</a></li>
<li>Authorize</li>
<li>Select the project</li>
</ol>
<p><img src="/images/howtoblog-proseioproject.png" alt="howtoblog-proseioproject.png" /></p>
<p>If the file _custom.yml is configured correctly, you will only see the files inside _posts folder. Otherwise, just browse to the _posts folder, there should be some examples there.</p>
<p><img src="/images/howtoblog-proseioposts.png" alt="howtoblog-proseioposts.png" /></p>
<p>Simply click <em>Edit</em> and the markdown file will be open for editing. Saving from prose.io will modify your github repository so there’s no need to locally clone the repository after everything is setup.</p>
<p><img src="/images/howtoblog-proseiopostedit.png" alt="howtoblog-proseiopostedit.png" /></p>
<h1 id="customizing-your-blog">Customizing your blog</h1>
<p>That’s when we will need the cloned repository in your dev machine.</p>
<h2 id="config-file">Config file</h2>
<p>Edit the file _config.yml.</p>
<p>That’s the boring part, you will need to check item by item and replace with the information you want for your blog.</p>
<p><strong>Protip:</strong> You can also have an item called <em>prose</em> with information that prose.io will use to help you edit your posts. Notepad theme has done this greatly, as you can see in <a href="https://github.com/hmfaysal/Notepad/blob/gh-pages/_config.yml#L72">their original _config.yml file</a>. More information can be found on <a href="https://github.com/prose/prose/wiki/Getting-Started">Prose.io Getting Started page</a>.</p>
<hr />
<p><strong>If for some reason GitHub fails to build Jekyll, it will send an email to you informing that. So check your email if your page are not being updated after you pushed changes.</strong>
—</p>
<h2 id="htmlcss">HTML/CSS</h2>
<p>Locations for customizing HTML/CSS:</p>
<ul>
<li>_layouts/*.html - page layouts</li>
<li>_includes/*.html - page exerpts used in the layout</li>
<li>assets/css/style.css - add your custom CSS here</li>
</ul>
<h2 id="cleaning-up">Cleaning up</h2>
<p>If you are using Notepad theme, you will notice there are 2 branches: gh-pages and master. Unless you are using <a href="https://help.github.com/articles/user-organization-and-project-pages/#project-pages">GitHub Pages for a project page</a>, I recommend removing the gh-pages branch, it can be done by running:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git push origin :gh-pages # deletes remote branch gh-pages
</code></pre></div></div>
<p>Again for Notepad theme, you can safely delete images from the <em>images</em> folder, and replace the logo.png with your own.</p>
<p><a href="https://allandenot.com/development/2015/01/11/blogging-like-a-dev-jekyll-github-prose-io.html">Blogging like a dev: Jekyll + GitHub + Prose.io</a> was originally published by Allan Denot at <a href="https://allandenot.com">Allan Denot</a> on January 11, 2015.</p>https://allandenot.com/devops/2014/08/21/devops-interview-questions2014-08-21T00:00:00+10:002015-08-21T00:00:00-00:00Allan Denothttps://allandenot.comadenot at gmail
<p>These are some interview questions (the ones I could remember), which I received while interviewing for DevOps roles.</p>
<ul>
<li>What’s a PTR in DNS?</li>
<li>What’s a MX record in DNS?</li>
<li>Difference between RAID 1 and 5?</li>
<li>What’s the advantage of one RAID over another?</li>
<li>Alternative to init.d in Linux?</li>
<li>How to view running processes in Linux?</li>
<li>Difference between authorization and authentication?</li>
</ul>
<p><em>Common sense: any question that could be answer by Google in 5 seconds should not be used to test any one.</em></p>
<hr />
<p>Have more to add? Comment below and I will add it here.</p>
<p><a href="https://allandenot.com/devops/2014/08/21/devops-interview-questions.html">DevOps Interview Questions</a> was originally published by Allan Denot at <a href="https://allandenot.com">Allan Denot</a> on August 21, 2014.</p>https://allandenot.com/startups/2014/06/23/the-social-network-cycle2014-06-23T00:00:00+10:002011-01-08T00:00:00-00:00Allan Denothttps://allandenot.comadenot at gmail
<p>I read some complains recently about how snapchat has so many tap gestures and is complicated to use to the average person. After a bit of though, I realize that this is not a problem but a market strategy.</p>
<p>You probably aware of the life cycle of a social network. People join it in the beginning when all their cool friends are there, then it eventually gets less cool when some of your “undesirable” friends start to join and add you as a friend/follow you.</p>
<p>Then parents discover the social network and start to add their children and relatives. Whatever kids were posting before, they will think twice before posting.</p>
<p>But it gets worse. Eventually their teachers and bosses will join the network, that’s when we can’t post anything that will not please 100% of your public, i.e. you can’t post any more.</p>
<p>And that’s when the cool kids will move to another social network and the cycle restarts.</p>
<p>By making their app more complicated, snapchat is trying to stop or delay the join of older people to their network. And by older people, I mean parents, teachers and bosses.</p>
<p>Genius, right?</p>
<p><a href="https://allandenot.com/startups/2014/06/23/the-social-network-cycle.html">The social network cycle</a> was originally published by Allan Denot at <a href="https://allandenot.com">Allan Denot</a> on June 23, 2014.</p>