54
Deploying (micro)services with Disnix Sander van der Burg Nov 14, 2015 Sander van der Burg Deploying (micro)services with Disnix

Deploying (micro)services with Disnix

Embed Size (px)

Citation preview

Deploying (micro)services with Disnix

Sander van der Burg

Nov 14, 2015

Sander van der Burg Deploying (micro)services with Disnix

Microservice architectures

Microservice architectures have become quite popular:

Sander van der Burg Deploying (micro)services with Disnix

Microservice architectures

There are even books available:

Sander van der Burg Deploying (micro)services with Disnix

Microservice architectures: What are they?

In short, the microservice architectural style is anapproach to developing a single application as a suite ofsmall services, each running in its own process andcommunicating with lightweight mechanisms, often anHTTP resource API. These services are built aroundbusiness capabilities and independently deployable byfully automated deployment machinery. There is a bareminimum of centralized management of these services,which may be written in different programming languagesand use different data storage technologies.

– Martin Fowler

Sander van der Burg Deploying (micro)services with Disnix

Microservice architectures: What are they?

In short, the microservice architectural style is anapproach to developing a single application as a suite ofsmall services, each running in its own process andcommunicating with lightweight mechanisms, often anHTTP resource API. These services are built aroundbusiness capabilities and independently deployable byfully automated deployment machinery. There is a bareminimum of centralized management of these services,which may be written in different programming languagesand use different data storage technologies.

– Martin Fowler

Sander van der Burg Deploying (micro)services with Disnix

Microservice architectures: are they a revolution?

Sander van der Burg Deploying (micro)services with Disnix

Microservice architectures: are they a revolution?

Sander van der Burg Deploying (micro)services with Disnix

Service oriented architectures

Services are autonomous, platform-independententities that can be described, published, discov-ered, and loosely coupled in novel ways. They per-form functions that range from answering simplerequests to executing sophisticated business pro-cesses requiring peer-to-peer relationships amongmultiple layers of service consumers and providers.Any piece of code and any application componentdeployed on a system can be reused and trans-formed into a network-available service.

Microservice architectures: are they a revolution?

“A software component is a unit of composition withcontractually specified interfaces and explicit contextdependencies only. A software component can bedeployed independently and is subject to composition bythird parties.”

Sander van der Burg Deploying (micro)services with Disnix

Let’s implement an example system!

Sander van der Burg Deploying (micro)services with Disnix

Let’s implement an example system!

Sander van der Burg Deploying (micro)services with Disnix

Stafftracker

Let’s maintain a collection of staff members and theirrooms

From the room number I can determine the zipcode

From the zipcode I can determine the street and city

Divide the system into processes communicatingthrough “light weight” network protocols (HTTP,TCP, ...)

Designing an architecture

Sander van der Burg Deploying (micro)services with Disnix

Designing an architecture

Sander van der Burg Deploying (micro)services with Disnix

Pros

Strong Module Boundaries:

You can build teams around each service

Independent Deployment:

Less likely that a failure crashes the whole systemA small component is typically easier to deploy (e.g.fewer dependencies)

Technology Diversity:

One service can be implemented in JavaScript,another in Python etc.Any storage means possible (e.g. databases)We can use many operating systems, hardwarearchitectures etc.

