Continuous Delivery  -  Deploying a Node.js app to AWS EC2 using Ansible
Tags: devops, ansible, iac
Published: 2020-02-03 02:50:35

<!-- wp:paragraph -->
<p>The main key point for all our projects is trying to automate all things, it helps to reduce errors (e.g. human mistake), fast and easy to deploy / rollback, and improve customer satisfaction.</p>
<!-- /wp:paragraph -->

<!-- wp:image {"linkDestination":"custom"} -->
<figure class="wp-block-image"><img src="https://cdn-images-1.medium.com/max/800/0*RBJGZPYN8d8R2BuB" alt="Continuous Delivery and Automation are Key"/><figcaption><a rel="noreferrer noopener" href="https://www.google.com.vn/url?sa=i&amp;source=images&amp;cd=&amp;ved=2ahUKEwiJ2rKF0bfeAhXYaN4KHcZ_D8QQjhx6BAgBEAM&amp;url=https%3A%2F%2Fwww.slideshare.net%2Fdcjuengst%2Fcloudbeesjenkinsplatform2016&amp;psig=AOvVaw1RxLgKUvrZis9gBgTe1LLi&amp;ust=1541314216834361" target="_blank">Images Sources</a></figcaption></figure>
<!-- /wp:image -->

<!-- wp:more -->
<!--more-->
<!-- /wp:more -->

<!-- wp:paragraph -->
<p>We do have some approaches to automate the deployment process that we have been applying to our projects such as using <a rel="noreferrer noopener" href="https://aws.amazon.com/elasticbeanstalk/" target="_blank">Amazon Elastic BeanStalk</a> or <a rel="noreferrer noopener" href="https://aws.amazon.com/ecs/" target="_blank">Amazon Elastic Container Service</a>. However, in some cases, our customers they don’t want to use those approaches because they don’t use AWS, they’ve already had the servers to run the app, they want to keep their app on their On-Prime Data Center and have their IT guy to manage it. It led us to have to find out another approach to automate our delivery process. And we have chosen Ansible as the tool to implement our Continuous Delivery pipeline.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>So I would like to write this article to share with you and outline our workflow and provide a brief introduction along with sample code to build this flow.</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":4} -->
<h4>The Tools</h4>
<!-- /wp:heading -->

<!-- wp:list -->
<ul><li><a href="https://jenkins.io/doc/" rel="noreferrer noopener" target="_blank">Jenkins</a>: Jenkins is a self-contained, open-source automation server that can be used to automate all sorts of tasks related to building, testing, and delivering or deploying software.</li><li><a href="https://www.ansible.com/" rel="noreferrer noopener" target="_blank">Ansible</a>: Ansible is an open-source automation platform. Ansible can help you with configuration management, application deployment, task automation. It can also do IT orchestration, where you have to run tasks in sequence and create a chain of events that must happen on several different servers or devices.</li><li><a href="https://slack.com" rel="noreferrer noopener" target="_blank">Slack</a>: a cloud-based set of proprietary team collaboration tools and services.</li></ul>
<!-- /wp:list -->

<!-- wp:heading {"level":4} -->
<h4>Why Ansible?</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>As you know, there are a lot of tools for infrastructure automation (infrastructure as code) such as Terraform, Chef, Ansible, Juju, and more. But there are a few reasons that make me selected Ansible as below:</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>It is very, <a href="https://docs.ansible.com/ansible/2.7/installation_guide/intro_installation.html" rel="noreferrer noopener" target="_blank">very simple to set up </a>and yet powerful.</li><li>Ansible is a radically simple IT automation platform that makes your applications and systems easier to deploy. Avoid writing scripts or custom code to deploy and update your applications.</li><li>Automate in a language that approaches plain English, using SSH, with no agents (likes Puppet or Chef) to install on remote systems.</li><li>Easy to integrate with our CI/CD pipeline using the Jenkins server.</li></ul>
<!-- /wp:list -->

<!-- wp:heading {"level":4} -->
<h4>The Steps</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>What we are going to build is the following deployment flow:</p>
<!-- /wp:paragraph -->

