Skip to content
This repository has been archived by the owner on Mar 24, 2022. It is now read-only.

EXXETA/devops-demo

Repository files navigation

Build Status

Principles of DevOps Demo

In this project we demo a couple of techniques informed by the three pillars of DevOps: flow, feedback, and continual experimentation.

Table of contents

Setup

This demo was developed and tested on OSX - it should therefore run just as well on Linux operating systems.

For OSX Docker installation instructions, visit https://docs.docker.com/docker-for-mac/install/.

For how to install and work with Docker (a central component of this sample project) on Windows please follow the instructions here: https://docs.docker.com/docker-for-windows/.

Make certain you have Docker installed in a recent version:

$ docker --version
Docker version 17.12.0-ce, build c97c6d6

I recommend using Anaconda Python 3 which is straightfoward to use and maintain virtual environment with: https://www.anaconda.com/download/.

Create a virtual environment:

$ conda create -n devops python=3.6 --yes

Activate the virtual environment:

$ source activate devops

Install high-level DevOps-specific frameworks:

$ pip install -r requirements.txt

Run tests for greetings service

Install greetings requirements

$ pip install pytest
$ pip install -r greetings/requirements.txt

Run tests

$ python -m pytest greetings -k tests

Test services locally

To build all Docker images:

$ docker-compose build

Now run the services locally:

$ docker-compose up

To see all Docker containers that the above command starts:

$ docker ps

To shut all services down again:

$ docker-compose down

A tour of our services

Now that our services are running (docker-compose up) let us take a look at the various services we have and how they interact.

Imagine we worked on an exciting new app - a really friendly calculator. Our calculator implements all the important arithmetic operations and presents the results together with a friendly personalized greeting.

Our calculator app therefore has three main components: A main app with a user interface (this is our Awesome App), a greetings module that generates a personal greeting based on the user's first name, and a mathematics module that implements all desired arithmetic operations.

Now suppose that our organization is already fairly big with numerous developers constantly improving each of these three components. To reduce friction between the developers and allow overall faster development we already broke up our three components into three microservices.

image

Note that our docker-compose.yml file describes this structure in detail.

Awesome App

Our Awesome App (the main app interface) implements a simple endpoint (see awesome_app/awesome_app/app.py) which forwards the user's name to the greetings service and the input variables to the maths service. Once the greetings and maths services respond, the awesome_app service fills all the information it has into an interface template (awesome_app/awesome_app/templates/index.html) to be displayed in the user's browser.

image

Greetings

Our greetings service takes the user's name and returns a personalized greeting.

image

Note that the greetings service is reachable at the address http://localhost:5002 whereas the awesome app service is reachable at a different address http://localhost:5000.

Greetings are likely a matter of personal taste. The team working on the greetings service has therefore implemented an online A/B test (greetings/greetings/service.py) which adapts the applied greeting to the user's taste:

The awesome_app interface presents a Like button that sends a POST request to the greeting service thus sending a signal that the user enjoyed the greeting they were presented with. The greetings service then stores this positive signal in a Redis backend (a popular, fast key-value data store used in numerous web applications akin to ours) by incrementing the respective greeting counter by one.

Upon requesting a personalized greeting from our greeting service we return the best-performing greeting 90% of the time (exploitation). For 10% of the greeting requests we return a randomly chosen personalized greeting in order to explore whether the user's preference has changed (exploration). See greetings/greetings/service.py for details.

Also check the terminal window where we started our services where the greetings service informs us about the number of observed Like signals for each greeting and the personalization strategy (exploration / exploitation) used.

image

Mathematics

Our mathematics service implements the arithmetic operations desired by our users (see maths/maths/service.py).

image

The team maintaining the mathematics service is interested in seeing which arithmetic operations our users are most interested in. To this end, they attached their service to a StatsD / Graphite service which allows them to easily monitor the number of times each arithmetic operation is invoked. Here the team increments a corresponding counter every time an arithmetic operation is invoked.

This now allows our mathematics team to monitor in real-time service-level metrics in their Graphite web interface:

image

The dashboard tool Grafana offers a more up-to-date look than Graphite and presents a plethora of dashboard widgets to make all metrics collected through StatsD / Graphite accessible for everyone.

To log into the Grafana dashboard in this sample app, use username admin and password admin. Click on "Add Datasource" and add our Graphite service as follows:

image

For how to create dashboards in Grafana please refer to the documentation of the Grafana project:

http://docs.grafana.org/features/datasources/graphite/

Continuous Testing / Integration

We use TravisCI to run tests every time we push code changes to our GitHub repository.

For details on what tests we run and we integrate with TravisCI see the file .travis.yml.

Be aware that we run both small unit tests (greetings/greetings/test_greetings.py) in the TravisCI cloud and more involved integration tests (integration_tests/test_awesome_app.py) where we open a headless (windowless) Google Chrome browser, navigate to our Awesome App interface, and check that the browser sees what we expect to see - all in the TravisCI cloud.

This integration of GitHub with TravisCI presents our developers with rapid feedback on their work (in line with the second way of DevOps).