(source: http://martinfowler.com/microservices)

Designing an architecture

Sander van der Burg Deploying (micro)services with Disnix

Cons

Distribution:

Network links are slow and subject to failure

Eventual Consistency:

Difficult to guarantee that data remains consistent

Operational Complexity:

...

(source: http://martinfowler.com/microservices)

Operational Complexity

All services can be deployed to one machine, but each service canalso run on a dedicated machine:

Worst case: 8 machines need to be managed

Sander van der Burg Deploying (micro)services with Disnix

Operational Complexity

Diverse technology imposes many kinds of deployment procedures:

Deploying a Node.js package is different than deploying aPython package

Different operating systems, different dependencies, manyvariants

Sander van der Burg Deploying (micro)services with Disnix

Operational Complexity

How to update the deployment frequently?

How not to break the system while upgrading?

How to minimize downtimes?

How to roll back in case of a failure?

Sander van der Burg Deploying (micro)services with Disnix

The Nix project

Automated deployment using declarative specifications with thefollowing properties:

Generic. Can be used with many programming languages,component technologies, and operating systems.

Reproducible. (Almost) no impurities – if inputs are the same,result should be the same regardless of its location

Reliable. Dependency completeness, (almost) atomicupgrades and rollbacks.

Efficient. Only the required deployment activities areexecuted.

Sander van der Burg Deploying (micro)services with Disnix

The Nix project

Automated deployment using declarative specifications with thefollowing properties:

Generic. Can be used with many programming languages,component technologies, and operating systems.

Reproducible. (Almost) no impurities – if inputs are the same,result should be the same regardless of its location

Reliable. Dependency completeness, (almost) atomicupgrades and rollbacks.

Efficient. Only the required deployment activities areexecuted.

Sander van der Burg Deploying (micro)services with Disnix

The Nix project: Tools

Nix – declarative specification of package build procedures(including their dependencies)

NixOS – declarative specification of system aspects

Hydra – declarative specification of jobs

NixOps – declarative specification of a network of machines

Deployment activities are implicit – a user writes or adapts a deploy-ment specification, and the tools will carry out the required activities,such as building, transfering, activating, and deactivating.

Sander van der Burg Deploying (micro)services with Disnix

Deploying (micro)services

How to deploy (micro)service(-oriented) systems the “Nix-way”?

Sander van der Burg Deploying (micro)services with Disnix

Disnix

$ disnix-env -s services.nix -i infrastructure.nix -d distribution.nix

Sander van der Burg Deploying (micro)services with Disnix

Disnix: Modeling a service build

{stdenv, inetutils}:

let

makeFlags = "PREFIX=$out "+

"inetutils=${inetutils}";

in

stdenv.mkDerivation {

name = "hello-world-client";

src = ../../../services/hello-world-client;

buildPhase = "make ${makeFlags}";

installPhase = "make ${makeFlags} install";

}

Services are specified in a similar way as “ordinary” Nix packages:

Define a function taking local (intra-dependencies) as aparameters

Body describes how to build package from source and itsdependencies

Sander van der Burg Deploying (micro)services with Disnix

Disnix: Modeling a service build

Sander van der Burg Deploying (micro)services with Disnix

Disnix: Modeling a service build

{stdenv, inetutils}:

{hello world server}:

let

makeFlags = "PREFIX=$out "+

"helloWorldHostname=${hello world server.target.hostname} "+

"helloWorldPort=${toString (hello world server.port)} "+

"inetutils=${inetutils}";

in

stdenv.mkDerivation {

name = "hello-world-client";

src = ../../../services/hello-world-client;

buildPhase = "make ${makeFlags}";

installPhase = "make ${makeFlags} install";

}

Disnix expressions also take inter-dependencies into account

Sander van der Burg Deploying (micro)services with Disnix

Composing services locally

{system, pkgs}:

let

callPackage = pkgs.lib.callPackageWith (pkgs // self);

self = {

hello_world_server = callPackage ../pkgs/hello-world-server { };

hello_world_client = callPackage ../pkgs/hello-world-client { };

};

in

self

As with ordinary Nix packages, we need to compose their intra-dependencies by providing them as function parameters.

Sander van der Burg Deploying (micro)services with Disnix

Services model

{system, distribution, invDistribution, pkgs}:

let

# Imports the intra-dependency composition shown previously

customPkgs = import ../top-level/all-packages.nix { inherit system pkgs; };

in rec {

hello_world_server = rec {

name = "hello_world_server";

pkg = customPkgs.hello_world_server { inherit port; };

port = 3000;

type = "wrapper"; # Specifies how to activate and deactivate a service

};

hello_world_client = {

name = "hello_world_client";

# Refers to the intra-dependency closure of the client

pkg = customPkgs.hello_world_client;

dependsOn = { # Inter-dependency composition

inherit hello_world_server;

};

type = "echo";

};

}

Sander van der Burg Deploying (micro)services with Disnix

Infrastructure model

{

test1 = { # x86 Linux machine (Kubuntu) reachable with SSH

hostname = "192.168.56.101";

system = "i686-linux";

targetProperty = "hostname";

clientInterface = "disnix-ssh-client";

};

test2 = { # x86-64 Linux machine (NixOS) reachable with SOAP/HTTP

hostname = "192.168.56.102";

system = "x86_64-linux";

targetEPR = http://192.168.56.102:8080/DisnixWebService/...;

targetProperty = "targetEPR";

clientInterface = "disnix-soap-client";

};

test3 = { # x86-64 Windows machine (Windows 7) reachable with SSH

hostname = "192.168.56.103";

system = "x86_64-cygwin";

targetProperty = "hostname";

clientInterface = "disnix-ssh-client";

};

}

Sander van der Burg Deploying (micro)services with Disnix

Distribution model

{infrastructure}:

{

hello_world_server = [ infrastructure.test2 ];

hello_world_client = [ infrastructure.test1 ];

}

Maps services in the services model to target machines in the infras-tructure model

Sander van der Burg Deploying (micro)services with Disnix

Demo

Sander van der Burg Deploying (micro)services with Disnix

Demo

Initial deployment:

$ disnix-env -s services.nix -i infrastructure.nix -d distribution.nix

Adding a second client (by adding test2):

$ disnix-env -s services.nix -i infrastructure.nix -d distribution.nix

Moving the server from test2 to test3 and building on targets:

$ disnix-env -s services.nix -i infrastructure.nix -d distribution.nix \--build-on-targets

Sander van der Burg Deploying (micro)services with Disnix

Disnix: Communication flow

disnix-env communicates with target machines through a customconnection client to remotely execute deployment activities:

SSH (the default)

SOAP/HTTP through DisnixWebService(http://github.com/svanderburg/DisnixWebService)

NixOps through DisnixOS(http://github.com/svanderburg/disnixos)

Sander van der Burg Deploying (micro)services with Disnix

Disnix: Communication flow

Two deployment tools are invoked to carry out remote deploymentactivities:

Nix (http://nixos.org/nix): package manager responsiblefor building, distributing

Dysnomia (http://github.com/svanderburg/dysnomia):plugin system responsible for activating, deactivating, locking,snapshotting, restoring

Sander van der Burg Deploying (micro)services with Disnix

Disnix: Process decomposition of disnix-env

Each deployment activity is implemented by a command-line tool.

Sander van der Burg Deploying (micro)services with Disnix

Disnix: Process decomposition of disnix-env

Two additional tools are used when building on targets has beenenabled.

Sander van der Burg Deploying (micro)services with Disnix

How can we deploy our example system?

Sander van der Burg Deploying (micro)services with Disnix

How can we deploy our example system?

Sander van der Burg Deploying (micro)services with Disnix

Implementation details

Each database: a MongoDB database instance

Each service: a process with REST API implementedin Node.js

Web application front-end: A web applicationimplemented in Node.js

nginx proxy

Infrastructure deployment

Before we can use Disnix, we need machines first! With thefollowing characteristics:

A Disnix service instance for executing deployment stepsremotely

MongoDB DBMS

Machines can be deployed with various kinds of (external)solutions (including: Disnix itself).

Sander van der Burg Deploying (micro)services with Disnix

Infrastructure deployment

NixOps can be used to automatically instantiate and deploy anetwork of NixOS machines having the required characteristics:

{

test1 = {

{ pkgs, ...}:

{

networking.firewall.enable = false;

# Enable the Disnix service

services.disnix.enable = true;

# Enabling MongoDB also configures Disnix

# to use the Dysnomia plugin that can activate it

services.mongodb.enable = true;

services.mongodb.bind_ip = "0.0.0.0";

}

test2 = ...

test3 = ...

}

Sander van der Burg Deploying (micro)services with Disnix

Integrating service and infrastructure deployment

Disnix’s service deployment and NixOps’ infrastructure deploymentfacilities can be combined with an extension toolset called:DisnixOS.

Major difference with the basic toolset: DisnixOS usesnetworked NixOS configuration files instead of aninfrastructure model

Sander van der Burg Deploying (micro)services with Disnix

Demo

Sander van der Burg Deploying (micro)services with Disnix

Demo

Deploying a network of NixOS machines with NixOps:

$ nixops create ./network.nix ./network-virtualbox.nix -d test$ nixops deploy -d test

Deploying services to machines with DisnixOS:

$ export NIXOPS DEPLOYMENT=test$ disnixos-env -s services.nix \-n network.nix -n network-virtualbox.nix \-d distribution.nix --use-nixops

Sander van der Burg Deploying (micro)services with Disnix

A real world example: Conference Compass

Sander van der Burg Deploying (micro)services with Disnix

A real world example: Conference Compass

Conference Compass provides a service to improve the waypeople experience events

Most visible part of the service: apps for conference attendeesEach customer basically gets “their own” app.

We have a product-line using a Nix-based build infrastructure,including Hydra

Sander van der Burg Deploying (micro)services with Disnix

A real world example: Conference Compass

The app’s contents is customizable with a configurator serviceallowing organizers to create and update their content

Apps connect to a configurator to retrieve the data to bedisplayed and other configuration settings

Integration with third party information systems is alsopossible

Sander van der Burg Deploying (micro)services with Disnix

Architectural decisions

Each app connects to its own dedicated configurator service:

No single point of failureMore scalable – slow configurator of one app does not affectanotherMore flexible – we can easily move configurators aroundMultiple version support – we can add new features for a newapp, without breaking old appsImplemented in Node.js

Each third party integration (called: channel) is a seperateprogram:

They may consume a lot of system resourcesImplemented in Python, because we find that more appropriatefor data conversion

Processes communicate through REST/HTTP APIs

Sander van der Burg Deploying (micro)services with Disnix

Deploying services

We deploy four kinds of services with Disnix:

Configurators (Node.js programs)

Channels (Python programs)

Mongo databases (one for each configurator)

nginx proxies (one for each machine)

Responsible for forwarding requests to configurators andcaching expensive requests

Sander van der Burg Deploying (micro)services with Disnix

Deploying services

A simple deployment scenario:

(Diagram generated with disnix-visualize)

Sander van der Burg Deploying (micro)services with Disnix

Deploying services

We might want to move services to more powerful machines whenan event goes live (because more users of an app imply that moresystem resources are needed, e.g. network bandwidth):

Sander van der Burg Deploying (micro)services with Disnix

Deploying services

For really big events, we may want to deploy redundant instancesconfigurators and channels to handle all the load:

Sander van der Burg Deploying (micro)services with Disnix

Some statistics

We have been using Disnix + NixOps for deploying ourproduction environment since January 2015

Between 6-11 Amazon EC2 machines are managed by NixOps

±80 configurators have been deployed with Disnix includingtheir inter-dependencies

Translates to ±200 services managed by Disnix

Production environment is frequently updated. Sometimesthree times a day.

Transition phase duration is ±5 minutes in worst case. Mostsimple upgrades only bring a few seconds of downtime.

Sander van der Burg Deploying (micro)services with Disnix

Conclusions

I have explained the relevance of componentized distributedsystem architectures (e.g. microservices)

I have explained how to do service deployment with Disnix

I have explained how to integrate infrastructure deploymentand service deployment

I have shown a real-life usage scenario

Sander van der Burg Deploying (micro)services with Disnix

References

There is much more you can do with Disnix! This presentationonly covers a few basic aspects!

Disnix homepage: http://nixos.org/disnix

TCP proxy example: https://github.com/svanderburg/disnix-proxy-example

StaffTracker examples:

Java/WebServices/MySQL version: https://github.com/svanderburg/disnix-stafftracker-java-examplePHP/MySQL version: https://github.com/svanderburg/disnix-stafftracker-php-exampleNode.js/MongoDB version: https://github.com/svanderburg/disnix-stafftracker-nodejs-example

Disnix should be considered an advanced prototype tool!

Sander van der Burg Deploying (micro)services with Disnix

References

Sander van der Burg Deploying (micro)services with Disnix

Questions

Sander van der Burg Deploying (micro)services with Disnix