findcommonground.uk/_posts/2016-03-24-the-automated-monolith.md

76 lines
5.4 KiB
Markdown
Raw Normal View History

2016-03-24 11:43:10 +00:00
---
layout: post
title: The Automated Monolith
subtitle: Build, Deploy and Testing using Docker, Docker Compose, Docker Machine, go.cd and Azure
category: howto
tags: [cloud, devops, docker, automation]
author: marco_seifried
author_email: marco.seifried@haufe-lexware.com
header-img: "images/bg-post.old.jpg"
---
Let's be honest, systems age and while we try hard not to accumulate technical depth, sometimes you realize it's time for a bigger change. In this case, we looked at a Haufe owned platform providing services like user-, licence- and subscription management for internal and external customers. Written in Java, based on various open source components, somewhat automated, fairly monolithic.
2016-03-24 11:43:10 +00:00
Backed by our technical strategy, we try to follow the microservices approach (a good read is [Sam Newman's book](http://shop.oreilly.com/product/0636920033158.do)). We treat infrastructure as code and automate wherever possible.
So whenever we start from scratch, it's fairly straight forward to apply those principles.
But what if you already have your system, and it's grown over the years? How do you start? Keeping in mind we have a business critical system on a tight budget and a busy team. Try to convince business it's time for a technical face lift...
We decided to look at the current painpoints and start with something that shows *immediate business results in a reasonably short timeframe*.
2016-03-24 11:43:10 +00:00
### Rough Idea
The team responsible for this platform has to develop, maintain and run the system. A fair amount of their time went into deploying environments for internal clients and help them get up and running. This gets even trickier when different clients use an environment for testing simultanously. Setting up a test environment from scratch - build, deploy, test - takes 5 man days. That's the reality we tried to improve.
We wanted to have a one click deployment of our system per internal client directly onto Azure. Everything should be build from scratch, all the time and we wanted some automated testing in there as well.
To make it more fun, we decided to fix our first go live date to 8 working weeks later by hosting a public [meetup](http://www.meetup.com/de-DE/Timisoara-Java-User-Group/events/228106103/) in Timisoara and present what we did! The pressure (or fun, depending on your viewpoint) was on...
So time was an issue, we wanted to be fast to have something to work with. Meaning that we didn't spend much time in evaluating every little component we used but made sure we are flexible enough to change it easily - evolutionary refinement instead of initial perfection.
### How
Our guiding principles:
* **Infrastructure as code** - EVERYTHING. IN CONFIG FILES. CHECKED IN. No implicit head knowledge.
* **Immutable Servers** - We build from scratch, the whole lot. ALWAYS. NO UPDATES, HOT FIX, NOTHING.
* **Be independent of underlying infrastructure** - it shouldn't matter where we deploy to. So we picked Azure just for the fun of it.
Main components we used:
* [go.cd](https://www.go.cd/) for continous delivery
* [Docker](https://www.docker.com/): All our components run within docker containers
* [Bitbucket](https://bitbucket.org/) as repository for config files and scripts
* [Team Foundation Server](https://www.visualstudio.com/en-us/products/tfs-overview-vs.aspx) as code repository
* [Artifactory](https://www.jfrog.com/open-source/#os-arti) as internal docker hub
* [ELK stack](https://www.elastic.co/webinars/introduction-elk-stack) for logging
* [Grafana](http://grafana.org/) with [InfluxDB](http://grafana.org/features/#influxdb) for basic monitoring
The flow:
{:.center}
![go.cd Flow]( /images/automated-monolith/automated_monolith_flow.jpg){:style="margin:auto"}
2016-03-24 11:43:10 +00:00
Let's first have a quick look on how go.cd works:
Within go.cd you model your worklows using pipelines. Those pipelines contain stages which you use to run your jobs which themselves contain tasks. Stages will run in order and if one fails, the pipeline will stop. Jobs will run in parallel, go.cd is taking care of that.
The trigger for a pipeline to run is called a material - so this can be a git repository where a commit will start the pipeline.
You can also define variables on multiple levels - we have used it on a pipeline level - where you can store things like host names and alike. There is also an option to store secure variables.
In our current setup we use three pipelines: The first on creates a docker image for every component in our infrastructure - database, message queue, application server. It builds images for the logging part - Elastic Search, Kibana and Fluentd - as well as for the monitoring and testing.
We also pull an EAR file out of our Team Foundation Server and deploy it onto the application server.
2016-03-24 11:43:10 +00:00
Haufe has written and open sourced a [plugin](https://github.com/Haufe-Lexware/gocd-plugins/wiki/Docker-pipeline-plugin) to do exactly that job: Building a docker image.
2016-03-24 11:43:10 +00:00
Put in an image name and point to the dockerfile:
![go.cd Flow]( /images/automated-monolith/docker_plugin_1.jpg){:style="margin:auto"}
You can also tag your image:
2016-03-24 11:43:10 +00:00
![go.cd Flow]( /images/automated-monolith/docker_plugin_2.jpg){:style="margin:auto"}
Our docker images get stored in our internal Artifactory which we use as a docker hub. You can add your repository and the credentials for that as well:
2016-03-24 11:43:10 +00:00
![go.cd Flow]( /images/automated-monolith/docker_plugin_3.jpg){:style="margin:auto"}
Those images are based on our [docker guidelines](https://github.com/Haufe-Lexware/docker-style-guide).