Peter at Project Calico has already described some of the cool things that Calico can do to link Virtual Machines and Docker Containers using Software-Defined Networking. Here I want to show how some of the new features in Clocker can use Calico to orchestrate the deployment of applications that span both platforms. To make this work, we will need the latest version of Clocker, which is the 1.0.0 technology preview, currently available for testing.
There are several new and updated features in this release. The major points are listed below, but we will concentrate on how to link OpenStack Virtual Machines and Docker Containers in this post.
- The ability to start Calico with an external etcd cluster, using local proxies on each Docker host.
- Support for Swarm as the entry point for the cluster of Docker hosts.
- An OpenStack aware virtual network entity for mixed-infrastructure applications.
- Configurable setting to switch off
sshdinstallation and use
docker execinstead of
- Change from Ubuntu base image to use Alpine for faster container startup times.
OpenStack and Docker
Peter's blog post describes how to create an OpenStack cloud with the Calico driver for Neutron. Apache Brooklyn can be configured to deploy to a
JcloudsLocation defined using the
jclouds:openstack-nova provider. By saving the connection details in the
brooklyn.properties it can be referenced in a blueprint by name, such as
my-openstack-cloud. To create a Calico based Docker Cloud that is linked to this OpenStack cloud we only need to make sure that Clocker deploys the correct version of the Calico Node software, and that they connect to the same etcd data store that Calico is using on the OpenStack compute nodes are using. We can do this by configuring the Calico nodes to use an
EtcdProxy entity that is connected to the correct remote URL. Here is the snippet of the YAML blueprint describing the SDN provider specification:
sdn.provider.spec: $brooklyn:entitySpec: type: brooklyn.networking.sdn.calico.CalicoNetwork brooklyn.config: calico.version: 0.4.8 etcd.version: 2.0.11 sdn.network.cidr: 18.104.22.168/16 sdn.network.size: 24 etcd.node.spec: $brooklyn:entitySpec: type: brooklyn.entity.nosql.etcd.EtcdProxy brooklyn.config: etcd.cluster.name: "controller.example.org" etcd.cluster.url: "http://192.168.0.123:2380"
Once we have our Calico Docker and OpenStack Cloud running, we can deploy applications there, in the same way that we would deploy applications to a standalone Docker Cloud. These applications will consist of containers connected to Calico networks, and will only be able to connect to services running on Virtual Machines in the OpenStack cloud through the Internet. For private communication between VMs and Containers to take place on a Calico network, we must write a blueprint that describes this. Calico connects containers together by adding them to a profile on Docker. Calico also create profiles on OpenStack when a security group is created, so we must ensure that our application has a way to link the security group name used on OpenStack to the profile name needed on Docker. We do this with a new
VirtualNetwork sub-class which creates a new security group in OpenStack. The UUID of this new security group is then used by Calico as a profile name for Docker Containers.
We have created a simple demo application to illustrate linking Docker and OpenStack with Calico. This consists of a Riak cluster running on Virtual Machines in OpenStack, and a cluster of Node.js applications, fronted by an HAProxy load balancer, all running in Docker Containers. The Clocker blueprint for this application needs to describe the OpenStack location where we will create a
RiakCluster entity with several
RiakNode children. These will use VMs in a security group, created by the
OpenStackVirtualNetwork entity. Finally, we will create a
ControlledDynamicWebAppCluster which is a load-balanced group of web services, each of which will be a
NodeJsWebAppService running some client code that access Riak to update a simple counter and display it on a web page.
The complete YAML blueprint is shown below, and the application can be found at csabapalfi/riak-counters-example.
id: riak-nodejs-demo name: "Riak and Node.js Demo Application" services: - type: brooklyn.networking.OpenStackVirtualNetwork location: my-openstack-cloud networkId: data cidr: 22.214.171.124/24 - type: brooklyn.entity.nosql.riak.RiakCluster location: my-openstack-cloud initialSize: 3 id: cluster brooklyn.config: install.version: 2.0.5 provisioning.properties: minRam: 7g minCores: 8 securityGroup: data - type: brooklyn.entity.webapp.ControlledDynamicWebAppCluster location: my-docker-cloud name: Web Cluster brooklyn.config: initialSize: 2 dynamiccluster.memberspec: $brooklyn:entitySpec: type: brooklyn.entity.webapp.nodejs.NodeJsWebAppService brooklyn.config: appName: riak-counters-example gitRepoUrl: "https://github.com/csabapalfi/riak-counters-example" appFileName: index.js docker.openPorts: - 3000 shell.env: RIAK_NODES: > $brooklyn:component("cluster") .attributeWhenReady("riak.cluster.nodeListPbPort") network.list: - data - web controlleddynamicwebappcluster.controllerSpec: $brooklyn:entitySpec: type: brooklyn.entity.proxy.haproxy.HAProxyController brooklyn.config: docker.image.name: haproxy docker.image.tag: 1.5.9 install.dir: "/usr/local/sbin/" run.dir: "/usr/local/etc/haproxy/" network.list: - web
There are a few things to note about this blueprint. Firstly, the
OpenStackVirtualNetwork is created with the name data, and this network is used by both the
RiakNode and the
NodeJsWebAppService entities. The second network refernced is named web and is also used by the Node.js entities, as well as the
HAProxyController which is acting as a load balancer. The second network will be created by Clocker automatically, without the need for any explicit entity definition, using its default settings and will be used only with Docker Containers. The specification for the controller entity for the web cluster uses a Brooklyn entity, the
HAProxyController, but Clocker can simply use a pre-existing image from Docker Hub (in this case haproxy:1.5.9) and will reconfigure it appropriately when new web services are added to the controlled group. A similar method could have been used with the Node.js entity, if desired, and in many cases when a blueprint will only be used in a Clocker context this is desirable.
The running application displays a counter and a unique identifier for each Node.js server connected. The number of these services can be increased either automatically with a Brooklyn policy when scaling criteria are met, or manually by invoking the resize effector on the cluster. To learn more about how to write and run Brooklyn and Clocker blueprints, look at the this introduction or more in-depth documentation about creating YAML.
Clocker is available on GitHub under the Apache 2.0 license. You can provide feedback with any comments or problems on the incubator-brooklyn-dev mailing list, or add issues to the GitHub repository. If you have an idea for an improvement or a new feature, just fork the code and issue a pull request! See the Trello board for the current roadmap and task list.