<!-- wp:list {"ordered":true} -->
<ol><li>Launch EC2 instance(s) (optional).</li><li>Update OS and install needed dependencies such as install Node.js.</li><li>Deploy the Node.js app to EC2 instance(s).</li><li>Configure DNS (optional).</li><li>Smock test.</li></ol>
<!-- /wp:list -->

<!-- wp:heading {"level":4} -->
<h4>Let’s coding…</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p><strong>Project Structure</strong></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>When doing any coding stuff, the <em>project structure</em> is one of the most importing things I pay attention to. If you have experience in working with Ansible, you should know how to organize the Ansible project. I followed the alternative approach mentioned in <a href="https://docs.ansible.com/ansible/latest/user_guide/playbooks_best_practices.html#directory-layout" rel="noreferrer noopener" target="_blank">this</a> article, feel free to select your own approach.</p>
<!-- /wp:paragraph -->

<!-- wp:image -->
<figure class="wp-block-image"><img src="https://cdn-images-1.medium.com/max/800/1*4Juvy1AXwPQwI0UwADyXlw.png" alt="Ansible project structure"/><figcaption>Ansible Project Structure</figcaption></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>My project contains the following root directories/files:</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li><em>scripts</em>: it contains a shell <em>setup</em> script to install Ansible, Ansible Galaxy,  generate a self-signed certificate to run our Node.js app in secure mode (HTTPS).</li><li><em>cert</em>: directory to keep a self-signed certificate.</li><li><em>ansible</em>: put all Ansible code into this directory including playbooks, roles, var files, etc.</li><li><em>Jenkinsfile</em>: the Jenkins pipeline code for CI/CD pipeline.</li></ul>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p><strong>Role</strong></p>
<!-- /wp:paragraph -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>In Ansible, the role is the primary mechanism for breaking a playbook into multiple files. This simplifies writing <strong>complex playbooks</strong>, and it makes them easier to reuse. The breaking of playbook allows you to logically break the playbook into reusable components.</p></blockquote>
<!-- /wp:quote -->

<!-- wp:paragraph -->
<p>Here are the following roles we will use on this project:</p>
<!-- /wp:paragraph -->

<!-- wp:image -->
<figure class="wp-block-image"><img src="https://cdn-images-1.medium.com/max/800/1*Jhtfl60VH2zu9m268e9SzA.png" alt="Ansible roles"/><figcaption>Ansible Roles</figcaption></figure>
<!-- /wp:image -->

<!-- wp:list -->
<ul><li><em>apache-server</em>: we don’t use this role on this project but I wanted to keep it here. This role will configure the Apache using our own <em>httpd.conf</em> template file. To install Apache, we can use <a rel="noreferrer noopener" href="https://github.com/geerlingguy/ansible-role-apache" target="_blank">geerlingguy.apache</a> role.</li><li><em>common</em>: put all your comment stuff into this role such as update your OS to ensure your server(s) are up to date.</li><li><em>launch-ec2</em>: this role to launch EC2 instance(s) to deploy our app.</li><li><em>node-server</em>: contains all needed steps to deploy and run the Node.js app</li><li><em>nodejs</em>: install the Node.js runtime.</li></ul>
<!-- /wp:list -->

<!-- wp:paragraph -->

<!-- wp:heading {"level":4} -->
<h4>Conclusion</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Using Ansible, you can easy to provision and install software to run your application automatically, you can manage your infrastructure as code (IaC). However, running your software is not simple likes this demo, you will need to do more things such as setup network, configure firewall, auto-scaling. To do those things, you might need to combine with other tools. For example, you can use the AWS CDK framework to provide your AWS infrastructure (network, database, EC2 instances, and auto-scaling), then use Ansible to provision your EC2 instances and configure your applications. </p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>I hope this post will bring some ideas to you to design and deploy your application. If you have any issues or need help, just let me know by adding comments on this post. </p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Thank you for reading!</p>
<!-- /wp:paragraph -->

This post is originally published on [our blog](https://innomizetech.com/blog/continuous-delivery-deploying-a-node-js-app-to-aws-ec2-using-ansible).