Code Monkey home page Code Monkey logo

lg201's Introduction

LG201

Table of contents

Prerequisites

To run these examples the following must be configured on the local host:

All solutions were implemented on OS X Sierra and due to time constraints have not been tested on any other platforms. The benefit of using virtualisation technologies here means it should work on other platforms with no changes, however YMMV.

Local docker registry

For this example, a local docker registry will be used for speed and ease of development.

This won't be covered by the Ansible automation so will need to be setup before running any commands.

If you already have a suitable docker registry, go ahead and skip this step, but change the docker_registry variable in the Ansible playbook files.

To set up a docker registry on the host machine run

$ docker run -d -p 5000:5000 --restart=always --name registry registry:2

Note: for speed, this registry is not configured securely and is not production-ready in this form. In a real-world scenario, the registry should be secured with TLS and require authentication if it's externally accessible.

Task 1

This is the solution to task 2, to see the solution to task 1 checkout tag task1 in this repository.

Alternatively you can view it in the browser here https://github.com/hipyhop/LG201/tree/task1.

Solution

The solution to Task 2 involves building the two application servers as Docker images, and running them as containers on the web server hosts.

I've separated this into two sections to simulate a typical CI/CD pipeline building the docker images when changes are published, and a manual deployment stage using Ansible/vagrant automation.

Building the applications with Docker

In lieu of a CI system, such as Jenkins, I've added build.sh scripts to the forked application repository https://github.com/hipyhop/Hello.

To simulate a build you can clone the repository and run ./build.sh in the respective directories to build the application images. Then, if successful, push the resulting image to the specified Docker registry.

EXPORT DOCKER_TAG=latest
EXPORT DOCKER_REGISTRY=localhost:5000

./build.sh

Ideally these would be added to the CI/CD pipeline as build steps, hopefully with additional testing/validation steps between the building the image, and pushing it to the remote registry.

Then on a successful build the new image(s) will be ready to be deployed.

Deploying the containers with vagrant

Launching the three required vagrant guests and provisioning them with the required configuration is as simple as running:

vagrant up

What does this do?

  1. Launches three ubuntu/trusty64 guests within the same private network and creates an Ansible inventory file.
  2. This inventory files groups two hosts as docker-hosts, and the other as a load balancer.
  3. Then the Ansible playbook common.yml is used to provision these hosts. As Ansible files are designed to be human-readable, I recommend reading this file for more information on the provisioning process.
  4. The application servers are deployed as containers from the docker registry using the tag latest. Each docker_host runs one go_app, and one node_app instance.
  5. The load balancer is configured with two ACLs to route incoming L7 traffic to the appropriate backend based on the request path.

If it any point in the future more docker hosts need to be added, just edit the N_DOCKERHOSTS variable in the Vagrantfile. The next time vagrant up is run the Ansible inventory file will be updated.

See lines 46-48 and 54-56 of haproxy/haproxy.cfg.j2 to see how the HAProxy configuration is dynamically generated from the Ansible inventory file.

Issues

Duplicated provisioning

In the current setup, vagrant runs the Ansible playbook after each host definition, resulting in a lot of duplicated effort.

This isn't a huge problem, since Ansible modules are smart about the defined tasks and can check if anything needs doing, however this still introduces a significant delay to the up-provision loop.

It looks like I'm not the only person to face this issue: hashicorp/vagrant#1784 A few suggestions were offered, but I couldn't find a decent solution within a sensible time..

The best way around it appears to be separating the spin-up and provisioning steps:

$ vagrant up --no-provision && vagrant provision

Improvements

There are a number of possible improvements that could be added in the future to improve the efficiency and speed of builds, while simplifying the deployment stage.

  • Kubernetes! Currently there is no orchestration. Deployment is manual using vagrant up or vagrant provision. Containers are restarted on failure, and the load balancer performs health checks to ensure the host is alive before routing traffic to it. But Kubernetes would handle restarting the services on new hosts automatically if required.

  • No logging or notifications in the current implementation. It's all good having a fail-over system, but nobody is notified about a failure, you may get to a point where all fail-over systems have failed, resulting in downtime.

  • Vagrant is slower and more resource intensive than containers. The whole solution could be implemented with docker-compose or kubernetes more efficiently. However that's not what the solution asked for.

  • Initial vagrant host provisioning time is quite slow. In a real-world scenario I would look into building a suitable Vagrant box with the latest updates and dependencies pre-installed to reduce provisioning time on each launch.

  • The docker build stage doesn't go in to too much details about how this would work in a CI/CD pipeline. Given time I would:

    • Keep a local cache of the git repository, to speed up clone/git pull times.
    • mount the source directory into a docker container and run any tests in there.
    • Build the docker image inside the container, by mounting the the host's docker socket to the CI container docker run -v /var/run/docker.sock:/var/run/docker.sock .... This is much better than running docker-in-docker.
  • The applications are stateless. Not data storage on the local filesystem or a database is required making this example reasonably trivial.

lg201's People

Contributors

hipyhop avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.