Control Center - A container-based management system


Sorry for the long absence. Been struggling to find some time to sit down and write, so glad to be finally doing it! Today's topic I am going to go through some work I've been doing with Control Center. (note American spelling!)

What is Control Center?

You probably would not of heard of Control Centre unless you've been working with Zenoss. The project seems to have stated, publicly anyway, in Aug 2013 and is actively being developed.
Control Centre is essentially a neat container management system. No, not the type you find at the Docklands.

It's key components are:

  • Docker & Docker Registry
  • OpentTSDB & Hbase
  • Logstash - process logs
  • Elasticsearch - Store logs
  • Zookeeper - cluster coordination
  • AngularJS, Bootstrap and nvd3.js for UI
  • Linux kernel for NFS, Btrfs and cgroups.

At the heart of Control Centre's automation are JSON service files, it is in here where you define what Control Centre should do to deliver your application. As part of this article we will:

  • Install Control Centre
  • Build a Docker image for our app
  • Provide the config files for our app to Control Centre
  • Configure the Networking for our container via Control Centre
  • Create persistent storage with Control Centre with the use of Docker Volumes
Installing Control Centre

Before we start, I am assuming you already have docker installed and set up on your system. If not, install it before continuing.

Hate to start this off with a caveat but according to the official docs, you have to make sure you have set a hostname/IP in your host file. Control Center will not function correctly if the hostname is mapped to the loopback adapter IP: Once you've address this you are ready to start with the below:

$>sudo apt-key adv --keyserver --recv-keys AA5A1AD7
$>sudo sh -c 'echo "deb [ arch=amd64 ] trusty universe" \
    > /etc/apt/sources.list.d/zenoss.list'
$>sudo apt-get update
$>sudo apt-get install serviced           

Once you let that complete you should be able to start it up:

$>sudo start serviced

Control Center's GUI is accessible over https thus upon starting serviecd the webserver binds to port 443. Make sure you don't already have a daemon bound to this port or you will see start up errors in the logs /var/log/upstart/serviced.log.

Deploy an application to Control Center

Before showing you how to deploy an application in Control Center, lets first cover some theory. So firstly Control Center provides a layer of abstraction from Docker. There is no need to write Dockerfiles for your containers. Instead you provide are template files, that are in JSON format, to instruct Control Center. It is beneficial to also note that Control Center refers to containers as applications, we will use this terminology going forwards to avoid confusion.

Now lets look at and example Control Center application. I have taken uploaded an example called webserver.json. There is alot of configuration options in the template. I will covered the options we are using.

 2/ "ID": "",
 3/ "Name": "Python-Web-Server",
 4/ "Description": "Python Web Server",

The first couple of lines just define some metadata. This can be whatever you want. Here we have decided not to give an ID, in which case and automatic one is given. An appropriate description is given along with the name.

5/   "Services": [
6/ {
7/   "Name": "Python Web Server",
8/   "Command": "",
9/   "Description": "Python Web Server",
10/   "Tags": null,
11/   "ImageID": "",
12/   "Instances": {
13/     "Min": 0,
14/     "Max": 0
15/   },
16/   "ChangeOptions": null,
17/   "Launch": "auto",
18/   "HostPolicy": "",
19/   "Hostname": "",
20/   "Privileged": false,
21/   "ConfigFiles": {},
22/   "Context": null,
23/   "Endpoints": null,
24/   "Services": [

The "Services" definition accepts and array of objects and allows you to specify a hierarchy to your application. What we are doing here is creating a set of resources underneath the Python-Web-Server application. You can think of the Python-Web-Server application being a group that has a "Python Web Server" service within in. The config following on is pretty self explanatory, the ones to point out are;

  • "Instances": Its possible to have multiple instances of a service, for example multiple nginx web service.
  • "Launch": Specify whether the service starts automatically, manually etc.
  • "Hostname": Hostname of the container spawned by Control Center.

Following on from the other Services directive we have the bulk of configuration:

25/     {
26/       "Name": "python",
27/       "Command": "/usr/local/bin/python /data/ -p 8000 -l /var/log/webserver.log",
28/       "Description": "",
29/       "Tags": [
30/         "daemon"
31/       ],
32/       "ImageID": "python:2.7.11",
33/       "Instances": {
34/         "Min": 1,
35/         "Max": 0
36/       },

We start off by giving a name to the docker image, and give the image a command to run in the container. Notice we feed in a file, we will see how the container knows about this later.
On line 32 we give the imageID of the docker base image we want to use. I am using the 2.7.11 release of the python image found on dockerhub. By specifying a min of 1 instance ensures there is always at least one container running for this service.
So remember the we spoke about. The next couple of lines down we actually define this file.

42/       "ConfigFiles": {
43/         "/data/": {
44/           "Filename": "/data/",
45/           "Owner": "root",
46/           "Permissions": "",
47/           "Content": 
48/         }
49/       }

Note the content directive is where you specify the actual file content. This will need to be provided as one line in the json template, so make sure you use the ascii characters for new lines etc.

51/       "Endpoints": [
52/         {
53/           "Name": "http",
54/           "Purpose": "export",
55/           "Protocol": "tcp",
56/           "PortNumber": 8000,
57/           "PortTemplate": "",
58/           "VirtualAddress": "",
59/           "Application": "http",
60/           "ApplicationTemplate": "",
61/           "AddressConfig": {
62/             "Port": 8000,
63/             "Protocol": "tcp"
64/           },
65/           "VHosts": [
66/             "web"
67/           ]
68/         }
69/       ]

The Endpoints directive allows you to sort out the networking mapping between your host and your container. The above snippet is exposing container port via the "PortNumber" and making it accessible via host port 8000, as can be seen from the "AddressConfig" object. The vhost object tells control center to expose an endpoint over a vhost name so you don't have to use the ip address, here we just gave the name "web".

Other important sections to note:

74/      "LogConfigs": [
75/         {
76/           "Path": "/var/log/webserver.log",
77/           "Type": "apache",
78/           "Filters": null,
79/           "LogTags": null
80/         }
81/       ],

The "LogConfig" directive allows your to provide the location of the logs we're interested within the container.

117/       "RAMCommitment": 1073741824,
118/       "CPUCommitment": 2,

"RAMCommitment" directive below specific how much RAM in bytes the container takes from the host."CPUCommitment" dedicates CPU cores from the host.

Right so we need to add this template into Control Center. Take the webserver.json template and do:

# add template to serviced
$>serviced template add webserver.json

# then deploy the template into Control Center
$>serviced template deploy <template_id>

Once the template is deployed you should be able to see the service in Control Center. You can run the service via:

$>serviced service start <serviced_id>

Once the service is up an running you can access the python web server via https://web. < hostname >


Control Center allows you to design your systems with service oriented architecture in mind. I hope this post provides you with a jump start into Control Center and how it can be used to manage and run your container based services.