tag:blogger.com,1999:blog-198798222024-03-17T20:01:31.400-07:00Sebastien GoasguenI am trying bitcoin :) need a little donation: 18Wbz8mRkCd84mFud9QKn8HKJzVbxSYvWySebastien Goasguenhttp://www.blogger.com/profile/05197845236510805309noreply@blogger.comBlogger55125tag:blogger.com,1999:blog-19879822.post-58151703313573078312015-09-16T05:24:00.001-07:002016-02-26T01:00:45.560-08:00Running Kubernetes on a Raspberry PI<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3gWPx9re5vB20Dw-DHS5hVwma4D9EbW_lNOVDV4rR1NN5raAVl2wLnThgplblrcLipyowaCARSG1LuOEyGmgKQrTENu0eL9ltW2MRPZmGVWh0UHYxL8MvHkO3YOhjys2M5iN51w/s1600/dockbercover.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3gWPx9re5vB20Dw-DHS5hVwma4D9EbW_lNOVDV4rR1NN5raAVl2wLnThgplblrcLipyowaCARSG1LuOEyGmgKQrTENu0eL9ltW2MRPZmGVWh0UHYxL8MvHkO3YOhjys2M5iN51w/s320/dockbercover.png" /></a></div>
Running the Docker engine on Raspberry Pi is a breeze thanks to the Docker <em>pirates</em> from <a href="http://blog.hypriot.com/">Hypriot</a>, just download the image and flash it on your Pi and you are off to the races. I am not going to cover this installation process, it is well documented on the Hypriot <a href="http://blog.hypriot.com/getting-started-with-docker-on-your-arm-device/">website</a> and I also wrote a recipe in the <a href="http://shop.oreilly.com/product/0636920036791.do">Docker cookbook</a>. Roughly, download the .img file and dd it to your SD card, then boot your PI.<br />
Having Docker on Raspberry Pi offers tons of possibilities for hobbyist and home devices. It also triggered my interest because <a href="http://kubernetes.io/">Kubernetes</a>, one of the Docker orchestrators, can be run standalone on a single node using <a href="https://github.com/kubernetes/kubernetes/blob/master/docs/getting-started-guides/docker.md">Docker containers</a>. I wrote a <a href="http://sebgoa.blogspot.ch/2015/04/1-command-to-kubernetes-with-docker.html">post</a> several months ago about doing it using docker-compose. So I decided to give it a try last week-end, running Kubernetes on a PI using the Hypriot image that has the Docker engine.<br />
<h2 id="getting-etcd-to-run">
Getting <code>etcd</code> to run</h2>
The first issue is that Kubernetes currently uses <a href="https://github.com/coreos/etcd">etcd</a>, and that you need to run it on ARM. I decided to get the <code>etcd</code> source directly on the PI and updated the Dockerfile to build it directly there. Etcd uses a Golang ONBUILD image and it was causing me grief. So I copied the content of the ONBUILD image and created a new Dockerfile based on <code>hypriot/rpi-golang</code> to build it directly. You can see the <a href="https://github.com/how2kube/k8s4pi/blob/master/Dockerfile.etcd">Dockerfile</a>. With that you have a Docker container running etcd on ARM.<br />
<h2 id="getting-the-hyperkube-to-run-on-arm">
Getting the Hyperkube to run on ARM</h2>
Now, I needed the hyperkube binary to run on ARM. Hyperkube is a single binary that allows you to start all the Kubernetes components. Thankfully there are some <a href="https://github.com/andrewpsuedonym/Kubernetes-Arm-Binaries.git">binaries already available for ARM</a>. That was handy because I struggled to compile Kubernetes directly on the PI.<br />
With that hyperkube binary on hand, I built an image based on the <code>resin/rpi-raspbian:wheezy</code> image. Quite straightforward:<br />
<pre><code>FROM resin/rpi-raspbian:wheezy
RUN apt-get update
RUN apt-get -yy -q install iptables ca-certificates
COPY hyperkube /hyperkube</code></pre>
<h2 id="the-kubelet-systemd-unit">
The Kubelet systemd unit</h2>
The Kubernetes agent running on all nodes in a cluster is called the Kubelet. The Kubelet is in charge of making sure that all containers supposed to be running on the node actually do run. It can also be used with a manifest to start some specific containers at startup. There is a <a href="https://coreos.com/blog/introducing-the-kubelet-in-coreos/">good post</a> from Kelsey Hightower about it. Since The Hypriot image uses systemd I took the systemd unit that creates a Kubelet service directly from Kelsey's post:<br />
<pre><code>[Unit]
Description=Kubernetes Kubelet
Documentation=https://github.com/kubernetes/kubernetes
[Service]
ExecStart=/usr/bin/kubelet \
--api-servers=http://127.0.0.1:8080 \
--allow-privileged=true \
--config=/etc/kubernetes/manifests \
--v=2
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target</code></pre>
The <em>kubelet</em> binary is downloaded directly from the same <a href="https://github.com/andrewpsuedonym/Kubernetes-Arm-Binaries.git">location</a> as hyperkube. The manifest is a Kubernetes Pod definition that starts all the containers to get a Kubernetes controller running. It starts <code>etcd</code>, the API server, the scheduler, the controller and the service proxy, all using the hyperkube image built above.<br />
<h2 id="now-the-dirty-hack">
Now the dirty hack</h2>
Kubernetes does something interesting. All containers in a Pod actually use the same IP address. This is done by running a <em>fake</em> container that just does nothing. The other containers in the Pod just share the same network namespace as this <em>fake</em> container. This is actually called the <em>pause</em> container. I did not find a way to specify a different image for the <em>pause</em> container in Kubernetes, it seems hard coded to <code>gcr.io/google_containers/pause:0.8.0</code> which off course is supposed to run on x86_64.<br />
So the dirty trick consisted in taking the <em>pause</em> Goland code from the Kubernetes source, compiling it on the PI using the <code>hypriot/rpi-golang</code> and sticking the binary in a SCRATCH image and tagging it locally to appear as <code>gcr.io/google_containers/pause:0.8.0</code> and avoid the download of the real image that runs on x86_64. Yeah...right...I told you dirty but that was the quickest way I could think of.<br />
<h2 id="putting-it-all-together">
Putting it all together</h2>
Now that you have all the images ready directly on the PI, plus a Kubelet service, you can start it. The containers will be created and you will have a single node Kubernetes cluster on the PI. All is left is to use the <em>kubectl</em> CLI to use it. You can download an ARM <a href="https://storage.googleapis.com/kubernetes-release/release/v1.0.3/bin/linux/arm/kubectl">version</a> of Kubectl form the official Kubernetes release.<br />
<pre><code>HypriotOS: root@black-pearl in ~
$ docker images
REPOSITORY TAG
hyperkube latest
gcr.io/google_containers/pause 0.8.0
etcd latest
resin/rpi-raspbian wheezy
hypriot/rpi-golang latest
HypriotOS: root@black-pearl in ~
$ ./kubectl get pods
NAME READY STATUS RESTARTS AGE
kube-controller-black-pearl 5/5 Running 5 5m
HypriotOS: root@black-pearl in ~
$ ./kubectl get nodes
NAME LABELS STATUS
black-pearl kubernetes.io/hostname=black-pearl Ready</code></pre>
<h2 id="get-it">
Get it</h2>
Everything is on <a href="https://github.com/skippbox/k8s4pi" target="_blank">GitHub</a> at <code>https://github.com/skippbox/k8s4pi</code> including a horrible bash script that does the entire build :)Sebastien Goasguenhttp://www.blogger.com/profile/05197845236510805309noreply@blogger.com12tag:blogger.com,1999:blog-19879822.post-85140899256416373792015-06-15T05:44:00.001-07:002015-06-15T05:44:52.708-07:00Introducing Kmachine, a Docker machine fork for Kubernetes.<p><a href="https://github.com/docker/machine">Docker machine</a> is a great tool to easily start a Docker host on most public Cloud providers out there. Very handy as a replacement to Vagrant if all you want is a Docker host in the Cloud.</p>
<p>It automatically installs the Docker daemon and sets up the TLS authentication so that you can communicate with it using your local Docker client. It also has some early features to start a Swarm cluster (i.e Multiple Docker hosts).</p>
<p>Since I have been playing with <a href="http://kubernetes.io">Kubernetes</a> lately, and that there is a single node install <a href="https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/getting-started-guides/docker.md">available</a>, all based on Docker images...</p>
<p>I thought, let's hack Docker machine a bit so that in addition to installing the docker daemon it also pulls a few images and starts a few containers on boot.</p>
<div class="separator" style="clear: both; text-align: center;"><a href="http://shop.oreilly.com/product/0636920036791.do" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhziwkWBl0HWITMH0bzjKoMxVs36oTs1kci_XJBN-CufLARVnTqC4_VCFq6NL0_nsn_D0ZL11ZmnA_dNrOmuQi3PCEB_ru0Ww6Fz50NF_yMU8ZUwSwhVwoYfPIpHXi1N_uAMXyJLQ/s400/rc_cat.gif" /></a></div>
<p>The result is <a href="https://github.com/runseb/machine">kmachine</a>. The usage is exactly the same as Docker machine. It goes something like this on <a href="http://exoscale.ch">exoscale</a> (did not take time to open 6443 on all providers...PR :)):</p>
<pre><code>$ kmachine create -d exoscale foobar
$ kmachine env foobar
kubectl config set-cluster kmachine --server=https://185.19.29.23:6443 --insecure-skip-tls-verify=true
kubectl config set-credentials kuser --token=abcdefghijkl
kubectl config set-context kmachine --user=kuser --cluster=kmachine
kubectl config use-context kmachine
export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://185.19.29.23:2376"
export DOCKER_CERT_PATH="/Users/sebastiengoasguen/.docker/machine/machines/foobar5"
export DOCKER_MACHINE_NAME="foobar5"
# Run this command to configure your shell:
# eval "$(kmachine_darwin-amd64 env foobar5)"</code></pre>
<p>You see that I used <em>kubectl</em>, the Kubernetes <a href="https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/getting-started-guides/aws/kubectl.md">client</a> to automatically setup the endpoint created by machine. The only gotcha right now is that I hard coded the token...Easily fixed by a friendly PR. We could also setup proper certificates and TLS authentication. But I opted for the easy route for now. If you setup your env. You will have access to Kubernetes, and Docker of course, the original docker-machine functionality is not broken.</p>
<pre><code>$ eval "$(kmachine env foobar)"
$ kubectl get pods
POD IP CONTAINER(S) IMAGE(S)
kubernetes-127.0.0.1 controller-manager gcr.io/google_containers/hyperkube:v0.17.0
apiserver gcr.io/google_containers/hyperkube:v0.17.0
scheduler gcr.io/google_containers/hyperkube:v0.17.0
$ kubectl get nodes
NAME LABELS STATUS
127.0.0.1 Schedulable <none> Ready</code></pre>
<p>Since all Kubernetes components are started as containers, you will see all of them running from the start. <em>etcd</em>, the <em>kubelet</em>, the <em>controller</em>, <em>proxy</em> etc.</p>
<pre><code>$ docker ps
CONTAINER ID IMAGE COMMAND
7e5d356d31d7 gcr.io/google_containers/hyperkube:v0.17.0 "/hyperkube controll
9cc05adf2b27 gcr.io/google_containers/hyperkube:v0.17.0 "/hyperkube schedule
7a0e490a44e1 gcr.io/google_containers/hyperkube:v0.17.0 "/hyperkube apiserve
6d2d743172c6 gcr.io/google_containers/pause:0.8.0 "/pause"
7950a0d14608 gcr.io/google_containers/hyperkube:v0.17.0 "/hyperkube proxy --
55fc22c508a9 gcr.io/google_containers/hyperkube:v0.17.0 "/hyperkube kubelet
c67496a47bf3 kubernetes/etcd:2.0.5.1 "/usr/local/bin/etcd </code></pre>
<p>Have fun ! I think it is very handy to get started with Kubernetes and still have the Docker machine setup working. You get the benefit of both, easy provisioning of a Docker host in the Cloud and a fully working Kubernetes setup to experience with. If we could couple it with Weave of Flannel, we could setup a full Kubernetes cluster in the Cloud, just like Swarm.</p>Sebastien Goasguenhttp://www.blogger.com/profile/05197845236510805309noreply@blogger.com4tag:blogger.com,1999:blog-19879822.post-43877518703206654642015-06-09T04:36:00.001-07:002015-06-09T08:47:25.775-07:00Building an S3 object store with Docker, Cassandra and Kubernetes<p>Docker makes building distributed applications relatively painless. At the very least deploying existing distributed systems/framework is made easier since you only need to launch containers. <a href="https://hub.docker.com">Docker hub</a> is full of MongoDB, Elasticsearch, Cassandra images etc ... Assuming that you like what is inside those images, you can just grab them and run a container and you are done.</p>
<p>With a cluster manager/container orchestration system like Kubernetes, running clustered version of these systems where you need to operate multiple containers and multiple nodes is also made dead simple. Swear to God, it is !</p>
<p>Just check the list of <a href="https://github.com/GoogleCloudPlatform/kubernetes/tree/master/examples">examples</a> and you will find everything that is needed to run a Redis, a Spark, a Storm, an Hazelcast even a Glusterfs cluster. Discovery of all the nodes can be a challenge but with things like Etcd, Consul, registrator, service discovery has never been easier.</p>
<p>What caught my eye in the list of Kubernetes examples is the ability to run an Apache <a href="https://github.com/GoogleCloudPlatform/kubernetes/tree/master/examples/cassandra">Cassandra cluster</a>. Yes, a Cassandra cluster based on Docker containers. It caught my eye especially that my buddies at <a href="https://exoscale.ch">exoscale</a> have written an S3 compatible object store that uses Cassandra for storage. It's called <a href="https://github.com/exoscale/pithos">Pithos</a> and for those interested is written in Clojure.</p>
<p>So I wondered, let's run Cassandra in Kubernetes, then let's create a Docker image for Pithos and run it in Kubernetes as well. That should give me a S3 compatible object store, built using Docker containers.</p>
<p>To start we need a Kubernetes cluster. The easiest is to use Google container <a href="https://cloud.google.com/container-engine/">engine</a>. But keep an eye on <a href="https://github.com/kelseyhightower/kubestack">Kubestack</a> which is a Terraform plan to create one. It could easily be adapted for different cloud providers. If you are new to Kubernetes check my previous <a href="http://sebgoa.blogspot.ch/2015/04/1-command-to-kubernetes-with-docker.html">post</a>, or get the <a href="http://shop.oreilly.com/product/0636920036791.do">Docker cookbook</a> in early release I just pushed a chapter on Kubernetes. Whatever technique you use, before proceeding you should be able to use the <em>kubectl</em> client and list the nodes in your cluster. For example:</p>
<pre><code>$ ./kubectl get nodes
NAME LABELS STATUS
k8s-cookbook-935a6530-node-hsdb kubernetes.io/hostname=k8s-cookbook-935a6530-node-hsdb Ready
k8s-cookbook-935a6530-node-mukh kubernetes.io/hostname=k8s-cookbook-935a6530-node-mukh Ready
k8s-cookbook-935a6530-node-t9p8 kubernetes.io/hostname=k8s-cookbook-935a6530-node-t9p8 Ready
k8s-cookbook-935a6530-node-ugp4 kubernetes.io/hostname=k8s-cookbook-935a6530-node-ugp4 Ready</code></pre>
<h2 id="running-cassandra-in-kubernetes">Running Cassandra in Kubernetes</h2>
<p>You can use the Kubernetes example straight up or clone my own repo, you can explore all the pods, replication controllers and service definition there:</p>
<pre><code>$ git clone https://github.com/how2dock/dockbook.git
$ cd ch05/examples</code></pre>
<p>Then launch the Cassandra replication controller, increase the number of replicas and launch the service:</p>
<pre><code>$ kubectl create -f ./cassandra/cassandra-controller.yaml
$ kubectl scale --replicas=4 rc cassandra
$ kubectl create -f ./cassandra/cassandra-service.yaml</code></pre>
<p>Once the image is downloaded you will have your Kubernetes pods in running state. Note that the image currently used comes from the Google registry. That's because this image contains a Discovery class specified in the Cassandra configuration. You could use the Cassandra image from Docker hub but would have to put that Java class in there to allow all cassandra nodes to discover each other. As I said, almost painless !</p>
<pre><code>$ kubectl get pods --selector="name=cassandra"</code></pre>
<p>Once Cassandra discovers all nodes and rebalances the database storage you will get something like:</p>
<pre><code>$ ./kubectl exec cassandra-5f709 -c cassandra nodetool status
Datacenter: datacenter1
=======================
Status=Up/Down
|/ State=Normal/Leaving/Joining/Moving
-- Address Load Tokens Owns (effective) Host ID Rack
UN 10.16.2.4 84.32 KB 256 46.0% 8a0c8663-074f-4987-b5db-8b5ff10d9774 rack1
UN 10.16.1.3 67.81 KB 256 53.7% 784c8f4d-7722-4d16-9fc4-3fee0569ec29 rack1
UN 10.16.0.3 51.37 KB 256 49.7% 2f551b3e-9314-4f12-affc-673409e0d434 rack1
UN 10.16.3.3 65.67 KB 256 50.6% a746b8b3-984f-4b1e-91e0-cc0ea917773b rack1</code></pre>
<p>Note that you can also access the logs of a container in a pod with <em>kubectl logs</em> very handy.</p>
<h2 id="launching-pithos-s3-object-store">Launching Pithos S3 object store</h2>
<p><a href="http://pithos.io">Pithos</a> is a daemon which "provides an S3 compatible frontend to a cassandra cluster". So if we run Pithos in our Kubernetes cluster and point it to our running Cassandra cluster we can expose an S3 compatible interface.</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBxkrwVvEu5XwMqmGvek0CsWedst6eZg2mFjzbA6YdSSYo_ZRfNnYGKkRaujtwOX3irsXr_XFwHG211BMef_n3lemZcwnzDZR2DHOjcnBsyDg9JQqaIPvCXdeLBRG3cyo6c8INsw/s1600/s3pithos.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBxkrwVvEu5XwMqmGvek0CsWedst6eZg2mFjzbA6YdSSYo_ZRfNnYGKkRaujtwOX3irsXr_XFwHG211BMef_n3lemZcwnzDZR2DHOjcnBsyDg9JQqaIPvCXdeLBRG3cyo6c8INsw/s400/s3pithos.png" /></a></div>
<p>To that end I created a Docker image for Pithos <em>runseb/pithos</em> on Docker hub. Its an automated build so you can check out the Dockerfile there. The image contains the default configuration file. You will want to change it to edit your access keys and bucket stores definitions. I launch Pithos as a Kubernetes replication controller and expose a service with an external load balancer created on Google compute engine. The Cassandra service that we launched earlier allows Pithos to find Cassandra using DNS resolution. To bootstrap pithos we need to run a non-restarting Pod which installs the Pithos schema in Cassandra. Let's do it:</p>
<pre><code>$ kubectl create -f ./pithos/pithos-bootstrap.yaml</code></pre>
<p>Wait for the bootstrap to happen, i.e for the Pod to get in <em>succeed</em> state. Then launch the replication controller. For now we will launch only one replicas. Using an rc makes it easy to attach a service and expose it via a Public IP address.</p>
<pre><code>$ kubectl create -f ./pithos/pithos-rc.yaml
$ kubectl create -f ./pithos/spithos.yaml
$ ./kubectl get services --selector="name=pithos"
NAME LABELS SELECTOR IP(S) PORT(S)
pithos name=pithos name=pithos 10.19.251.29 8080/TCP
104.197.27.250 </code></pre>
<p>Since Pithos will serve on port 8080 by default, make sure that you open the firewall for public IP of the load-balancer.</p>
<h2 id="use-an-s3-client">Use an S3 client</h2>
<p>You are now ready to use your S3 object store, offered by Pithos, backed by Cassandra, running on Kubernetes using Docker. Wow...a mouth full !!!</p>
<p>Install <a href="http://s3tools.org/s3cmd">s3cmd</a> and create a configuration file like so:</p>
<pre><code>$ cat ~/.s3cfg
[default]
access_key = AKIAIOSFODNN7EXAMPLE
secret_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
check_ssl_certificate = False
enable_multipart = True
encoding = UTF-8
encrypt = False
host_base = s3.example.com
host_bucket = %(bucket)s.s3.example.com
proxy_host = 104.197.27.250
proxy_port = 8080
server_side_encryption = True
signature_v2 = True
use_https = False
verbosity = WARNING</code></pre>
<p>Note that we use an unencrypted proxy (the load-balancer IP created by the Pithos Kubernetes service, don't forget to change it). The access and secret keys are the default stored in the <a href="https://github.com/runseb/pithos">Dockerfile</a></p>
<p>With this configuration in place, you are ready to use +s3cmd+:</p>
<pre><code>$ s3cmd mb s3://foobar
Bucket 's3://foobar/' created
$ s3cmd ls
2015-06-09 11:19 s3://foobar</code></pre>
<p>If you wanted to use Boto, this would work as well:</p>
<pre><code>#!/usr/bin/env python
from boto.s3.key import Key
from boto.s3.connection import S3Connection
from boto.s3.connection import OrdinaryCallingFormat
apikey='AKIAIOSFODNN7EXAMPLE'
secretkey='wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY'
cf=OrdinaryCallingFormat()
conn=S3Connection(aws_access_key_id=apikey,
aws_secret_access_key=secretkey,
is_secure=False,host='104.197.27.250',
port=8080,
calling_format=cf)
conn.create_bucket('foobar')</code></pre>
<p>And that's it. All of these steps make sound like a lot, but honestly it has never been that easy to run an S3 object store. Docker and Kubernetes truly make running distributed applications a breeze.</p>
Sebastien Goasguenhttp://www.blogger.com/profile/05197845236510805309noreply@blogger.com1tag:blogger.com,1999:blog-19879822.post-50791900828396434662015-05-04T09:49:00.001-07:002015-05-04T09:49:01.226-07:00Running VMs in Docker Containers via Kubernetes<p>Couple weeks ago Google finally published a technical <a href="https://research.google.com/pubs/pub43438.html">paper</a> describing Borg, their cluster management system that they built over the last ten years or more and that runs all Google services.</p>
<p>There are several interesting concepts in the paper, one of them of course being that they run everything in containers. Whether they use Docker or not is unknown. Some parts of their workloads probably still use <a href="https://github.com/google/lmctfy">LMCTFY</a>, - Let Me Contain That For You-. What struck me is that they say to not be using full virtualization. It makes sense in terms of timeline, considering that Borg started before the advent of hardware virtualization. However, their Google Compute Engine offers VM as a Service, so it is fair to wonder how they are running their VMs. This reminded me of John Wilkes <a href="https://www.youtube.com/watch?v=VQAAkO5B5Hg">talk</a> at MesosCon 2014. He discussed scheduling in Borg (without mentioning it) and at 23 minutes in his talk, mentions that they run VMs in containers.</p>
<p>Running VM in containers does make sense when you think in terms of a cluster management system that deals with multiple type of workloads. You treat your IaaS (e.g GCE) as a workload, and contain it so that you can pack all your servers and maximize utilization. It also allows you to run some workloads on bare-metal for performance.</p>
<p>Therefore let's assume that GCE is just another workload for Google and that it runs through Borg.</p>
<p>Since Borg laid out the principles for <a href="https://github.com/GoogleCloudPlatform/kubernetes">Kubernetes</a>, the cluster management system designed for containerized workloads and open sourced by Google in June 2014. You are left asking:</p>
<p>"How can we run VMs in Kubernetes ?"</p>
<p>This is where Rancher comes to our help to help us prototype a little some-some. Two weeks ago, Rancher announced <a href="http://rancher.com/introducing-ranchervm-package-and-run-virtual-machines-as-docker-containers/">RancherVM</a>, basically a startup script that creates KVM VMs inside Docker containers (not really doing it justice calling it a script...). It is available on <a href="https://github.com/rancherio/vm">GitHub</a> and super easy to try. I will spare you the details and tell you to go to GitHub instead. The result is that you can build a Docker image that contains a KVM qcow image, and that running the container starts the VM with the proper networking.</p>
<h2 id="privilege-gotcha">Privilege gotcha</h2>
<p>With a Docker image now handy to run a KVM instance in it, using Kubernetes to start this container is straightforward. Create a Pod that launches this container. The only caveat is that the Docker host(s) that you use and that form your Kubernetes cluster need to have KVM installed and that your containers will need to have some level of privileges to access the KVM devices. While this can be tweaked with Docker run parameters like --device and --cap-add, you can brute force it in a very unsecure manner with --privilege. However Kubernetes does not accept to run privileged containers by default (rightfully so). Therefore you need to start you Kubernetes cluster (i.e API server and Kubelet with the --allow_privilege=true option).</p>
<p>If you are new to Kubernetes, check out my previous <a href="http://sebgoa.blogspot.ch/2015/04/1-command-to-kubernetes-with-docker.html">post</a> where I show you how to start a one node Kubernetes "cluster" with Docker compose. The only modification that I did from that post, is that I am running this on a Docker host that also has KVM installed, that the compose manifest specifies --allow_pivileged=true in the kubelet startup command, and that I modify the /etc/kubernetes/manifests/master.json by specifiying a volume. This allows me not to tamper with the images from Google.</p>
<h2 id="lets-try-it-out">Let's try it out</h2>
<p>Build your RancherVM images:</p>
<pre><code>$ git clone https://github.com/rancherio/vm.git
$ cd vm
$ make all</code></pre>
<p>You will now have several RancherVM images:</p>
<pre><code>$ sudo docker images
REPOSITORY TAG ...
rancher/vm-android 4.4 ...
rancher/vm-android latest ...
rancher/ranchervm 0.0.1 ...
rancher/ranchervm latest ...
rancher/vm-centos 7.1 ...
rancher/vm-centos latest ...
rancher/vm-ubuntu 14.04 ...
rancher/vm-ubuntu latest ...
rancher/vm-rancheros 0.3.0 ...
rancher/vm-rancheros latest ...
rancher/vm-base 0.0.1 ...
rancher/vm-base latest ...</code></pre>
<p>Starting one of those will give you access to a KVM instance running in the container.</p>
<p>I will skip the startup of the Kubernetes components. Check my previous post. Once you have Kubernetes running you can list the pods (i.e group of containers/volumes). You will see that the Kubernetes master itself is running as a Pod.</p>
<pre><code>$ ./kubectl get pods
POD IP CONTAINER(S) IMAGE(S) ...
nginx-127 controller-manager gcr.io/google_containers/hyperkube:v0.14.1 ...
apiserver gcr.io/google_containers/hyperkube:v0.14.1
scheduler gcr.io/google_containers/hyperkube:v0.14.1</code></pre>
<p>Now let's define a RancherVM as a Kubernetes Pod. We do this in a YAML file</p>
<pre><code>apiVersion: v1beta2
kind: Pod
id: ranchervm
labels:
name: vm
desiredState:
manifest:
version: v1beta2
containers:
- name: master
image: rancher/vm-rancheros
privileged: true
volumeMounts:
- name: ranchervm
mountPath: /ranchervm
env:
- name: RANCHER_VM
value: "true"
volumes:
- name: ranchervm
source:
hostDir:
path: /tmp/ranchervm</code></pre>
<p>To create the Pod use the kubectl CLI:</p>
<pre><code>$ ./kubectl create -f vm.yaml
pods/ranchervm
$ ./kubectl get pods
POD IP CONTAINER(S) IMAGE(S) ....
nginx-127 controller-manager gcr.io/google_containers/hyperkube:v0.14.1 ....
apiserver gcr.io/google_containers/hyperkube:v0.14.1
scheduler gcr.io/google_containers/hyperkube:v0.14.1
ranchervm 172.17.0.10 master rancher/vm-rancheros ....</code></pre>
<p>The RancherVM image specified contains RancherOS. The container will start automatically but of course the actual VM will take couple more seconds to start. Once it's up, you can ping it and you can ssh to the VM instance.</p>
<pre><code>$ ping -c 1 172.17.0.10
PING 172.17.0.10 (172.17.0.10) 56(84) bytes of data.
64 bytes from 172.17.0.10: icmp_seq=1 ttl=64 time=0.725 ms
$ ssh rancher@172.17.0.10
...
[rancher@ranchervm ~]$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[rancher@ranchervm ~]$ sudo system-docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
229a22962a4d console:latest "/usr/sbin/entry.sh 2 minutes ago Up 2 minutes console
cfd06aa73192 userdocker:latest "/usr/sbin/entry.sh 2 minutes ago Up 2 minutes userdocker
448e03b18f93 udev:latest "/usr/sbin/entry.sh 2 minutes ago Up 2 minutes udev
ff929cddeda9 syslog:latest "/usr/sbin/entry.sh 2 minutes ago Up 2 minutes syslog </code></pre>
<p>Amazing ! I can feel that you are just wondering what the heck is going on:)</p>
<p>You want to kill the VM ? Just kill the pod:</p>
<pre><code>$ ./kubectl delete pod ranchervm</code></pre>
<p>Remember that a Pod is not a single container but could contain several ones as well as volumes.</p>
<p>Let's go a step further, and scale the number of VMs by using a replication controller.</p>
<h2 id="using-a-replication-controller-to-scale-the-vm">Using a Replication Controller to scale the VM</h2>
<p>Kubernetes is quite nice, it builds on years of experience with fault-tolerance at Google and provides mechanism for keeping your services up, scaling them and rolling new versions. The replication Controller is a primitive to manage the scale of your services.</p>
<p>So say you would like to automatically increase or decrease the number of VMs running in your datacenter. Start them with a replication controller. This is defined in a YAML manifest like so:</p>
<pre><code>id: ranchervm
kind: ReplicationController
apiVersion: v1beta2
desiredState:
replicas: 1
replicaSelector:
name: ranchervm
podTemplate:
desiredState:
manifest:
version: v1beta2
id: vm
containers:
- name: vm
image: rancher/vm-rancheros
privileged: true
volumeMounts:
- name: ranchervm
mountPath: /ranchervm
env:
- name: RANCHER_VM
value: "true"
volumes:
- name: ranchervm
source:
hostDir:
path: /tmp/ranchervm
labels:
name: ranchervm
</code></pre>
<p>This manifest defines a Pod template (the one that we created earlier), and set a number of replicas. Here we start with one. To launch it, use the kubectl binary again:</p>
<pre><code>$ ./kubectl create -f vmrc.yaml
replicationControllers/ranchervm
$ ./kubectl get rc
CONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLICAS
ranchervm vm rancher/vm-rancheros name=ranchervm 1</code></pre>
<p>If you list the pods, you will see that your container is running and hence your VM will start shortly.</p>
<pre><code>$ ./kubectl get pods
POD IP CONTAINER(S) IMAGE(S) ...
nginx-127 controller-manager gcr.io/google_containers/hyperkube:v0.14.1 ...
apiserver gcr.io/google_containers/hyperkube:v0.14.1
scheduler gcr.io/google_containers/hyperkube:v0.14.1
ranchervm-16ncs 172.17.0.11 vm rancher/vm-rancheros ...</code></pre>
<p>Why is this awesome ? Because you can scale easily:</p>
<pre><code>$ ./kubectl resize --replicas=2 rc ranchervm
resized</code></pre>
<p>And Boom, two VMs:</p>
<pre><code>$ ./kubectl get pods -l name=ranchervm
POD IP CONTAINER(S) IMAGE(S) ...
ranchervm-16ncs 172.17.0.11 vm rancher/vm-rancheros ...
ranchervm-279fu 172.17.0.12 vm rancher/vm-rancheros ...</code></pre>
<p>Now of course, this little test is done on one node. But if you had a real Kubernetes cluster, it would schedule these pods on available nodes. From a networking standpoint, RancherVM can provide DHCP service or not. That means that you could let Kubernetes assign the IP to the Pod and the VMs would be networked over the overlay in place.</p>
<p>Now imagine that we had security groups via an OVS switch on all nodes in the cluster...we could have multi-tenancy with network isolation and full VM isolation. While being able to run workloads in "traditional" containers. This has some significant impact on the current IaaS space, and even Mesos itself.</p>
<p>Your Cloud as a containerized distributed workload, anyone ???</p>
<p>For more recipes like these, checkout the Docker <a href="http://shop.oreilly.com/product/0636920036791.do">cookbook</a>.</p>
Sebastien Goasguenhttp://www.blogger.com/profile/05197845236510805309noreply@blogger.com4tag:blogger.com,1999:blog-19879822.post-13979693063691062962015-04-09T12:59:00.001-07:002015-06-19T02:20:57.106-07:001 command to Kubernetes with Docker compose<p>After <a href="http://sebgoa.blogspot.ch/2015/03/1-command-to-mesos-with-docker-compose.html">1 command to Mesos</a>, here is 1 command to Kubernetes.</p>
<p>I had not looked at <a href="http://kubernetes.io">Kubernetes</a> in over a month. It is a fast paced project so it is hard to keep up. If you have not looked at Kubernetes, it is <em>roughly</em> a cluster manager for containers. It takes a set of Docker hosts under management and schedules groups of containers in them. Kubernetes was open sourced by Google around June last year to bring all the Google knowledge of working with containers to us, a.k.a The people :) There are a lot of container schedulers or orchestrators if you wish out there, Citadel, Docker Swarm, Mesos with the Marathon framework, Cloud Foundry lattice etc. The Docker ecosystem is booming and our heads are spinning.</p>
<p>What I find very interesting with Kubernetes is the concept of <i>replication controllers</i>. Not only can you schedule groups of colocated containers together in a cluster, but you can also define replica sets. Say you have a container you want to scale up or down, you can define a replica controller and use it to resize the number of containers running. It is great for scaling when the load dictates it, but it is also great when you want to replace a container with a new image. Kubernetes also exposes a concept of <em>services</em> basically a way to expose a container application to all the hosts in your cluster as if it were running locally. Think the ambassador pattern of the early Docker days but on steroid.</p>
<p>All that said, you want to try Kubernetes. I know you do. So here is 1 command to try it out. We are going to use <a href="https://docs.docker.com/compose/">docker-compose</a> like we did with Mesos and thanks to this <a href="https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/getting-started-guides/docker.md">how-to</a> which seems to have landed 3 days ago, we are going to run Kubernetes on a single host with containers. That means that all the Kubernetes components (the "agent", the "master" and various controllers) will run in containers.</p>
<p>Install compose on your Docker host, if you do not have it yet:</p>
<pre><code>curl -L https://github.com/docker/compose/releases/download/1.2.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose</code></pre>
<p>Then create this YAML file, call it say k8s.yml:</p>
<pre><code>etcd:
image: kubernetes/etcd:2.0.5.1
net: "host"
command: /usr/local/bin/etcd --addr=127.0.0.1:4001 --bind-addr=0.0.0.0:4001 --data-dir=/var/etcd/data
master:
image: gcr.io/google_containers/hyperkube:v0.17.0
net: "host"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
command: /hyperkube kubelet --api_servers=http://localhost:8080 --v=2 --address=0.0.0.0 --enable_server --hostname_override=127.0.0.1 --config=/etc/kubernetes/manifests
proxy:
image: gcr.io/google_containers/hyperkube:v0.17.0
net: "host"
privileged: true
command: /hyperkube proxy --master=http://127.0.0.1:8080 --v=2
</code></pre>
<p>And now, 1 command:</p>
<pre><code>$ docker-compose -f k8s.yml up -d</code></pre>
<p>Quickly there after, you will see a bunch of containers pop-up:</p>
<pre><code>$ docker ps
CONTAINER ID IMAGE
a17cac87965b kubernetes/pause:go
659917e61d3e gcr.io/google_containers/hyperkube:v0.17.0
caf22057dbad gcr.io/google_containers/hyperkube:v0.17.0
288fcb4408c7 gcr.io/google_containers/hyperkube:v0.17.0
820cc546b352 kubernetes/pause:go
0bfac38bdd10 kubernetes/etcd:2.0.5.1
81f58059ca8d gcr.io/google_containers/hyperkube:v0.17.0
ca1590c1d5c4 gcr.io/google_containers/hyperkube:v0.17.0</code></pre>
<p>In the YAML file above, you see in the commands that it used a single binary hyperkube that allows you to start all the kubernetes components, the API server, the replication controller etc ... One of the components it started is the kubelet which is normally used to monitor containers on one of the host in your cluster and make sure they stay up. Here by passing the /etc/kubernetes/manifests it helped us start the other components of kubernetes defined in that manifest. Clever ! Note also that the containers where started with a host networking. So these containers have the network stack of the host, you will not see an interface on the docker bridge.</p>
<p>With all those up, grab the <a href="http://storage.googleapis.com/kubernetes-release/release/v0.14.1/bin/linux/amd64/kubectl">kubectl binary</a>, that is your kubernetes client that you will use to interact with the system. The first thing you can do is list the nodes:</p>
<pre><code>$ ./kubectl get nodes
NAME LABELS STATUS
127.0.0.1 <none> Ready</code></pre>
<p>Now start your first container:</p>
<pre><code>./kubectl run-container nginx --image=nginx --port=80</code></pre>
<p>That's a simple example, where you can actually start a single container. You will want to group your containers that need to be colocated and write a POD description in YAML or json than pass that to kubectl. But it looks like they extended kubectl to take single container start up. That's handy for testing.</p>
<p>Now list your pods:</p>
<pre><code>$ ./kubectl get pods
POD IP CONTAINER(S) IMAGE(S)
k8s-master-127.0.0.1 controller-manager gcr.io/google_containers/hyperkube:v0.14.1
apiserver gcr.io/google_containers/hyperkube:v0.14.1
scheduler gcr.io/google_containers/hyperkube:v0.14.1
nginx-p2sq7 172.17.0.4 nginx nginx </code></pre>
<p>You see that there is actually two pods running. The nginx one that you just started and one pod made of three containers. That's the pod that was started by your kubelet to get Kubernetes up. Kubernetes managed by Kubernetes...</p>
<p>It automatically created a replication controller (rc):</p>
<pre><code>$ ./kubectl get rc
CONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLICAS
nginx nginx nginx run-container=nginx 1</code></pre>
<p>You can have some fun with the resize capability right away and see a new container pop-up.</p>
<pre><code>$ ./kubectl resize --replicas=2 rc nginx
resized</code></pre>
<p>Now that is fine and dandy but there is no port exposed on the host, so you cannot access your application on the outside. That's where you want to define a service. Technically it is used to expose a service to all nodes in a cluster but of course you can bind that service proxy to a publicly routed interface:</p>
<pre><code>$ ./kubectl expose rc nginx --port=80 --public-ip=192.168.33.10</code></pre>
<p>Now take your browser and open it at http://192.168.33.10 (if that's the IP of your host of course) and enjoy a replicated nginx managed by Kubernetes deployed in 1 command.</p>
<p>You will get more of that good stuff in my <a href="http://shop.oreilly.com/product/0636920036791.do">book</a>, if I manage to finish it. Wish me luck.</p>Sebastien Goasguenhttp://www.blogger.com/profile/05197845236510805309noreply@blogger.com6tag:blogger.com,1999:blog-19879822.post-85548810444389239122015-04-09T07:44:00.001-07:002015-04-09T07:44:57.974-07:00Running the CloudStack Simulator in Docker<p>CloudStack comes with a simulator. It is very handy for testing purposes, we use it to run our smoke tests on <a href="https://travis-ci.org/apache/cloudstack">TravisCI</a> for each commit to the code base. However if you want to run the simulator, you need to compile from source using some special maven profiles. That requires you to check out the code and setup your working environment with the dependencies for a successfull CloudStack build.</p>
<p>With Docker you can skip all of that and simply download the <code>cloudstack/simulator</code> image from the Docker Hub. Start a container from that image and expose port 8080 where the dashboard is being served. Once the container is running, you can use <code>docker exec</code> to configure a simulated data center. This will allow you to start fake virtual machines, create security groups and so on. You can do all of this through the dashboard or using the CloudStack API.</p>
<p>So you want to give CloudStack a try ? Use Docker :)</p>
<pre><code>$ docker pull cloudstack/simulator</code></pre>
<p>The image is a bit big and we need to work on slimming it down but once the image is pulled, starting the container will be almost instant. If you feel like sending a little PR just the <a href="https://github.com/apache/cloudstack/blob/master/Dockerfile">Dockerfile</a>, there might be a few obvious things to slim down the image.</p>
<pre><code>$ docker run -d -p 8080:8080 --name cloudstak cloudstack/simulator</code></pre>
<p>The application needs a few minutes to start however, something that I have not had time to check. Probably we need to give more memory to the container. Once you can access the dashboard at <code>http://localhost:8080/client</code> you can configure the simulated data-center. You can choose between a basic network which gives you L3 network isolation or advanced zone which gives you a VLAN base isolation:</p>
<pre><code>$ docker exec -ti cloudstack python /root/tools/marvin/marvin/deployDataCenter.py -i /root/setup/dev/basic.cfg</code></pre>
<p>Once the configuration completes, head over to the dashboard <code>http://localhost:8080/client</code> and check your simulated infrastructure</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjY5Jgcrkf5K3JY_fZ1H43gCwnI-YgYBYEJ15HlVpLAppVRzjdHOdcrgq_qah_HeEM4m04UX3S74hAXE9Xn-r_iIGEpoqIzv5xQ0sBWSgGIjCKWJ62fo2AqaspXwwaY-_dsLMeCXQ/s1600/acsdocker.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjY5Jgcrkf5K3JY_fZ1H43gCwnI-YgYBYEJ15HlVpLAppVRzjdHOdcrgq_qah_HeEM4m04UX3S74hAXE9Xn-r_iIGEpoqIzv5xQ0sBWSgGIjCKWJ62fo2AqaspXwwaY-_dsLMeCXQ/s320/acsdocker.png" /></a></div>
<p>Enjoy the CloudStack simulator brought to you by Docker.</p>Sebastien Goasguenhttp://www.blogger.com/profile/05197845236510805309noreply@blogger.com6tag:blogger.com,1999:blog-19879822.post-22897667662670080892015-03-18T03:01:00.001-07:002015-03-18T03:01:17.071-07:001 Command to Mesos with Docker ComposeIf you have not tried Docker, you should. The sheer power it puts in your hands and the simplicity of the user experience will just wow you. In this post, I will show you how to start a one node Mesos setup with Docker compose.<br />
<br />
Docker announced <a href="http://blog.docker.com/2015/02/announcing-docker-compose/" target="_blank">compose</a> on February 26th. Compose allows you to describe a multi-container setup and manage it with one binary <code>docker-compose</code>. The containers and volumes combinations managed by Compose are defined in a YAML file, super easy to read and super easy to write. The UX is very similar to the Docker CLI.<br />
<br />
When compose was released, I tried it and was a bit underwhelmed, as it is basically a relooking of <a href="http://www.fig.sh/" target="_blank">Fig</a>. This is not unexpected as Docker Inc, acquired Orchard the makers of Fig. But I was expecting more added functionality and even a tighter integration with the Docker client (something a <a href="https://github.com/docker/docker/issues/9459" target="_blank">dev</a> branch actually prototyped), even a common release instead of a separate binary. I am sure this will come.<br />
<br />
As I am writing the docker <a href="http://shop.oreilly.com/product/0636920036791.do" target="_blank">cookbook</a>, I have deployed Wordpress 20 different ways, and it's getting a bit boring ! I was looking for more information on Mesos and its support for Docker, I re-read a terrific <a href="https://medium.com/@gargar454/deploy-a-mesos-cluster-with-7-commands-using-docker-57951e020586" target="_blank">blog</a> post that showed how to start a Mesos setup (zookeeper, master, slave, marathon framework) in 7 commands. Can't beat that.<br />
<br />
When I re-read this post, I automatically thought this was an exciting use case for <code>docker-compose</code>. One YAML file to start Mesos/Zookeeper/Marathon and experiment with it. Of course I am not talking about a production multi-node setup. I am just looking at it for an easy Mesos experiment.<br />
I will spare you the details of installing compose (just a curl away). The dockers docs are <a href="http://docs.docker.com/compose/" target="_blank">great</a>.<br />
<br />
So here is the YAML file describing our Mesos setup:<br />
<pre><code>
</code></pre>
<pre><code>zookeeper:
image: garland/zookeeper
ports:
- "2181:2181"
- "2888:2888"
- "3888:3888"
mesosmaster:
image: garland/mesosphere-docker-mesos-master
ports:
- "5050:5050"
links:
- zookeeper:zk
environment:
- MESOS_ZK=zk://zk:2181/mesos
- MESOS_LOG_DIR=/var/log/mesos
- MESOS_QUORUM=1
- MESOS_REGISTRY=in_memory
- MESOS_WORK_DIR=/var/lib/mesos
marathon:
image: garland/mesosphere-docker-marathon
links:
- zookeeper:zk
- mesosmaster:master
command: --master zk://zk:2181/mesos --zk zk://zk:2181/marathon
ports:
- "8080:8080"
mesosslave:
image: garland/mesosphere-docker-mesos-master:latest
ports:
- "5051:5051"
links:
- zookeeper:zk
- mesosmaster:master
entrypoint: mesos-slave
environment:
- MESOS_HOSTNAME=192.168.33.10
- MESOS_MASTER=zk://zk:2181/mesos
- MESOS_LOG_DIR=/var/log/mesos
- MESOS_LOGGING_LEVEL=INFO</code></pre>
<pre><code>
</code></pre>
Four containers, images pulled from Docker hub, some ports exposed on the host. Some container linking and some environment variables used to configure the Mesos slave and master. One small hickup in the Slave defintion. You will see that I set the MESOS_HOSTNAME to the IP of the host. This allows me to browse the stdout and stderr of a Marathon task, otherwise we cannot reach it easily (small improvement to be done there.)<br />
<br />
Launch this with <code>docker-compose</code>:<br />
<pre><code>
</code></pre>
<pre><code>$ ./docker-compose up -d
Recreating vagrant_zookeeper_1...
Recreating vagrant_mesosmaster_1...
Recreating vagrant_marathon_1...
Recreating vagrant_mesosslave_1...</code></pre>
<br />
And open your browser at <i>http://IP_HOST</i><ip_host><i>:5050</i> then follow the rest of the <a href="https://medium.com/@gargar454/deploy-a-mesos-cluster-with-7-commands-using-docker-57951e020586[" target="_blank">blog</a> to start a task in marathon.</ip_host><br />
<ip_host><br /></ip_host>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOGLd-KyhiDX2jgCOfg8wwpao08EppWbcaHzZPYn-TbQm9BL1hbLJXs5WjDOObuHmotXB8rJPc895kQhRtNMdyQ7uMpMf2Y9HgWp-Xdl4sntfX1BGKDCXeU77_0KqHO2hrJ4asYQ/s1600/mesos.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOGLd-KyhiDX2jgCOfg8wwpao08EppWbcaHzZPYn-TbQm9BL1hbLJXs5WjDOObuHmotXB8rJPc895kQhRtNMdyQ7uMpMf2Y9HgWp-Xdl4sntfX1BGKDCXeU77_0KqHO2hrJ4asYQ/s1600/mesos.png" height="180" width="320" /></a></div>
<ip_host><br /></ip_host>
<ip_host><br /></ip_host>
Bottom line, I went from '7 commands to Mesos' to '1 command to Mesos' thanks to Docker-compose and a fairly simple YAML file. Got to love it. When compose can do this across Docker hosts in a Docker <a href="http://blog.docker.com/2015/02/orchestrating-docker-with-machine-swarm-and-compose/" target="_blank">Swarm started by Machine</a>. Then the real fun will begin !Sebastien Goasguenhttp://www.blogger.com/profile/05197845236510805309noreply@blogger.com4tag:blogger.com,1999:blog-19879822.post-38922991858463893052015-03-03T07:38:00.001-08:002015-03-03T07:38:45.839-08:00Rancher on RancherOSSomeone at <a href="http://rancher.com/">Rancher</a> must have some <a href="https://github.com/rancherio/cattle">cattle</a> in the middle of Arizona or in the backcountry of California. Or one of their VCs might be in Montana sitting in a big ranch while <a href="http://docker.com/">Docker</a> is eating the IT world. In any case, this post is short and sweet like veggies and not like cattle (TFW) and is about <a href="https://github.com/rancherio/rancher">Rancher</a> and the newly announced <a href="https://github.com/rancherio/os">RancherOS</a>. Check out the rancheros <a href="http://rancher.com/announcing-rancher-os/">announcement</a>.<br />
<br />
Let's keep this short, shall we ? Docker is great, but it is a daemon running on a single host. Since you want to scale :) and operate multiple servers, you need something to manage your Docker containers across multiple hosts. Several solutions are emerging, of course Docker <a href="https://github.com/docker/swarm/">Swarm</a> but also <a href="https://github.com/GoogleCloudPlatform/kubernetes">Kubernetes</a>, <a href="https://github.com/cloudfoundry-incubator/lattice">Lattice</a> from Cloudfoundry and even Apache <a href="http://mesos.apache.org/documentation/latest/docker-containerizer/">Mesos</a>. <a href="http://rancher.com/">Rancher</a> is one of these cluster management solutions for Docker. It does some nice things like cross-hosts container linking through a custom built network overlay (think Flannel, Weave, Socketplane).<br />
<br />
You can use Rancher with any set of Docker hosts. However, a new type of operating systems have started to appear. Container optimized OS. Or Just Enough Operating System for Docker. CoreOS, ProjectAtomic from RedHat, Ubuntu Snappy fit in that space. They aim to provide rolling atomic upgrades to the OS and run everything in it as a container. No more package manager, magic happens and you are always up to date. Package all your apps in containers, and use Rancher to run them in your cluster. End of story. Wait, enters rancherOS.<br />
<h2 id="rancheros">
RancherOS</h2>
A couple lines of bash make all the talking:<br />
<br />
<pre><code>$ git clone https://github.com/rancherio/os-vagrant.git
$ cd os-vagrant
$ vagrant up
$ vagrant ssh
[rancher@rancher ~]$ docker version
Client version: 1.5.0
…</code></pre>
<pre><code>
</code></pre>
rancherOS is a super minimalistic OS exclusively for Docker. It goes further and also runs system services as container themselves. And I will let @ibuildthecloud talk about systemd and Docker as PID 1.<br />
<br />
<pre><code>[rancher@rancher ~]$ sudo system-docker ps
CONTAINER ID IMAGE COMMAND ... NAMES
32607470eb78 console:latest "/usr/sbin/console.s ... console
d0420165c1c0 userdocker:latest "/docker.sh" ... userdocker
375a8de12183 syslog:latest "/syslog.sh" ... syslog
d284afd7f628 ntp:latest "/ntp.sh" ... ntp </code></pre>
<pre><code>
</code></pre>
The next logical question is of course....drum roll... Can I run rancher on rancheros. RinR not R&R ? And the answer is a resounding yes. I expect Rancher to come out in the next weeks maybe months with a solid product based on the two.<br />
<h2 id="rancher">
Rancher</h2>
If you are interested to try out RinR then check out the Ansible <a href="https://github.com/runseb/ansible-rancher">playbook</a> I just made. You can use use it to deploy a cluster of rancherOS instances in AWS, and use one of them as a master and the others as workers. The master runs in a container:<br />
<br />
<pre><code>$ docker run -d -p 8080:8080 rancher/server </code></pre>
<br />
And the workers can register with their agent:<br />
<pre><code>
</code></pre>
<pre><code>$ sudo docker run --rm -it --privileged -v /var/run/docker.sock:/var/run/docker.sock rancher/agent http://<master_ip>:8080</code></pre>
<br />
Once all the workers have registered you can use the UI or the API to start containers.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://raw.githubusercontent.com/runseb/ansible-rancher/master/images/ui.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="173" src="https://raw.githubusercontent.com/runseb/ansible-rancher/master/images/ui.png" width="320" /></a></div>
<br />
As you can see I tested this at web scale with two nodes :)<br />
<h2 id="notes">
Notes</h2>
In this very early super bleeding-edge testing phase (as you can tell in my good spirit today), I did find a few things that were a bit strange. Considering rancherOS was announced just last week, I am sure things will get fixed. Cloud-init support is minimal, not able to add second network interface, support for both keypair and userdata at the same time seems off. The UI was a bit slow to start and building the overlay was also a bit slow. It is also possible that I did something wrong.<br />
<br />
Overall though, rancher is quite nice. It builds on years of experience in the team with developing CloudStack and operating clouds at scale and applies it to the Docker world. It does seem that they want to integrate with and provide the native Docker API, this would mean that users will be able to use Docker machine to add hosts to a rancher cluster, or even Docker swarm and that launching a container would also be a docker command away. How that differentiates from Swarm itself is not yet clear, but I would bet we will see additional networking and integration services in Rancher. Blurring the lines with Kubernetes ? Time will tell.Sebastien Goasguenhttp://www.blogger.com/profile/05197845236510805309noreply@blogger.com0tag:blogger.com,1999:blog-19879822.post-46573573049361242352015-01-29T05:41:00.001-08:002015-01-29T05:41:41.799-08:00O'Reilly Docker cookbookThe last two months have been busy as I am writing the O'Reilly <a href="http://shop.oreilly.com/product/0636920036791.do">Docker cookbook</a> at night and on week-ends. CloudStack during the day, Docker at night :) You can read the very "drafty" preface on <a href="https://www.safaribooksonline.com/library/view/docker-cookbook/9781491919705/pr01.html#_why_i_wrote_this_book">Safari</a> and you will get a sense of why I started writing the book.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaH5x3CvbDfsQIXhQ5hR6KA93ZXz5KljWKSy0WXMEUTPDPADay0sbrbCxkgJXU2QoBcMza18Fx4k8PB_iaSzebJbJk-Kqwvp3TlbVYRLmlBPyfWV0xKw8A_QoBPDZr2tR2fnhcAQ/s1600/dockbercover.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaH5x3CvbDfsQIXhQ5hR6KA93ZXz5KljWKSy0WXMEUTPDPADay0sbrbCxkgJXU2QoBcMza18Fx4k8PB_iaSzebJbJk-Kqwvp3TlbVYRLmlBPyfWV0xKw8A_QoBPDZr2tR2fnhcAQ/s1600/dockbercover.png" height="320" width="246" /></a></div>
<br />
Docker is amazing, it brings a terrific user experience to packaging application and deploying them easily. It is also a software that is moving very fast with over 5,500 pull requests closed so far. The community is huge and folks are very excited about it, just check those 18,000+ stars on <a href="https://github.com/docker/docker">Github</a>.<br />
<br />
Writing a book on Docker means reading all the documentation, reading countless blogs that are flying through twitter and then because its a cookbook, you need to get your hands dirty and actually try everything, test everything, over and over again. A cookbook is made of recipes in a very set format: Problem, Solution, Discussion. It is meant to be picked up at anytime, opened at any page and read a recipe that is independent of all the others. The book is now on pre-release, it means that you can buy it and get the very drafty version of the book as I write it, mistakes, typos and bad grammar included. As I keep writing you get the updates and once I am done you of course get the final proof-read, corrected and reviewed version.<br />
<br />
As I started writing, I thought I would share some of the snippets of code I am writing to do the recipes. The code is available on GitHub at the <a href="https://github.com/how2dock/docbook">how2dock</a> account. How2dock should become a small company for Docker training and consulting as soon as I find spare time :).<br />
<br />
What you will find <a href="https://github.com/how2dock/docbook">there</a> is not really code, but really a repository of scripts and Vagrantfiles that I use in the book to showcase a particular feature or command of Docker. The repository is organized the same way than the book. You can pick a chapter and then a particular recipe then go through the README.<br />
<br />
For instance if you are curious about Docker swarm:<br />
<pre><code>
</code></pre>
<pre><code>$ git clone https://github.com/how2dock/docbook.git
$ cd ch07/swarm
$ vagrant up</code></pre>
<br />
This will bring up four virtual machines via <a href="http://vagrantup.com/">Vagrant</a> and do the necessary boostrapping to get the cluster setup with <a href="https://github.com/how2dock/docbook/tree/master/ch07/swarm">Swarm</a>.<br />
<br />
If you want to run a wordpress blog with a mysql database, checkout the fig recipe:<br />
<pre><code>
</code></pre>
<pre><code>$ cd ch07/fig
$ vagrant up
$ vagrant ssh
$ cd /vagrant
$ fig up -d</code></pre>
<br />
And enjoy Wordpress :)<br />
<br />
I put a lot more in there. You will find an example of using the <a href="https://github.com/how2dock/docbook/tree/master/ch07/ansible">Ansible</a> Docker module, a <a href="https://github.com/how2dock/docbook/tree/master/ch06/snappy-cloud">libcloud</a> script to start an Ubuntu Snappy instance on EC2, a <a href="https://github.com/how2dock/docbook/tree/master/ch04/tls">Dockerfile</a> to help you create TLS certificates (really a convenience container for testing TLS in Docker). A Docker <a href="https://github.com/how2dock/docbook/tree/master/ch01/dockermachine">machine</a> setup and a recipe on using <a href="https://github.com/how2dock/docbook/tree/master/ch01/supervisor">Supervisor</a>.<br />
<br />
As I keep writing, I will keep putting all the snippets in this <a href="https://github.com/how2dock/docbook">How2dock</a> repo. Except frequent changes, typos, errors...and corrections :)<br />
<br />
And FWIW, it is much scarier to put a book out in pre-release unedited than to put some scripts up on GitHub.<br />
<br />
Suggestions, comments, reviews all welcome ! Happy Docking !Sebastien Goasguenhttp://www.blogger.com/profile/05197845236510805309noreply@blogger.com0tag:blogger.com,1999:blog-19879822.post-21197577288558584962014-10-02T03:07:00.000-07:002014-10-02T03:07:37.444-07:00CloudStack simulator on Docker<p><a href="http://www.docker.com">Docker</a> is a lot of fun, one of its strength is in the portability of applications. This gave me the idea to package the <a href="http://cloudstack.apache.org">CloudStack</a> management server as a docker image.</p>
<p>CloudStack has a simulator that can fake a data center infrastructure. It can be used to test some of the basic functionalities. We use it to run our integration tests, like the smoke tests on <a href="https://travis-ci.org/apache/cloudstack/builds">TravisCI</a>. The simulator allows us to configure an advanced or basic networking zone with fake hypervisors.</p>
<p>So I bootstrapped the CloudStack management server, configured the Mysql database with an advanced zone and created a docker image with <a href="http://www.packer.io/intro">Packer</a>. The resulting image is on <a href="https://registry.hub.docker.com/u/runseb/cloudstack/">DockerHub</a>, and I realized after the fact that four other great minds already did something <a href="https://registry.hub.docker.com/search?q=cloudstack&searchfield=">similar</a> :)</p>
<p>On a machine running docker:</p>
<pre><code>docker pull runseb/cloudstack
docker run -t -i -p 8080:8080 runseb/cloudstack:0.1.4 /bin/bash
# service mysql restart
# cd /opt/cloudstack
# mvn -pl client jetty:run -Dsimulator</code></pre>
<p>Then open your browser on http://<IP_of_docker_host>:8080/client and enjoy !</p>Sebastien Goasguenhttp://www.blogger.com/profile/05197845236510805309noreply@blogger.com5tag:blogger.com,1999:blog-19879822.post-90612918022295337142014-09-30T02:18:00.001-07:002014-09-30T02:18:34.977-07:00On Docker and Kubernetes on CloudStack<h1 id="on-docker-and-kubernetes-on-cloudstack">On Docker and Kubernetes on CloudStack</h1>
<p><a href="http://www.docker.io">Docker</a> has pushed containers to a new level, making it extremely easy to package and deploy applications within containers. Containers are not new, with <a href="http://en.wikipedia.org/wiki/Solaris_Containers">Solaris containers</a> and <a href="http://en.wikipedia.org/wiki/OpenVZ">OpenVZ</a> among several containers technologies going back 2005. But Docker has caught on <a href="http://thenewstack.io/why-did-docker-catch-on-quickly-and-why-is-it-so-interesting/">quickly</a> as mentioned by @adrianco. The startup speed is not surprising for containers, the portability is reminiscent of the Java goal to "write once run anywhere". What is truly interesting with Docker is that availability of Docker registries (e.g <a href="http://hub.docker.com">Docker Hub</a>) to share containers and the potential to change the application deployment workflows.</p>
<p>Rightly so, we should soon see IT move to a docker based application deployment, where developers package their applications and make them available to Ops. Very much like we have been using war files. Embracing a DevOps mindset/culture should be easier with Docker. Where it becomes truly interesting is when we start thinking about an infrastructure whose sole purpose is to run containers. We can envision a bare operating system with a single goal to manage docker based services. This should make sys admin life easier.</p>
<h2 id="the-role-of-the-cloud-with-docker">The role of the Cloud with Docker</h2>
<p>While the buzz around Docker has been truly amazing and a community has grown over night, some may think that this signals the end of the cloud. I think it is far from the truth as Docker may indeed become the killer app of the cloud.</p>
<p><strong>A IaaS layer is what is: an infrastructure orchestration layer, while Docker and its ecosystem will become the application orchestration layer.</strong></p>
<p>The question then becomes: How do I run Docker in the cloud ? And there is a straightforward answer: Just install Docker in your cloud templates. Whether on AWS or GCE or Azure or your private cloud, you can prepare linux based templates that provide Docker support. If you are aiming for the bare operating system whose sole purpose is to run Docker then the new <a href="https://coreos.com">CoreOS</a> linux distribution might be your best pick. CoreOS provides rolling upgrades of the kernel, systemd based services, a distributed key value store (i.e <a href="https://github.com/coreos/etcd">etcd</a>) and a distributed service scheduling system (i.e <a href="https://coreos.com/using-coreos/clustering/">fleet</a>)</p>
<p><strong><a href="http://exoscale.ch">exoscale</a> an Apache CloudStack based public clouds, recently <a href="https://www.exoscale.ch/syslog/2014/09/17/coreos-available-on-exoscale-swiss-cloud/">announced</a> the availability of CoreOS templates.</strong></p>
<p>Like exoscale, any cloud provider be it public or private can make CoreOS templates available. Providing Docker within the cloud instantly.</p>
<h2 id="docker-application-orchestration-here-comes-kubernetes">Docker application orchestration, here comes <a href="https://github.com/GoogleCloudPlatform/kubernetes">Kubernetes</a></h2>
<p>Running one container is easy, but running multiple coordinated containers across a cluster of machines is not yet a solved problem. If you think of an application as a set of containers, starting these on multiple hosts, replicating some of them, accessing distributed databases, providing proxy services and fault tolerance is the true challenge.</p>
<p>However, Google came to the resuce and announced <a href="http://www.datacenterknowledge.com/archives/2014/07/10/googles-docker-container-management-project-kubernetes-gets-big-league-support/">Kubernetes</a> a system that solves these issues and makes managing scalable, fault-tolerant container based apps doable :)</p>
<p>Kubernetes is of course available on Google public cloud GCE, but also in Rackspace, Digital Ocean and Azure. It can also be deployed on CoreOS easily.</p>
<h2 id="kubernetes-on-cloudstack">Kubernetes on CloudStack</h2>
<p>Kubernetes is under heavy development, you can test it with <a href="https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/getting-started-guides/vagrant.md">Vagrant</a>. Under the hood, aside from the go code :), most of the deployment solutions use <a href="http://www.saltstack.com">SaltStack</a> recipes but if you are a Chef, Puppet or Ansible user I am sure we will see recipes for those configuration management solution soon.</p>
<p>But you surely got the same idea that I had :) Since Kubernetes can be deployed on <a href="https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/getting-started-guides/coreos.md">CoreOS</a> and that CoreOS is available on exoscale. We are just a breath away from running Kubernetes on CloudStack.</p>
<p><strong>It took a little more than a breath, but you can clone <a href="https://github.com/runseb/kubernetes-exoscale">kubernetes-exoscale</a> and you will get running in 10 minutes. With a 3 node etcd cluster and a 5 node kubernetes cluster, running a <a href="https://coreos.com/blog/introducing-rudder/">Flannel</a> overlay.</strong></p>
<p>CloudStack supports EC2 like userdata, and the CoreOS templates on exoscale support cloud-init, hence passing some cloud-config files to the instance deployment was straightforward. I used libcloud to provision all the nodes, created proper security groups to let the Kubernetes nodes access the etcd cluster and let the Kubernetes nodes talk to each other, especially to open a UDP port to build a networking overlay with Flannel. Fleet is used to launch all the Kubernetes services. Try it out.</p>
<h2 id="conclusions.">Conclusions.</h2>
<p>Docker is extremely easy to use and taking advantage of a cloud you can get started quickly. CoreOS will put your docker work on steroid with availability to start apps as systemd services over a distributed cluster. Kubernetes will up that by giving you replication of your containers and proxy services for free (time).</p>
<p>We might see pure docker based public clouds (e.g think Mesos cluster with a Kubernetes framework). These will look much more like PaaS, especially if they integrate a Docker registry and a way to automatically build docker images (e.g think continuous deployment pipeline).</p>
<p>But a "true" IaaS is actually very complimentary, providing multi-tenancy, higher <a href="http://www.linux.com/news/enterprise/cloud-computing/785769-containers-vs-hypervisors-the-battle-has-just-begun">security</a> as well as multiple OS templates. So treating docker as a standard cloud workload is not a bad idea. With three dominant public clouds in AWS, GCE and Azure and a multitude of "regional" ones like exoscale it appears that building a virtualization based cloud is a solved problem (at least with Apache CloudStack :)).</p>
<p><strong>So instead of talking about cloudifying your application, maybe you should start thinking about Dockerizing your applications and letting them loose on CloudStack.</strong></p>
Sebastien Goasguenhttp://www.blogger.com/profile/05197845236510805309noreply@blogger.com4tag:blogger.com,1999:blog-19879822.post-78799459328861171442014-07-11T15:42:00.001-07:002014-07-11T15:42:53.796-07:00GCE Interface to CloudStack<h1 id="gstack-a-gce-compatible-interface-to-cloudstack"><em>Gstack</em>, a GCE compatible interface to CloudStack</h1>
<p><a href="https://cloud.google.com/products/compute-engine/">Google Compute Engine (GCE)</a> is the Google public cloud. In december 2013, Google announced the <a href="http://yourstory.com/2013/12/google-compute-engine-gce/">General Availability (GA)</a> of GCE. With AWS and Microsoft Azure, it is one of the three leading public clouds in the market. <a href="http://cloudstack.apache.org">Apache CloudStack</a> now has a brand new GCE compatible interface (Gstack) that lets users use the GCE clients (i.e gcloud and gcutil) to access their CloudStack cloud. This has been made possible through the Google Summer of Code program.</p>
<p>Last summer Ian Duffy, a student from Dublin City University participated in GSoC through the Apache Software Foundation (<a href="http://community.apache.org/gsoc.html">ASF</a>) and worked on a LDAP plugin to CloudStack. He did such a great job that he finished early and was made an Apache CloudStack committer. Since he was done with his original GSoC project I encouraged him to take on a new one :), he brought in a friend for the ride: Darren Brogan. Both of them worked for fun on the GCE interface to CloudStack and learned Python doing so.</p>
<p>They remained engaged with the CloudStack community and has a third year project worked on an Amazon EC2 <a href="https://github.com/BroganD1993/ec2stack">interface</a> to CloudStack using what they learned from the GCE interface. They got an A :). Since they loved it so much, Darren applied to the GSoC program and proposed to go back to Gstack, improve it, extend the unittests and make it compatible with the GCE v1 API.</p>
<p>Technically, Gstack is a Python Flask application that provides a REST API compatible with the GCE API and forwards the requests to the corresponding CloudStack API. The source is available on <a href="https://github.com/NOPping/gstack">GitHub</a> and the binary is downloadable via <a href="https://pypi.python.org/pypi/gstack">PyPi</a>. Let's show you how to use it.</p>
<h2 id="installation-and-configuration-of-gstack">Installation and Configuration of Gstack</h2>
<p>You can grab the <em>Gstack</em> binary package from Pypi using <em>pip</em> in one single command.</p>
<pre><code>pip install gstack</code></pre>
<p>Or if you plan to explore the source and work on it, you can Clone the repository and install it by hand. Pull requests are of course welcome.</p>
<pre><code>git clone https://github.com/NOPping/gstack.git
sudo python ./setup.py install</code></pre>
<p>Both of these installation methods will install a <em>gstack</em> and a <em>gstack-configure</em> binary in your path. Before running <em>Gstack</em> you must configure it. To do so run:</p>
<pre><code>gstack-configure</code></pre>
<p>And enter your configuration information when prompted. You will need to specify the host and port where you want <code>gstack</code> to run on, as well as the CloudStack endpoint that you want <code>gstack</code> to forward the requests to. In the example below we use the <a href="http://exoscale.ch">exoscale</a> cloud:</p>
<pre><code>$ gstack-configure
gstack bind address [0.0.0.0]: localhost
gstack bind port [5000]:
Cloudstack host [localhost]: api.exoscale.ch
Cloudstack port [8080]: 443
Cloudstack protocol [http]: https
Cloudstack path [/client/api]: /compute</code></pre>
<p>The information will be stored in a configuration file available at <code>~/.gstack/gstack.conf</code>:</p>
<pre><code>$ cat ~/.gstack/gstack.conf
PATH = 'compute/v1/projects/'
GSTACK_BIND_ADDRESS = 'localhost'
GSTACK_PORT = '5000'
CLOUDSTACK_HOST = 'api.exoscale.ch'
CLOUDSTACK_PORT = '443'
CLOUDSTACK_PROTOCOL = 'https'
CLOUDSTACK_PATH = '/compute'</code></pre>
<p>You are now ready to start <em>Gstack</em> in the foreground with:</p>
<pre><code>gstack</code></pre>
<p>That's all there is to running <em>Gstack</em>. To be able to use it as if you were talking to GCE however, you need to use <em>gcutil</em> and configure it a bit.</p>
<h2 id="using-gcutil-with-gstack">Using <code>gcutil</code> with Gstack</h2>
<p>The current version of <em>Gstack</em> only works with the stand-alone version of <a href="https://developers.google.com/compute/docs/gcutil/">gcutil</a>. Do not use the version of <em>gcutil</em> bundled in the Google Cloud SDK. Instead install the 0.14.2 version of <em>gcutil</em>. <em>Gstack</em> comes with a self-signed certificate for the local endpoint <code>gstack/data/server.crt</code>, copy the certificate to the gcutil certificates file <code>gcutil/lib/httplib2/httplib2/cacerts.txt</code>. A bit dirty I know, but that's a work in progress.</p>
<p>At this stage your CloudStack apikey and secretkey need to be entered in the gcutil auth_helper.py file at <code>gcutil/lib/google_compute_engine/gcutil/auth_helper.py</code>.</p>
<p>Again not ideal but hopefully <em>gcutil</em> or the Cloud SDK will soon be able to configure those without touching the source. Darren and Ian opened a feature request with google to pass the <code>client_id</code> and <code>client_secret</code> as options to gcutil, hopefully future release of <em>gcutil</em> will allow us to do so.</p>
<p>Now, create a cached parameters file for <em>gcutil</em>. Assuming you are running <em>gstack</em> on your local machine, using the defaults that were suggested during the configuration phase. Modify <code>~/.gcutil_params</code> with the following:</p>
<pre><code>--auth_local_webserver
--auth_host_port=9999
--dump_request_response
--authorization_uri_base=https://localhost:5000/oauth2
--ssh_user=root
--fetch_discovery
--auth_host_name=localhost
--api_host=https://localhost:5000/</code></pre>
<p><strong>Warning</strong>: Make sure to set the --auth_host_name variable to the same value as GSTACK_BIND_ADDRESS in your <code>~/.gstack/gstack.conf</code> file. Otherwise you will see certificates errors.</p>
<p>With this setup complete, <em>gcutil</em> will issues requests to the local Flask application, get an OAuth token, issue requests to your CloudStack endpoint and return the response in a <em>GCE</em> compatible format.</p>
<h2 id="example-with-exoscale.">Example with <a href="http://exoscale.ch">exoscale</a>.</h2>
<p>You can now start issuing standard gcutil commands. For illustration purposes we use <a href="http://exoscale.ch">Exoscale</a>. Since there are several <em>semantic</em> differences, you will notice that as a project we use the account information from CloudStack. Hence we pass our email address as the project value.</p>
<p>Let's start by listing the availability zones:</p>
<pre><code>$ gcutil --cached_flags_file=~/.gcutil_params --project=runseb@gmail.com listzones
+----------+--------+------------------+
| name | status | next-maintenance |
+----------+--------+------------------+
| ch-gva-2 | UP | None scheduled |
+----------+--------+------------------+</code></pre>
<p>Let's list the machine types or in CloudStack terminology: the compute service offerings and to list the available images.</p>
<pre><code>$ ./gcutil --cached_flags_file=~/.gcutil_params --project=runseb@gmail.com listimages
$ gcutil --cached_flags_file=~/.gcutil_params --project=runseb@gmail.com listmachinetypes
+-------------+----------+------+-----------+-------------+
| name | zone | cpus | memory-mb | deprecation |
+-------------+----------+------+-----------+-------------+
| Micro | ch-gva-2 | 1 | 512 | |
+-------------+----------+------+-----------+-------------+
| Tiny | ch-gva-2 | 1 | 1024 | |
+-------------+----------+------+-----------+-------------+
| Small | ch-gva-2 | 2 | 2048 | |
+-------------+----------+------+-----------+-------------+
| Medium | ch-gva-2 | 2 | 4096 | |
+-------------+----------+------+-----------+-------------+
| Large | ch-gva-2 | 4 | 8182 | |
+-------------+----------+------+-----------+-------------+
| Extra-large | ch-gva-2 | 4 | 16384 | |
+-------------+----------+------+-----------+-------------+
| Huge | ch-gva-2 | 8 | 32184 | |
+-------------+----------+------+-----------+-------------+</code></pre>
<p>You can also list firewalls which <em>gstack</em> maps to CloudStack security groups. To create a securitygroup, use the firewall commands:</p>
<pre><code>$ ./gcutil --cached_flags_file=~/.gcutil_params --project=runseb@gmail.com addfirewall ssh --allowed=tcp:22
$ ./gcutil --cached_flags_file=~/.gcutil_params --project=runseb@gmail.com getfirewall ssh</code></pre>
<p>To start an instance you can follow the interactive prompt given by <em>gcutil</em>. You will need to pass the --permit_root_ssh flag, another one of those semantic and access configuration that needs to be ironed out. The interactive prompt will let you choose the machine type and the image that you want, it will then start the instance</p>
<pre><code>$ ./gcutil --cached_flags_file=~/.gcutil_params --project=runseb@gmail.com addinstance foobar
Selecting the only available zone: CH-GV2
1: Extra-large Extra-large 16384mb 4cpu
2: Huge Huge 32184mb 8cpu
3: Large Large 8192mb 4cpu
4: Medium Medium 4096mb 2cpu
5: Micro Micro 512mb 1cpu
6: Small Small 2048mb 2cpu
7: Tiny Tiny 1024mb 1cpu
7
1: CentOS 5.5(64-bit) no GUI (KVM)
2: Linux CentOS 6.4 64-bit
3: Linux CentOS 6.4 64-bit
4: Linux CentOS 6.4 64-bit
5: Linux CentOS 6.4 64-bit
6: Linux CentOS 6.4 64-bit
<...snip>
INFO: Waiting for insert of instance . Sleeping for 3s.
INFO: Waiting for insert of instance . Sleeping for 3s.
Table of resources:
+--------+--------------+--------------+----------+---------+
| name | network-ip | external-ip | zone | status |
+--------+--------------+--------------+----------+---------+
| foobar | 185.1.2.3 | 185.1.2.3 | ch-gva-2 | RUNNING |
+--------+--------------+--------------+----------+---------+
Table of operations:
+--------------+--------+--------------------------+----------------+
| name | status | insert-time | operation-type |
+--------------+--------+--------------------------+----------------+
| e4180d83-31d0| DONE | 2014-06-09T10:31:35+0200 | insert |
+--------------+--------+--------------------------+----------------+</code></pre>
<p>You can of course list (with <code>listinstances</code>) and delete instances</p>
<pre><code>$ ./gcutil --cached_flags_file=~/.gcutil_params --project=runseb@gmail.com deleteinstance foobar
Delete instance foobar? [y/n]
y
WARNING: Consider passing '--zone=CH-GV2' to avoid the unnecessary zone lookup which requires extra API calls.
INFO: Waiting for delete of instance . Sleeping for 3s.
+--------------+--------+--------------------------+----------------+
| name | status | insert-time | operation-type |
+--------------+--------+--------------------------+----------------+
| d421168c-4acd| DONE | 2014-06-09T10:34:53+0200 | delete |
+--------------+--------+--------------------------+----------------+</code></pre>
<p><em>Gstack</em> is still a work in progress, it is now compatible with GCE GA v1.0 <a href="https://developers.google.com/compute/docs/reference/latest/">API</a>. The few differences in API semantics need to be investigated further and additional API calls need to be supported. However it provides a solid base to start working on hybrid solutions between GCE public cloud and a CloudStack based private cloud.</p>
<p>GSoC has been terrific to Ian and Darren, they both learned how to work with an open source community and ultimately became part of it through their work. They learned tools like JIRA, git, Review Board and became less shy with working publicly on a mailing lists. Their work on Gstack and EC2stack is certainly of high value to CloudStack and should become the base for interesting products that will use hybrid clouds.</p>
Sebastien Goasguenhttp://www.blogger.com/profile/05197845236510805309noreply@blogger.com0tag:blogger.com,1999:blog-19879822.post-18773081791754746762014-06-03T05:31:00.002-07:002014-06-17T00:20:14.220-07:00Eutester with CloudStack<h1 id="eutester">Eutester</h1>
<p>An interesting tool based on Boto is <a href="https://github.com/eucalyptus/eutester">Eutester</a> it was created by the folks at Eucalyptus to provide a framework to create functional tests for AWS zones and Eucalyptus based clouds. What is interesting with <code>eutester</code> is that it could be used to compare the AWS compatibility of multiple clouds. Therefore the interesting question that you are going to ask is: Can we use Eutester with CloudStack ? And the answer is Yes. Certainly it could use more work but the basic functionality is there.</p>
<p>Install <code>eutester</code> with:</p>
<pre><code>pip install eutester</code></pre>
<p>Then start Python/iPython interactive shell or write a script that will import <code>ec2ops</code> and create a connection object to your AWS EC2 compatible endpoint. For example, using <a href="https://github.com/BroganD1993/ec2stack.git">ec2stack</a>:</p>
<pre class="sourceCode python"><code class="sourceCode python"> <span class="co">#!/usr/bin/env python</span>
<span class="ch">from</span> eucaops <span class="ch">import</span> ec2ops
<span class="ch">from</span> IPython.terminal.embed <span class="ch">import</span> InteractiveShellEmbed
accesskey=<span class="st">"my api key"</span>
secretkey=<span class="st">"my secret key"</span>
conn.ec2ops.EC2ops(endpoint=<span class="st">"localhost"</span>,
aws_access_key_id=apikey,
aws_secret_access_key=secretkey,
is_secure=<span class="ot">False</span>,
port=<span class="dv">5000</span>,
path=<span class="st">"/"</span>,
APIVersion=<span class="st">"2014-02-01"</span>)
ipshell = InteractiveShellEmbed(banner1=<span class="st">"Hello Cloud Shell !!"</span>)
ipshell()</code></pre>
<p>Eutester at the time of this writing has 145 methods. Only the methods available through the CloudStack AWS EC2 interface will be availble. For example, <code>get_zones</code> and <code>get_instances</code> would return:</p>
<pre><code>In [3]: conn.get_zones()
Out[3]: [u'ch-gva-2']
In [4]: conn.get_instances()
[2014-05-21 05:39:45,094] [EUTESTER] [DEBUG]:
--->(ec2ops.py:3164)Starting method: get_instances(self, state=None,
idstring=None, reservation=None, rootdevtype=None, zone=None,
key=None, pubip=None, privip=None, ramdisk=None, kernel=None,
image_id=None, filters=None)
Out[4]:
[Instance:5a426582-3aa3-49e0-be3f-d2f9f1591f1f,
Instance:95ee8534-b171-4f79-9e23-be48bf1a5af6,
Instance:f18275f1-222b-455d-b352-3e7b2d3ffe9d,
Instance:0ea66049-9399-4763-8d2f-b96e9228e413,
Instance:7b2f63d6-66ce-4e1b-a481-e5f347f7e559,
Instance:46d01dfd-dc81-4459-a4a8-885f05a87d07,
Instance:7158726e-e76c-4cd4-8207-1ed50cc4d77a,
Instance:14a0ce40-0ec7-4cf0-b908-0434271369f6]</code></pre>
<p>This example shows that I am running eight instances at the moment in a zone called <em>ch-gva-2</em>, our familiar <a href="http://exoscale.ch">exoscale</a>. Selecting one of these instance objects will give you access to all the methods available for instances. You could also list, delete and create keypairs. List, delete and create security groups etc.</p>
<p>Eutester is meant for building integration tests and easily creating test scenarios. If you are looking for a client to build an application with, use Boto.</p>
<p>The <em>master</em> branch of eutester may still cause problems to list images from a CloudStack cloud. I recently <a href="https://github.com/runseb/eutester/commit/081dcb1216f68e1989ae50d937a6bb1c4e5ddadc">patched</a> a fork of the <em>testing</em> branch and opened an <a href="https://github.com/eucalyptus/eutester/issues/287">issue</a> on their github page. You might want to check its status if you want to use eutester heavily.</p>
Sebastien Goasguenhttp://www.blogger.com/profile/05197845236510805309noreply@blogger.com0tag:blogger.com,1999:blog-19879822.post-10492096516957867882014-03-19T08:26:00.002-07:002014-03-19T08:29:28.283-07:00Migrating from Publican to Sphinx and Read The Docs<h1 id="migration-from-publican-to-sphinx-and-read-the-docs">
Migration from Publican to Sphinx and Read The Docs</h1>
When we started with Cloudstack we chose to use <a href="https://fedorahosted.org/publican/">publican</a> for our documentation. I don't actually know why, except that Red Hat <a href="https://access.redhat.com/site/documentation/en-US/">documentation</a> is entirely based on publican. Perhaps David Nalley's background with <a href="http://docs.fedoraproject.org/en-US/index.html">Fedora</a> influenced us :) In any case publican is a very nice documentation building system, it is based on the <a href="http://www.docbook.org/">docbook</a> format and has great support for localization. However it can become difficult to read and organize lots of content, and builds may break for strange reasons. We also noticed that we were not getting many contributors to the documentation, in contrast, the translation efforts via <a href="http://transifex.net/">transifex</a> has had over 80 contributors. As more features got added to CloudStack the quality of the content also started to suffer and we also faced issues with publishing the translated documents. We needed to do something, mainly making it easier to contribute to our documentation. Enters <a href="http://docutils.sourceforge.net/rst.html">ReStructured Text (RST)</a> and <a href="https://readthedocs.org/">Read The Docs (RTD)</a>.<br />
<h2 id="choosing-a-new-format">
Choosing a new format</h2>
We started thinking about how to make our documentation easier to contribute to. Looking at Docbook, purely xml based, it is a powerful format but not very developer friendly. A lot of us are happy with basic text editor, with some old farts like me mainly stuck with vi. <a href="http://daringfireball.net/projects/markdown/">Markdown</a> has certainly helped a lot of folks in writing documentation and READMEs, just look at Github projects. I started writing in Markdown and my production in terms of documentation and tutorials skyrocketed, it is just a great way to write docs. <a href="http://docutils.sourceforge.net/rst.html">Restructured Text</a> is another alternative, not really markdown, but pretty close. I got familiar with RST in the <a href="http://libcloud.apache.org/">Apache libcloud</a> project and fell in love with it, or at least liked it way more than docbook. RST is basically text, only a few markups to learn and your off.<br />
<h2 id="publishing-platform">
Publishing Platform</h2>
A new format is one thing but you then need to build documentation in multiple formats: html, pdf, epub potentially more. How do you move from .rst to these formats for your projects ? Comes in <a href="http://sphinx-doc.org/">Sphinx</a>, pretty much an equivalent to publican originally aimed at Python documentation but now aimed at much more. Installing sphinx is easy, for instance on Debian/Ubuntu:<br />
<pre><code>apt-get install python-sphinx</code></pre>
You will then have the <code>sphinx-quickstart</code> command in your path, use it to create your sphinx project, add content in <code>index.rst</code> and build the docs with <code>make html</code>. Below is a basic example for a <code>ff</code> sample project.<br />
<div class="figure">
<br />
<div class="caption">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiztVbihaZ2CEHc8g-4gS1BcnYp0iYngnJM_TsB3ijz8PvfCEGCOtrb40I28G4T_jjKx3Lv1OgmfEnX8wnwxIJvWTmsDRJNLBrIonz88Dljn6D3YcAYHUoqu5TxcbHgXtSs_22yuA/s1600/exsphinx.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiztVbihaZ2CEHc8g-4gS1BcnYp0iYngnJM_TsB3ijz8PvfCEGCOtrb40I28G4T_jjKx3Lv1OgmfEnX8wnwxIJvWTmsDRJNLBrIonz88Dljn6D3YcAYHUoqu5TxcbHgXtSs_22yuA/s1600/exsphinx.png" height="177" width="640" /></a></div>
<div class="caption">
<br /></div>
<div class="caption">
<br /></div>
</div>
What really got me sold on reStructuredText and Sphinx was <a href="http://docs.readthedocs.org/en/latest/">ReadTheDocs (RTD)</a>. It hosts documentation for open source projects. It automatically pulls your documentation from your revision control system and builds the docs. The killer feature for me was the integration with github (not just git). Using hooks, RTD can trigger builds on every commit and it also displays an <code>edit on github</code> icon on each documentation page. Click on this icon, and the docs repository will get forked automatically on your github account. This means that people can edit the docs straight up in the github UI and submit pull requests as they read the docs and find issues.<br />
<h2 id="conversion">
Conversion</h2>
After [PROPOSAL] and [DISCUSS] threads on the cloudstack mailing list, we reached consensus and decided to make the move. This is still on-going but we are getting close to going live with our new docs in RST and hosted by RTD. There were couple challenges:<br />
<ol style="list-style-type: decimal;">
<li>Converting the existing docbook based documentation to RST</li>
<li>Setting up new repos, CNAMEs and Read The Docs projects</li>
<li>Setting up the localization with transifex</li>
</ol>
The conversion was much easier than expected thanks to <a href="http://johnmacfarlane.net/pandoc/">pandoc</a>, one of those great command line utility that saves your life.<br />
<pre><code>pandoc -f docbook -t rst -o test.rst test.docbook</code></pre>
You get the just of it, iterate through your docbook files and generate the RST files, combine everything to reconstruct your chapters and books and re-organize as you wish. They are off course couple <code>gotchas</code>, namely the table formatting may not be perfect, the <code>note</code> and <code>warnings</code> may be a bit out of whack and the heading levels should probably be checked. All of these are actually good to check as a first pass through the docs to revamp the content and the way it is organized.<br />
One thing that we decided to do before talking about changing the format was to move our docs to a separate repository. What we wanted to do was to be able to release docs on a different time frame than the code release, as well as make any doc bug fixes go live as fast as possible and not wait for a code release (that's a long discussion...). With a documentation specific repo in place, we used Sphinx to create the proper directory structure and add the converted RST files. Then we created a project on Read The Docs and pointed to the github mirror of our Apache git repo. Pointing to the github <a href="https://github.com/apache/cloudstack-docs">mirror</a> allowed us to enable the nice github interaction that RTD provides. The new doc site looks like this.<br />
<div class="figure">
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdEI8XTdcpnrmeeLhkpNqYskM80Cmo8l5GAjlqX4sCrXr42LfhzBbmNBYSwPzKTUxT4dx0mn-CToCsA3961pVqP0gxd7Sic-H6bl34-_9NG7DIeayEdTsFyEU8XiL71ZBqKTI5iw/s1600/acsrtd.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdEI8XTdcpnrmeeLhkpNqYskM80Cmo8l5GAjlqX4sCrXr42LfhzBbmNBYSwPzKTUxT4dx0mn-CToCsA3961pVqP0gxd7Sic-H6bl34-_9NG7DIeayEdTsFyEU8XiL71ZBqKTI5iw/s1600/acsrtd.png" height="343" width="400" /></a></div>
<br />
<br /></div>
There is a bit more to it, as we actually created several repositories and used a RTD feature called <code>subprojects</code> to make all the docs live under the same CNAME <code>docs.cloudstack.apache.org</code>. This is still work in progress but in track for the 4.3 code release. I hope to be able to announce the new documentation sites shortly after 4.3 is announced.<br />
The final hurdle is the localization support. Sphinx provides utilities to generate POT files. They can then be uploaded to transifex and translation strings can be pulled to construct the translated docs. The big challenge that we are facing is to not loose the existing translation that were done from the docbook files. Strings may have changed. We are still investigating how to not loose all that work and get back on our feet to serve the translated docs. The Japanese translators have started to look at this.<br />
Overall the migration was easy, ReStructuredText is easy, Sphinx is also straigthfoward and Read The Docs provides a great hosting platform well integrated with Github. Once we go live, we will see if our doc contributors increase significantly, we have already seen a few pull requests come in, which is very encouraging.<br />
I will be talking about all of this at the <a href="http://conf.writethedocs.org/eu/2014/">Write The Docs</a> conference in Budapest on March 31st, april 1st. If you are in the area stop by :)Sebastien Goasguenhttp://www.blogger.com/profile/05197845236510805309noreply@blogger.com1tag:blogger.com,1999:blog-19879822.post-40099426288292527912014-03-04T15:07:00.001-08:002014-06-17T00:15:11.030-07:00Why CloudStack is not a Citrix project
<p>I was at CloudExpo Europe in London last week for the Open Cloud <a href="http://www.cloudexpoeurope.com/Content/Open-Cloud-Forum/3_46/">Forum</a> to give a tutorial on CloudStack tools. A decent crowd showed up, all carrying phones. Kind of problematic for a tutorial where I wanted the audience to install python packages and actually work :) Luckily I made it self-paced so you can follow at <a href="https://github.com/runseb/cloudstack-books/blob/master/en/ocftutorial.markdown">home</a>. Giles from <a href="http://shapeblue.com">Shapeblue</a> was there too and he was part of a panel on Open Cloud. He was told once again "But Apache CloudStack is a Citrix project !" This in itself is a paradox and as @jzb told me on twitter yesterday "Citrix donated CloudStack to Apache, the end". Apache projects do not have any company affiliation.</p>
<p>I don't blame folks, with all the vendors seemingly supporting OpenStack, it does seem that CloudStack is a one supporter project. The commit <a href="http://www.qyjohn.net/?p=3432">stats</a> are also pretty clear with 39% of commits coming from Citrix. This number is also probably higher since those stats are reporting gmail and apache as domain contributing 20 and 15% respectively, let's say 60% is from Citrix. But nonetheless, this is ignoring and mis-understanding what Apache is and looking at the glass half empty.</p>
<p>When Citrix donated CloudStack to the Apache Software Foundation (ASF) it relinquished control of the software and the brand. This actually put Citrix in a bind, not being able to easily promote the CloudStack project. Indeed, CloudStack is now a trademark of the ASF and Citrix had to rename their own product CloudPlatform (powered by Apache CloudStack). Citrix cannot promote CloudStack directly, it needs to get approval to donate sponsoring and follow the ASF trademark guidelines. Every committer and especially PMC members of Apache CloudStack are now supposed to work and protect the CloudStack brand as part of the ASF and make sure that any confusion is cleared. This is what I am doing here.</p>
<p>Of course when the software was donated, an initial set of committers was defined, all from Citrix and mostly from the former cloud.com startup. Part of the incubating process at the ASF is to make sure that we can add committers from other organization and attract a community. "Community over Code" is the bread and butter of ASF and so this is what we have all been working on, expanding the community outside Citrix, welcoming anyone who thinks CloudStack is interesting enough to contribute a little bit of time and effort. Looking at the glass half empty is saying that CloudStack is a Citrix project "Hey look 60% of their commits is from Citrix", looking at it half full like I do is saying "Oh wow, in a year since graduation, they have diversified the committer based, 40% are not from Citrix". Is 40% enough ? of course not, I wish it were the other way around, I wish Citrix were only a minority in the development of CloudStack.</p>
<p>Couple other numbers: Out of the 26 members of the project management committee (PMC) only seven are from Citrix and looking at mailing lists participation since the beginning of the year, 20% of the folks on the users mailing list and 25% on the developer list are from Citrix. We have diversified the community a great deal but the "hand-over", that moment when new community members are actually writing more code than the folks who started it, has not happened yet. A community is not just about writing code, but I will give it to you that it is not good for a single company to "control" 60% of the development, this is not where we/I want to be.</p>
<p>This whole discussion is actually against Apache's modus operandi. Since one of the biggest tenant of the foundation is non-affiliation. When I participate on the list I am Sebastien, I am not a Citrix employee. Certainly this can put some folks in conflicting situations at times, but the bottom line is that we do not and should not take into account company affiliation when working and making decisions for the project. But if you really want some company name dropping, let's do an ASF faux-pas and let's look at a few features:</p>
<p>The Nicira/NSX and OpenDaylight SDN integration was done by Schuberg Phillis, the OpenContrail plugin was done by Juniper, Midokura created it's own plugin for Midonet and Stratosphere as well, giving us a great SDN coverage. The LXC integration was done by Gilt, Klarna is contributing in the ecosystem with the vagrant and packer plugins, CloudOps has been doing terrific job with Chef recipes, Palo-Alto networks integration and Netscaler support, a google summer of code intern did a brand new LDAP plugin and another GSoC did the GRE support for KVM. RedHat contributed the Gluster plugin and PCExtreme contributed the Ceph interface while Basho of course contributed the S3 plugin for secondary storage as well as major design decisions on the storage refactor. The Solidfire plugin was done by, well Solidfire and Netapp has developed a plugin as well for their virtual storage console. NTT contributed the CloudFoundry interface via BOSH. On the user side, Shapeblue is leading the user support company. So no it's not just Citrix.</p>
<p>Are all these companies members of the CloudStack project ? No. There is no such thing as a company being a member of an ASF project. There is no company affiliation, there is no lock in, just a bunch of guys trying to make good software and build a community. And yes, I work for Citrix and my job here will be done when Citrix only contributes 49% of the commits. Citrix is paying me to make sure they loose control of the software, that a healthy ecosystem develops and that CloudStack keeps on becoming a strong and vibrant Apache project. I hope one day folks will understand what CloudStack has become, an ASF project, like HTTP, Hadoop, Mesos, Ant, Maven, Lucene, Solr and 150 other projects. Come to Denver for #apachecon you will see ! The end.</p>
Sebastien Goasguenhttp://www.blogger.com/profile/05197845236510805309noreply@blogger.com2tag:blogger.com,1999:blog-19879822.post-19451485944026427002014-01-21T04:18:00.000-08:002014-01-21T04:18:44.124-08:00PaaS with CloudStack<h2 id="a-few-talks-from-ccc-in-amsterdam">
A few talks from CCC in Amsterdam</h2>
In November at the CloudStack Collaboration Conference I was pleased to see several talks on PaaS. We had <a href="http://www.youtube.com/watch?v=VOoPCs7Vq-k&list=UU9VU9uvQTOkw29LICWSRhyw">Uri Cohen</a> (@uri1803) from <a href="http://www.gigaspaces.com/">Gigaspaces</a>, <a href="http://www.youtube.com/watch?v=2taNUzHFxzU&list=UU9VU9uvQTOkw29LICWSRhyw">Marc-Elian Begin</a> (@lemeb) from <a href="http://sixsq.com/">Sixsq</a> and <a href="http://www.youtube.com/watch?v=nrXFwCewLDw&list=UU9VU9uvQTOkw29LICWSRhyw">Alex Heneveld</a> (@ahtweetin) from <a href="http://www.cloudsoftcorp.com/">CloudSoft</a>. We also had some related talks -depending on your definition of PaaS- with talks about <a href="http://www.youtube.com/watch?v=qcMUs2CeqUQ&list=UU9VU9uvQTOkw29LICWSRhyw">Docker</a> and <a href="http://www.youtube.com/watch?v=saiZ3cE6MkE&list=UU9VU9uvQTOkw29LICWSRhyw">Vagrant</a>.<br />
<h2 id="paas-variations">
PaaS variations</h2>
The differences between PaaS solutions is best explained by this picture from <a href="http://aws.amazon.com/application-management/">AWS FAQ</a> about application management. <br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzZjENWP2B5wcCx7dVwiJCUDr5mgjeV0fHGhantx9jgDrWZDBU9_Ell_gJBBLb74T8sKBpHcVPc0c_s_cwqHTdOKbKJIN_vweRBXmdtyC3CkuLqNzfn-YputWOjgeaiASG4UCUXw/s1600/app-svcs-comparison-graphic.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzZjENWP2B5wcCx7dVwiJCUDr5mgjeV0fHGhantx9jgDrWZDBU9_Ell_gJBBLb74T8sKBpHcVPc0c_s_cwqHTdOKbKJIN_vweRBXmdtyC3CkuLqNzfn-YputWOjgeaiASG4UCUXw/s320/app-svcs-comparison-graphic.png" height="156" width="400" /></a></div>
There is clearly a spectrum that goes from operational control to pure application deployment. We could argue that true PaaS abstracts the operational details and that management of the underlying infrastructure should be totally hidden, that said, automation of virtual infrastructure deployment has reached such a sophisticated state that it blurs the definition between IaaS and PaaS. Not suprisingly AWS offers services that covers the entire spectrum.<br />
Since I am more on the operation side, I tend to see a PaaS as an infrastructure automation framework. For instance I look for tools to deploy a MongoDB cluster or a RiakCS cluster. I am not looking for an abstract plaform that has Monogdb pre-installed and where I can turn a knob to increase the size of the cluster or manage my shards. An application person will prefer to look at something like Google App Engine and it's open source version <a href="http://www.appscale.com/">Appscale</a>. I will get back to all these differences in a next post on PaaS but this <a href="http://www.infoworld.com/d/cloud-computing/paas-isnt-dying-its-becoming-part-of-iaas-234351?utm_source=twitterfeed&utm_medium=twitter">article</a> by @DavidLinthicum that just came out is a good read.<br />
<h2 id="support-for-cloudstack">
Support for CloudStack</h2>
What is interesting for the CloudStack community is to look at the support for CloudStack in all these different solutions wherever they are in the application management spectrum.<br />
<ul>
<li>Cloudify from Gigaspaces was all over twitter about their support for OpenStack, and I was getting slightly bothered with the lack of CloudStack support. That's why it was great to see Uri Cohen in Amstredam. He delivered a great talk and he gave me a demo of Cloudify. I was very impressed of course by the slick UI but overall by the ability to provision complete application/infrastructure definitions on clouds. Underlying it uses Apache jclouds, so there was no reason that it could not talk to CloudStack. Over christmas Uri did a terrific job and the CloudStack support is now tested and documented. It works not only on the commercial version from Citrix <a href="http://www.cloudifysource.org/guide/2.7/setup/configuring_cloudstack">CloudPlatform</a> but also with Apache <a href="http://www.cloudifysource.org/guide/2.7/setup/configuring_exoscale">CloudStack</a>. And of course it works with my neighbors Cloud <a href="http://exoscale.ch/">exoscale</a></li>
<li>Slipstream is not widely known but worth a look. At CCC @lemeb <a href="http://www.youtube.com/watch?v=2taNUzHFxzU&list=UU9VU9uvQTOkw29LICWSRhyw">demoed</a> a CloudStack driver. Since then, they now offer an <a href="https://slipstream.sixsq.com/">hosted</a> version of their slipstream cloud orchestration framework which turns out to be hosted on exoscale CloudStack cloud. Slipstream is more of a Cloud broker than a PaaS but it automates application deployment on multiple clouds abstracting the various cloud APIs and offering application templates for deployments of virtual infrastructure. Check it out.</li>
<li>Cloudsoft main application deployment engine is <a href="http://brooklyncentral.github.io/">brooklyn</a>, it originated from Alex Heneveld contribution to Apache Whirr that I wrote about couple <a href="http://sebgoa.blogspot.ch/2013/07/apache-whirr-and-cloudstack-for-big.html">times</a>. But it can use OpenShift for additional level of PaaS. I will need to check with Alex how they are doing this, as I believe Openshift uses LXC. Since CloudStack has LXC support, one ought to be able to use Brooklyn to deploy a LXC cluster on CloudStack and then use OpenShift to manage deployed applications.</li>
<li>A quick note on OpenShift. As far as I understand, it actually uses a static cluster. The scalability comes from the use of containes in the nodes. So technically you could create an OpenShift cluster in CloudStack, but I don't think we will see OpenShift talking directly to the CloudStack API to add nodes. Openshift bypasses the IaaS APIs. Of course I have not looked at it in a while and I may be wrong :)</li>
<li>Talking about PaaS for <a href="http://vagrantup.com/">Vagrant</a> is probably a bit far fetched, but it fits the infrastructure deployment criteria and could be compared with <a href="http://aws.amazon.com/opsworks/getting-started/">AWS OpsWorks</a>. Vagrant helps to define reproducible machines so that devs and ops can actually work on the same base servers. But Vagrant with its plugins can also help deployment on public clouds, and can handle multiple server definitions. So one can look at a Vagrantfile as a template defintion for a virtual infrastructure deployment. As a matter of fact, there are many Vagrant boxes out there to deploy things like Apache Mesos clusters, MongoDB, RiakCS clusters etc. It's not meant to manage that stack in production but at a minimum can help develop it. Vagrant has a CloudStack plugin demoed by <a href="http://www.youtube.com/watch?v=saiZ3cE6MkE&list=UU9VU9uvQTOkw29LICWSRhyw">Hugo Correia</a> from Klarna at CCC. Exoscale took the bait and created a set of -<a href="https://www.exoscale.ch/syslog/2013/12/18/exoscale-vagrant/">exoboxes</a>- that's real gold for developers deploying in exoscale and any CloudStack provider should follow suit.</li>
<li>Which brings me on to <a href="http://docker.io/">Docker</a>, there is currently no support for Docker in CloudStack. We do have LXC <a href="https://cwiki.apache.org/confluence/display/CLOUDSTACK/LXC+Support+in+Cloudstack">support</a> therefore it would not be to hard to have a 'docker' cluster in CloudStack. You could even install docker within an image and deploy that on KVM or Xen. Of course some would argue that using containers within VMs defeats the purpose. In any case, with the Docker remote API you could then manage your containers. OpenStack already has a Docker <a href="https://wiki.openstack.org/wiki/Docker">integration</a>, we will dig deeper into Docker functionality to see how best to integrate it in CloudStack.</li>
<li>AWS as I mentioned has several PaaS like layers with OpsWorks, CloudFormation, Beanstalk. CloudStack has an EC2 interface but also has a third party solution to enabled CloudFormation. This is still under development but pretty close to full functionality, check out <a href="https://github.com/stackmate/stackmate">stackmate</a> and its web interface <a href="https://github.com/stackmate/stacktician">stacktician</a>. With a CF interface to CloudStack we could see a OpSWork and a Beanstalk interface coming in the future.</li>
<li>Finally, not present at CCC but the leader of PaaS for enterprise is <a href="http://www.cloudfoundry.com/">CloudFoundry</a>. I am going to see Andy Piper (@andypiper) in <a href="http://lanyrd.com/2014/lcs2014/">London</a> next week and will make sure to talk to him about the recent CloudStack support that was merged in the cloudfoundry community <a href="https://github.com/cloudfoundry-community/bosh-cloudstack-cpi">repo</a>. It came from folks in Japan and I have not had time to test it. Certainly we as a community should look at this very closely to make sure there is outstanding support for CloudFoundry in ACS.</li>
</ul>
It is not clear what the frontier between PaaS and IaaS is, it is highly dependent on the context, who you are and what you are trying to achieve. But CloudStack offers several interfaces to PaaS or shall I say PaaS offer several connectors to CloudStack :)Sebastien Goasguenhttp://www.blogger.com/profile/05197845236510805309noreply@blogger.com0tag:blogger.com,1999:blog-19879822.post-8201413563197397602013-12-19T00:15:00.001-08:002013-12-19T00:21:50.862-08:00Clojure with CloudStack<h1 id="clostack">CloStack</h1>
<p>CloStack is a Clojure client for Apache CloudStack. <a href="http://clojure.org">Clojure</a> is a dynamic programming language for the Java Virtual Machine (JVM). It is compiled directly in JVM bytecode but offers a dynamic and interactive nature of an interpreted language like Python. Clojure is a dialect of LISP and as such is mostly a functional programming language.</p>
<p>You can try Clojure in your <a href="http://tryclj.com">browser</a> and get familiar with its read eval loop (REPL). To get started, you can follow the <a href="http://moxleystratton.com/clojure/clojure-tutorial-for-the-non-lisp-programmer">tutorial</a> for non-LISP programmers through this web based REPL.</p>
<p>To give you a taste for it, here is how you would <code>2</code> and <code>2</code>:</p>
<pre><code>user=> (+ 2 2)
4</code></pre>
<p>And how you would define a function:</p>
<pre><code>user=> (defn f [x y]
#_=> (+ x y))
#'user/f
user=> (f 2 3)
5</code></pre>
<p>This should give you a taste of functional programming :)</p>
<h2 id="install-leinigen">Install Leinigen</h2>
<p><a href="https://github.com/technomancy/leiningen">leiningen</a> is a tool for managing Clojure projects easily. With <code>lein</code> you can create the skeleton of clojure project as well as start a read eval loop (REPL) to test your code.</p>
<p>Installing the latest version of leiningen is easy, get the <a href="https://raw.github.com/technomancy/leiningen/stable/bin/lein">script</a> and set it in your path. Make it executable and your are done.</p>
<p>The first time your run <code>lein repl</code> it will boostrap itself:</p>
<pre><code>$ lein repl
Downloading Leiningen to /Users/sebgoa/.lein/self-installs/leiningen-2.3.4-standalone.jar now...
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 13.0M 100 13.0M 0 0 1574k 0 0:00:08 0:00:08 --:--:-- 2266k
nREPL server started on port 58633 on host 127.0.0.1
REPL-y 0.3.0
Clojure 1.5.1
Docs: (doc function-name-here)
(find-doc "part-of-name-here")
Source: (source function-name-here)
Javadoc: (javadoc java-object-or-class-here)
Exit: Control+D or (exit) or (quit)
Results: Stored in vars *1, *2, *3, an exception in *e
user=> exit
Bye for now!</code></pre>
<h2 id="download-clostack">Download CloStack</h2>
<p>To install CloStack, clone the github <a href="https://github.com/pyr/clostack.git">repository</a> and start <code>lein repl</code>:</p>
<pre><code>git clone https://github.com/pyr/clostack.git
$ lein repl
Retrieving codox/codox/0.6.4/codox-0.6.4.pom from clojars
Retrieving codox/codox.leiningen/0.6.4/codox.leiningen-0.6.4.pom from clojars
Retrieving leinjacker/leinjacker/0.4.1/leinjacker-0.4.1.pom from clojars
Retrieving org/clojure/core.contracts/0.0.1/core.contracts-0.0.1.pom from central
Retrieving org/clojure/core.unify/0.5.3/core.unify-0.5.3.pom from central
Retrieving org/clojure/clojure/1.4.0/clojure-1.4.0.pom from central
Retrieving org/clojure/core.contracts/0.0.1/core.contracts-0.0.1.jar from central
Retrieving org/clojure/core.unify/0.5.3/core.unify-0.5.3.jar from central
Retrieving org/clojure/clojure/1.4.0/clojure-1.4.0.jar from central
Retrieving codox/codox/0.6.4/codox-0.6.4.jar from clojars
Retrieving codox/codox.leiningen/0.6.4/codox.leiningen-0.6.4.jar from clojars
Retrieving leinjacker/leinjacker/0.4.1/leinjacker-0.4.1.jar from clojars
Retrieving org/clojure/clojure/1.3.0/clojure-1.3.0.pom from central
Retrieving org/clojure/data.json/0.2.2/data.json-0.2.2.pom from central
Retrieving http/async/client/http.async.client/0.5.2/http.async.client-0.5.2.pom from clojars
Retrieving com/ning/async-http-client/1.7.10/async-http-client-1.7.10.pom from central
Retrieving io/netty/netty/3.4.4.Final/netty-3.4.4.Final.pom from central
Retrieving org/clojure/data.json/0.2.2/data.json-0.2.2.jar from central
Retrieving com/ning/async-http-client/1.7.10/async-http-client-1.7.10.jar from central
Retrieving io/netty/netty/3.4.4.Final/netty-3.4.4.Final.jar from central
Retrieving http/async/client/http.async.client/0.5.2/http.async.client-0.5.2.jar from clojars
nREPL server started on port 58655 on host 127.0.0.1
REPL-y 0.3.0
Clojure 1.5.1
Docs: (doc function-name-here)
(find-doc "part-of-name-here")
Source: (source function-name-here)
Javadoc: (javadoc java-object-or-class-here)
Exit: Control+D or (exit) or (quit)
Results: Stored in vars *1, *2, *3, an exception in *e
user=> exit</code></pre>
<p>The first time that you start the REPL lein will download all the dependencies of <code>clostack</code>.</p>
<h2 id="prepare-environment-variables-and-make-your-first-clostack-call">Prepare environment variables and make your first <code>clostack</code> call</h2>
<p>Export a few environmen variables to define the cloud you will be using, namely:</p>
<pre><code>export CLOUDSTACK_ENDPOINT=http://localhost:8080/client/api
export CLOUDSTACK_API_KEY=HGWEFHWERH8978yg98ysdfghsdfgsagf
export CLOUDSTACK_API_SECRET=fhdsfhdf869guh3guwghseruig</code></pre>
<p>Then relaunch the REPL</p>
<pre><code>$lein repl
nREPL server started on port 59890 on host 127.0.0.1
REPL-y 0.3.0
Clojure 1.5.1
Docs: (doc function-name-here)
(find-doc "part-of-name-here")
Source: (source function-name-here)
Javadoc: (javadoc java-object-or-class-here)
Exit: Control+D or (exit) or (quit)
Results: Stored in vars *1, *2, *3, an exception in *e
user=> (use 'clostack.client)
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
nil</code></pre>
<p>You can safely discard the warning message which only indicates that 'clostack' is meant to be used as a library in a clojure project.<br />Define a client to your CloudStack endpoint</p>
<pre><code>user=> (def cs (http-client))
#'user/cs</code></pre>
<p>And call an API like so:</p>
<pre><code>user=> (list-zones cs)
{:listzonesresponse {:count 1, :zone [{:id "1128bd56-b4d9-4ac6-a7b9-c715b187ce11", :name "CH-GV2", :networktype "Basic", :securitygroupsenabled true, :allocationstate "Enabled", :zonetoken "ccb0a60c-79c8-3230-ab8b-8bdbe8c45bb7", :dhcpprovider "VirtualRouter", :localstorageenabled true}]}}</code></pre>
<p>To explore the API calls that you can make, the REPL features tab completion. Enter <code>list</code> or <code>de</code> and press the tab key you should see:</p>
<pre><code>user=> (list
list list* list-accounts list-async-jobs
list-capabilities list-disk-offerings list-event-types list-events
list-firewall-rules list-hypervisors list-instance-groups list-ip-forwarding-rules
list-iso-permissions list-isos list-lb-stickiness-policies list-load-balancer-rule-instances
list-load-balancer-rules list-network-ac-ls list-network-offerings list-networks
list-os-categories list-os-types list-port-forwarding-rules list-private-gateways
list-project-accounts list-project-invitations list-projects list-public-ip-addresses
list-remote-access-vpns list-resource-limits list-security-groups list-service-offerings
list-snapshot-policies list-snapshots list-ssh-key-pairs list-static-routes
list-tags list-template-permissions list-templates list-virtual-machines
list-volumes list-vp-cs list-vpc-offerings list-vpn-connections
list-vpn-customer-gateways list-vpn-gateways list-vpn-users list-zones
list?
user=> (de
dec dec' decimal? declare def
default-data-readers definline definterface defmacro defmethod
defmulti defn defn- defonce defprotocol
defrecord defreq defstruct deftype delay
delay? delete-account-from-project delete-firewall-rule delete-instance-group delete-ip-forwarding-rule
delete-iso delete-lb-stickiness-policy delete-load-balancer-rule delete-network delete-network-acl
delete-port-forwarding-rule delete-project delete-project-invitation delete-remote-access-vpn delete-security-group
delete-snapshot delete-snapshot-policies delete-ssh-key-pair delete-static-route delete-tags
delete-template delete-volume delete-vpc delete-vpn-connection delete-vpn-customer-gateway
delete-vpn-gateway deliver denominator deploy-virtual-machine deref
derive descendants destroy-virtual-machine destructure detach-iso
detach-volume</code></pre>
<p>To pass arguments to a call follow the syntax:</p>
<pre><code>user=> (list-templates cs :templatefilter "executable")</code></pre>
<h2 id="start-a-virtual-machine">Start a virtual machine</h2>
<p>To deploy a virtual machine you need to get the <code>serviceofferingid</code> or instance type, the <code>templateid</code> also known as the image id and the <code>zoneid</code>, the call is then very similar to CloudMonkey and returns a <code>jobid</code></p>
<pre><code>user=> (deploy-virtual-machine cs :serviceofferingid "71004023-bb72-4a97-b1e9-bc66dfce9470" :templateid "1d961c82-7c8c-4b84-b61b-601876dab8d0" :zoneid "1128bd56-b4d9-4ac6-a7b9-c715b187ce11")
{:deployvirtualmachineresponse {:id "d0a887d2-e20b-4b25-98b3-c2995e4e428a", :jobid "21d20b5c-ea6e-4881-b0b2-0c2f9f1fb6be"}}</code></pre>
<p>You can pass additional parameters to the <code>deploy-virtual-machine</code> call, such as the <code>keypair</code> and the <code>securitygroupname</code>:</p>
<pre><code>user=> (deploy-virtual-machine cs :serviceofferingid "71004023-bb72-4a97-b1e9-bc66dfce9470" :templateid "1d961c82-7c8c-4b84-b61b-601876dab8d0" :zoneid "1128bd56-b4d9-4ac6-a7b9-c715b187ce11" :keypair "exoscale")
{:deployvirtualmachineresponse {:id "b5fdc41f-e151-43e7-a036-4d87b8536408", :jobid "418026fc-1009-4e7a-9721-7c9ad47b49e4"}}</code></pre>
<p>To query the asynchronous job, you can use the <code>query-async-job</code> api call:</p>
<pre><code>user=> (query-async-job-result cs :jobid "418026fc-1009-4e7a-9721-7c9ad47b49e4")
{:queryasyncjobresultresponse {:jobid "418026fc-1009-4e7a-9721-7c9ad47b49e4", :jobprocstatus 0, :jobinstancetype "VirtualMachine", :accountid "b8c0baab-18a1-44c0-ab67-e24049212925", :jobinstanceid "b5fdc41f-e151-43e7-a036-4d87b8536408", :created "2013-12-16T12:25:21+0100", :jobstatus 0, :jobresultcode 0, :cmd "com.cloud.api.commands.DeployVMCmd", :userid "968f6b4e-b382-4802-afea-dd731d4cf9b9"}}</code></pre>
<p>And finally to destroy the virtual machine you would pass the <code>id</code> of the VM to the <code>destroy-virtual-machine</code> call like so:</p>
<pre><code>user=> (destroy-virtual-machine cs :id "d0a887d2-e20b-4b25-98b3-c2995e4e428a")
{:destroyvirtualmachineresponse {:jobid "8fc8a8cf-9b54-435c-945d-e3ea2f183935"}}</code></pre>
<p>With these simple basics you can keep on exploring <code>clostack</code> and the CloudStack API.</p>
<h2 id="use-clostack-within-your-own-clojure-project">Use <code>CloStack</code> within your own clojure project</h2>
<p><h3>Hello World in clojure</h3></p>
<p>To write your own clojure project that makes user of <code>clostack</code>, use <code>leiningen</code> to create a project skeleton</p>
<pre><code>lein new toto</code></pre>
<p><code>Lein</code> will automatically create a <code>src/toto/core.clj</code> file, edit it to replace the function <code>foo</code> with <code>-main</code>. This dummy function returns <code>Hellow World !</code>. Let's try to execute it. First we will need to define the <code>main</code> namespace in the <code>project.clj</code> file. Edit it like so:</p>
<p>defproject toto "0.1.0-SNAPSHOT" :description "FIXME: write description" :url "http://example.com/FIXME" :license {:name "Eclipse Public License" :url "http://www.eclipse.org/legal/epl-v10.html"} :main toto.core :dependencies [[org.clojure/clojure "1.5.1"]])</p>
<p>Note the <code>:main toto.core</code></p>
<p>You can now execute the code with <code>lein run john</code> . Indeed if you check the <code>-main</code> function in <code>src/toto/core.clj</code> you will see that it takes an argument. Surprisingly you should see the following output:</p>
<pre><code>$ lein run john
john Hello, World!</code></pre>
<p>Let's now add the CloStack dependency and modify the <code>main</code> function to return the zone of the CloudStack cloud.</p>
<p><h3>Adding the Clostack dependency </h3></p>
<p>Edit the <code>project.clj</code> to add a dependency on <code>clostack</code> and a few logging packages:</p>
<pre><code>:dependencies [[org.clojure/clojure "1.5.1"]
[clostack "0.1.3"]
[org.clojure/tools.logging "0.2.6"]
[org.slf4j/slf4j-log4j12 "1.6.4"]
[log4j/apache-log4j-extras "1.0"]
[log4j/log4j "1.2.16"
:exclusions [javax.mail/mail
javax.jms/jms
com.sun.jdkmk/jmxtools
com.sun.jmx/jmxri]]])
</code></pre>
<p><code>lein</code> should have created a <code>resources</code> directory. In it, create a <code>log4j.properties</code> file like so:</p>
<pre><code>$ more log4j.properties
# Root logger option
log4j.rootLogger=INFO, stdout
# Direct log messages to stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n</code></pre>
<p>A discussion on logging is beyond the scope of this recipes, we merely add it in the configuration for a complete example.</p>
<p>Now you can edit the code in <code>src/toto/core.clj</code> with some basic calls.</p>
<pre><code>(ns testclostack.core
(:require [clostack.client :refer [http-client list-zones]]))
(defn foo
"I don't do a whole lot."
[x]
(println x "Hello, World!"))
(def cs (http-client))
(defn -main [args]
(println (list-zones cs))
(println args "Hey Wassup")
(foo args)
)</code></pre>
<p>Simply run this clojure code with <code>lein run joe</code> in the source of your project. And that's it, you have sucessfully discovered the very basics of Clojure and used the CloudStack client <code>clostack</code> to write your first Clojure code. Now for something more significant, look at <a href="http://palletops.com">Pallet</a></p>
Sebastien Goasguenhttp://www.blogger.com/profile/05197845236510805309noreply@blogger.com0tag:blogger.com,1999:blog-19879822.post-57830479464043265212013-12-18T12:32:00.000-08:002013-12-18T12:32:54.875-08:002014 Cloud Predictions<p><b>Warning:</b> this is written with a glass of wine on one hand, two days before vacation ...:)</p>
<p>1. CloudStack will abandon semantic versioning and adopt super hero names for its releases, this will make upgrade paths more understandable.</p>
<p>2. Someone will take Euca API server and stick CloudStack backend beneath it, adding Opennebula packaging will make this the best cloud distro of all.</p>
<p>3. I will finally make sense of <a href="http://netflix.github.io/#repo">NetflixOSS</a> plethora of software and reach nirvana by integrating CloudStack in Asgard.</p>
<p>4. AWS will opensource its software killing OpenStack, and we will realize that in fact they use CloudStack with Euca in front.</p>
<p>5. I will understand what NFV, VNF and SDN really mean and come up with a new acronym that will set twitter on fire.</p>
<p>6. We will actually see some code in <a href="https://github.com/stackforge/solum">Solum</a>.</p>
<p>7. bitcoin will crash and come back up at least five times.</p>
<p>8. Citrix stock will jump 100% on acquisition by IBM.</p>
<p>9. My boss will stop asking me for statistics.</p>
<p>10. Facebook will die on a Snowden revelation. </p>
<p>I will stop at 10 otherwise this could go on all night :)</p>
<p>Happy Holidays everyone </p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1hazfleGPAFaFUbg_nXKdHcfUfa_gC_Renl4knDQna0bXogcaJatBWIehqdXeaR0G2RInqQ4pUVk-OU-69_8rKsPD_LFWJhWGECcs2lqItyncEN6LLcY4oFsZnlTBX-h0AyRllA/s1600/santa.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1hazfleGPAFaFUbg_nXKdHcfUfa_gC_Renl4knDQna0bXogcaJatBWIehqdXeaR0G2RInqQ4pUVk-OU-69_8rKsPD_LFWJhWGECcs2lqItyncEN6LLcY4oFsZnlTBX-h0AyRllA/s320/santa.jpg" /></a></div>
Sebastien Goasguenhttp://www.blogger.com/profile/05197845236510805309noreply@blogger.com3tag:blogger.com,1999:blog-19879822.post-67899476785257025812013-12-06T04:58:00.000-08:002013-12-06T05:23:39.865-08:00Veewee, Vagrant and CloudStack<p>Coming back from CloudStack <a href="http://cloudstackcollab.org">conference</a> the feeling that this is not about building clouds got stronger. This is really about what to do with them and how they bring you agility, faster-time to market and allow you to focus on innovation in your core business. A large component of this is Culture and a change of how we do IT. The DevOps movement is the embodiment of this change. Over in Amsterdam I was stoked to meet with folks that I had seen at other locations throughout Europe in the last 18 months. Folks from PaddyPower, SchubergPhilis, Inuits who all embrace DevOps. I also met new folks, including Hugo Correia from <a href="https://klarna.com">Klarna</a> (CloudStack users) who came by to talk about Vagrant-cloudstack plugin. His talk and a demo by Roland Kuipers from Schuberg was enough to kick my butt and get me to finally check out Vagrant. I sprinkled a bit of Veewee and of course some CloudStack on top of it all. Have fun reading.</p>
<p>Automation is key to a reproducible, failure-tolerant infrastructure. Cloud administrators should aim to automate all steps of building their infrastructure and be able to re-provision everything with a single click. This is possible through a combination of configuration management, monitoring and provisioning tools. To get started in created appliances that will be automatically configured and provisioned, two tools stand out in the arsenal: Veewee and Vagrant.</p>
<p><b>Veewee</b>: <a href="https://github.com/jedi4ever/veewee">Veewee</a> is a tool to easily create appliances for different hypervisors. It fetches the .iso of the distribution you want and build the machine with a kickstart file. It integrates with providers like VirtualBox so that you can build these appliances on your local machine. It supports most commonly used OS templates. Coupled with virtual box it allows admins and devs to create reproducible base appliances. Getting started with veewee is a 10 minutes exericse. The README is great and there is also a very nice <a href="http://cbednarski.com/articles/veewee/">post</a> that guides you through your first box building.</p>
<p>Most folks will have no issues cloning Veewee from github and building it, you will need ruby 1.9.2 or above. You can get it via `rvm` or your favorite ruby version manager.</p>
<pre>
git clone https://github.com/jedi4ever/veewee
gem install bundler
bundle install
</pre>
<p>Setting up an alias is handy at this point `alias veewee="bundle exec veewee"`. You will need a virtual machine provider (e.g VirtualBox, VMware Fusion, Parallels, KVM). I personnaly use VirtualBox but pick one and install it if you don't have it already. You will then be able to start using `veewee` on your local machine. Check the sub-commands available (for virtualbox):</p>
<pre>
$ veewee vbox
Commands:
veewee vbox build [BOX_NAME] # Build box
veewee vbox copy [BOX_NAME] [SRC] [DST] # Copy a file to the VM
veewee vbox define [BOX_NAME] [TEMPLATE] # Define a new basebox starting from a template
veewee vbox destroy [BOX_NAME] # Destroys the virtualmachine that was built
veewee vbox export [BOX_NAME] # Exports the basebox to the vagrant format
veewee vbox halt [BOX_NAME] # Activates a shutdown the virtualmachine
veewee vbox help [COMMAND] # Describe subcommands or one specific subcommand
veewee vbox list # Lists all defined boxes
veewee vbox ostypes # List the available Operating System types
veewee vbox screenshot [BOX_NAME] [PNGFILENAME] # Takes a screenshot of the box
veewee vbox sendkeys [BOX_NAME] [SEQUENCE] # Sends the key sequence (comma separated) to the box. E.g for testing the :boot_cmd_sequence
veewee vbox ssh [BOX_NAME] [COMMAND] # SSH to box
veewee vbox templates # List the currently available templates
veewee vbox undefine [BOX_NAME] # Removes the definition of a basebox
veewee vbox up [BOX_NAME] # Starts a Box
veewee vbox validate [BOX_NAME] # Validates a box against vagrant compliancy rules
veewee vbox winrm [BOX_NAME] [COMMAND] # Execute command via winrm
Options:
[--debug] # enable debugging
-w, --workdir, [--cwd=CWD] # Change the working directory. (The folder containing the definitions folder).
# Default: /Users/sebgoa/Documents/gitforks/veewee
</pre>
<p>Pick a template from the `templates` directory and `define` your first box:</p>
<pre>
veewee vbox define myfirstbox CentOS-6.5-x86_64-minimal
</pre>
<p>
You should see that a `defintions/` directory has been created, browse to it and inspect the `definition.rb` file. You might want to comment out some lines, like removing `chef` or `puppet`. If you don't change anything and build the box, you will then be able to `validate` the box with `veewee vbox validate myfirstbox`. To build the box simply do:
</p>
<pre>
veewee vbox build myfristbox
</pre>
<p>
Everything should be successfull, and you should see a running VM in your virtual box UI. To export it for use with `Vagrant`, `veewee` provides an export mechanism (really a VBoxManage command): `veewee vbox export myfirstbox`. At the end of the export, a .box file should be present in your directory.
</p>
<p><b>Vagrant:</b> Picking up from where we left with `veewee`, we can now add the box to <a href="https://github.com/jedi4ever/veewee/blob/master/doc/vagrant.md">Vagrant</a> and customize it with shell scripts or much better, with Puppet recipes or Chef cookbooks. First let's add the box file to Vagrant:</p>
<pre>
vagrant box add 'myfirstbox' '/path/to/box/myfirstbox.box'
</pre>
<p>Then in a directory of your choice, create the Vagrant "project":</p>
<pre>
vagrant init 'myfirstbox'
</pre>
<p>This will create a `Vagrantfile` that we will later edit to customize the box. You can boot the machine with `vagrant up` and once it's up , you can ssh to it with `vagrant ssh`.</p>
<p>While `veewee` is used to create a base box with almost no <a href="https://github.com/jedi4ever/veewee/blob/master/doc/customize.md">customization</a> (except potentially a chef and/or puppet client), `vagrant` is used to customize the box using the Vagrantfile. For example, to customize the `myfirstbox` that we just built, set the memory to 2 GB, add a host-only interface with IP 192.168.56.10, use the apache2 Chef cookbook and finally run a `boostrap.sh` script, we will have the following `Vagrantfile`:</p>
<pre>
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# Every Vagrant virtual environment requires a box to build off of.
config.vm.box = "myfirstbox"
config.vm.provider "virtualbox" do |vb|
vb.customize ["modifyvm", :id, "--memory", 2048]
end
#host-only network setup
config.vm.network "private_network", ip: "192.168.56.10"
# Chef solo provisioning
config.vm.provision "chef_solo" do |chef|
chef.add_recipe "apache2"
end
#Test script to install CloudStack
#config.vm.provision :shell, :path => "bootstrap.sh"
end
</pre>
<p>The cookbook will be in a `cookbooks` directory and the boostrap script will be in the root directory of this vagrant definition. For more information, check the Vagrant <a href="http://www.vagrantup.com">website</a> and experiment. </p>
<p><b>Vagrant and CloudStack</b>: What is very interesting with Vagrant is that you can use various plugins to deploy machines on public clouds. There is a `vagrant-aws` plugin and of course a `vagrant-cloudstack` plugin. You can get the latest CloudStack plugin from <a href="https://github.com/klarna/vagrant-cloudstack">github</a>. You can install it directly with the `vagrant` command line:</p>
<pre>
vagrant plugin install vagrant-cloudstack
</pre>
<p>Or if you are building it from source, clone the git repository, build the gem and install it in `vagrant`</p>
<pre>
git clone https://github.com/klarna/vagrant-cloudstack.git
gem build vagrant-cloudstack.gemspec
gem install vagrant-cloudstack-0.1.0.gem
vagrant plugin install /Users/sebgoa/Documents/gitforks/vagrant-cloudstack/vagrant-cloudstack-0.1.0.gem
</pre>
<p>The only drawback that I see is that one would want to upload his local box (created from the previous section) and use it. Instead one has to create `dummy boxes` that use existing templates available on the public cloud. This is easy to do, but creates a gap between local testing and production deployments. To build a dummy box simply create a `Vagrantfile` file and a `metadata.json` file like so:</p>
<pre>
$ cat metadata.json
{
"provider": "cloudstack"
}
$ cat Vagrantfile
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
config.vm.provider :cloudstack do |cs|
cs.template_id = "a17b40d6-83e4-4f2a-9ef0-dce6af575789"
end
end
</pre>
<p>Where the `cs.template_id` is a uuid of a CloudStack template in your cloud. CloudStack users will know how to easily get those uuids with `CloudMonkey`. Then create a `box` file with `tar cvzf cloudstack.box ./metadata.json ./Vagrantfile`. Note that you can add additional CloudStack parameters in this box definition like the host,path etc (something to think about :) ). Then simply add the box in `Vagrant` with:</p>
<pre>
vagrant box add ./cloudstack.box
</pre>
<p>You can now create a new `Vagrant` project:</p>
<pre>
mkdir cloudtest
cd cloudtest
vagrant init
</pre>
<p>And edit the newly created `Vagrantfile` to use the `cloudstack` box. Add additional parameters like `ssh` configuration, if the box does not use the default from `Vagrant`, plus `service_offering_id` etc. Remember to use your own api and secret keys and change the name of the box to what you created. For example on <a href="http://www.exoscale.ch">exoscale</a>:</p>
<pre>
# -*- mode: ruby -*-
# vi: set ft=ruby :
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# Every Vagrant virtual environment requires a box to build off of.
config.vm.box = "cloudstack"
config.vm.provider :cloudstack do |cs, override|
cs.host = "api.exoscale.ch"
cs.path = "/compute"
cs.scheme = "https"
cs.api_key = "PQogHs2sk_3..."
cs.secret_key = "...NNRC5NR5cUjEg"
cs.network_type = "Basic"
cs.keypair = "exoscale"
cs.service_offering_id = "71004023-bb72-4a97-b1e9-bc66dfce9470"
cs.zone_id = "1128bd56-b4d9-4ac6-a7b9-c715b187ce11"
override.ssh.username = "root"
override.ssh.private_key_path = "/path/to/private/key/id_rsa_example"
end
# Test bootstrap script
config.vm.provision :shell, :path => "bootstrap.sh"
end
</pre>
<p>The machine is brought up with:</p>
<pre>
vagrant up --provider=cloudstack
</pre>
<p>The following example output will follow:</p>
<pre>
$ vagrant up --provider=cloudstack
Bringing machine 'default' up with 'cloudstack' provider...
[default] Warning! The Cloudstack provider doesn't support any of the Vagrant
high-level network configurations (`config.vm.network`). They
will be silently ignored.
[default] Launching an instance with the following settings...
[default] -- Service offering UUID: 71004023-bb72-4a97-b1e9-bc66dfce9470
[default] -- Template UUID: a17b40d6-83e4-4f2a-9ef0-dce6af575789
[default] -- Zone UUID: 1128bd56-b4d9-4ac6-a7b9-c715b187ce11
[default] -- Keypair: exoscale
[default] Waiting for instance to become "ready"...
[default] Waiting for SSH to become available...
[default] Machine is booted and ready for use!
[default] Rsyncing folder: /Users/sebgoa/Documents/exovagrant/ => /vagrant
[default] Running provisioner: shell...
[default] Running: /var/folders/76/sx82k6cd6cxbp7_djngd17f80000gn/T/vagrant-shell20131203-21441-1ipxq9e
Tue Dec 3 14:25:49 CET 2013
This works
</pre>
<p>Which is a perfect execution of my amazing bootstrap script:</p>
<pre>
#!/usr/bin/env bash
/bin/date
echo "This works"
</pre>
<p>You can now start playing with Chef cookbooks, Puppet recipes or SaltStack formulas and automate the configuration of your cloud instances, thanks to Veewee <a href="http://vagrantup.com">Vagrant</a> and <a href="http://cloudstack.apache.org">CloudStack</a>.</p>Sebastien Goasguenhttp://www.blogger.com/profile/05197845236510805309noreply@blogger.com0tag:blogger.com,1999:blog-19879822.post-48736971626267151492013-11-05T05:25:00.000-08:002013-11-05T05:35:34.480-08:00Fluentd plugin to CloudStack<p> When it rains, it pours...Here is a quick write up to use Fluentd to log CloudStack events and usage. <a href="http://fluentd.org">Fluentd</a> is an open source software to collect events and logs in JSON format. It has hundreds of plugins that allows you to store the logs/events in your favorite data store like AWS S3, MongoDB and even elasticsearch. It is an equivalent to <a href="http://logstash.net">logstash</a>. The source is available on <a href="https://github.com/fluent/fluentd">Github</a> but can also be installed via your favorite package manager (e.g brew, yum, apt, gem). A CloudStack <a href="https://github.com/u-ichi/fluent-plugin-cloudstack">plugin</a> has been written to be able to listen to CloudStack events and store these events in a chosen storage backend. In this blog I will show you how to store CloudStack logs in MongoDB using Fluent. Note that the same thing can be done with logstash, just ask @pyr. The <a href="http://docs.fluentd.org/articles/quickstart">documentation</a> is quite straightforward, but here are the basic steps.</p>
<p>You will need a working `fluentd` installed on your machine. Pick your package manager of choice and install `fluentd`, for instance with `gem` we would do:</p>
<pre>
sudo gem install fluentd
</pre>
<p>`fluentd` will now be in your path, you need to create a configuration file and start `fluentd` using this config. For additional options with `fluentd` just enter `fluentd -h`. The `s` option will create a sample configuration file in the working directory. The `-c` option will start `fluentd` using the specific configuration file. You can then send a test log/event message to the running process with `fluent-cat`.</p>
<pre>
$ fluentd -s conf
$ fluentd -c conf/fluent.conf &
$ echo '{"json":"message"}' | fluent-cat debug.test
</pre>
<p><b>The CloudStack plugin:</b></br>CloudStack has a `listEvents` API which does what is says :) it lists events happening within a CloudStack deployment. Such events as the start and stop of a virtual machine, creation of security groups, life cycles events of storage elements, snapshots etc. The `listEvents` API is well <a href="http://cloudstack.apache.org/docs/api/apidocs-4.2/root_admin/listEvents.html">documented</a>. Based mostly on this API and the <a href="http://fog.io">fog</a> ruby library, a CloudStack plugin for `fluentd` was written by <a href="https://github.com/u-ichi">Yuichi UEMURA</a>. It is slightly different from using `logstash`, as with `logstash` you can format the log4j logs of the CloudStack management server and directly collect those. Here we rely mostly on the `listEvents` API.</p>
<p>You can install it from source:</p>
<pre>
git clone https://github.com/u-ichi/fluent-plugin-cloudstack
</pre>
<p>Then build your own gem and install it with `sudo gem build fluent-plugin-cloudstack.gemspec` and `sudo gem install fluent-plugin-cloudstack-0.0.8.gem `</p>
<p>Or you install the gem directly:</p>
<pre>
sudo gem install fluent-plugin-cloudstack
</pre>
<p>Generate a configuration file with `fluentd -s conf`, you can specify the path to your configuration file. Edit the configuraton to define a `source` as being from your CloudStack host. For instance if you a running a development environment locally:</p>
<pre>
<source>
type cloudstack
host localhost
apikey $cloudstack_apikey
secretkey $cloustack_secretkey
# optional
protocol http # https or http, default https
path /client/api # default /client/api
port 8080 # default 443
#interval 300 # min 300, default 300
ssl false # true or false, default true
domain_id $cloudstack_domain_id
tag cloudstack
</source>
</pre>
<p>There is currently a small bug in the `interval` definition so I commented it out. You also want to define the tag explicitly as being `cloudstack`. You can then create a `match` section in the configuration file. To keep it simple at first, we will simply echo the events to `stdout`, therefore just add:</p>
<pre>
<match cloudstack.**>
type stdout
</match>
</pre>
<p>
Run `fluentd` with `fluentd -c conf/fluent.conf &`, browse the CloudStack UI, create a VM, create a service offering, just do a few things to generate some events that should appear in stdout. Once the interval is passed you will see the events being written to `stdout`:</p>
<pre>
$ 2013-11-05 12:19:26 +0100 [info]: starting fluentd-0.10.39
2013-11-05 12:19:26 +0100 [info]: reading config file path="conf/fluent.conf"
2013-11-05 12:19:26 +0100 [info]: using configuration file: <ROOT>
<source>
type forward
</source>
<source>
type cloudstack
host localhost
apikey 6QN8jOzEfhR7Fua69vk5ocDo_tfg8qqkT7-2w7nnTNsSRyPXyvRRAy23683qcrflgliHed0zA3m0SO4W9kh2LQ
secretkey HZiu9vhPAxA8xi8jpGWMWb9q9f5OL1ojW43Fd7zzQIjrcrMLoYekeP1zT9d-1B3DDMMpScHSR9gAnnG45ewwUQ
protocol http
path /client/api
port 8080
interval 3
ssl false
domain_id a9e4b8f0-3fd5-11e3-9df7-78ca8b5a2197
tag cloudstack
</source>
<match debug.**>
type stdout
</match>
<match cloudstack.**>
type stdout
</match>
</ROOT>
2013-11-05 12:19:26 +0100 [info]: adding source type="forward"
2013-11-05 12:19:26 +0100 [info]: adding source type="cloudstack"
2013-11-05 12:19:27 +0100 [info]: adding match pattern="debug.**" type="stdout"
2013-11-05 12:19:27 +0100 [info]: adding match pattern="cloudstack.**" type="stdout"
2013-11-05 12:19:27 +0100 [info]: listening fluent socket on 0.0.0.0:24224
2013-11-05 12:19:27 +0100 [info]: listening cloudstack api on localhost
2013-11-05 12:19:30 +0100 cloudstack.usages: {"events_flow":0}
2013-11-05 12:19:30 +0100 cloudstack.usages: {"vm_sum":1,"memory_sum":536870912,"cpu_sum":1,"root_volume_sum":1400,"data_volume_sum":0,"Small Instance":1}
2013-11-05 12:19:33 +0100 cloudstack.usages: {"events_flow":0}
2013-11-05 12:19:33 +0100 cloudstack.usages: {"vm_sum":1,"memory_sum":536870912,"cpu_sum":1,"root_volume_sum":1400,"data_volume_sum":0,"Small Instance":1}
2013-11-05 12:19:36 +0100 cloudstack.usages: {"events_flow":0}
2013-11-05 12:19:36 +0100 cloudstack.usages: {"vm_sum":1,"memory_sum":536870912,"cpu_sum":1,"root_volume_sum":1400,"data_volume_sum":0,"Small Instance":1}
2013-11-05 12:19:39 +0100 cloudstack.usages: {"events_flow":0}
...
2013-11-05 12:19:53 +0100 cloudstack.event: {"id":"b5051963-33e5-4f44-83bc-7b78763dcd24","username":"admin","type":"VM.DESTROY","level":"INFO","description":"Successfully completed destroying Vm. Vm Id: 17","account":"admin","domainid":"a9e4b8f0-3fd5-11e3-9df7-78ca8b5a2197","domain":"ROOT","created":"2013-11-05T12:19:53+0100","state":"Completed","parentid":"d0d47009-050e-4d94-97d9-a3ade1c80ee3"}
2013-11-05 12:19:53 +0100 cloudstack.event: {"id":"39f8ff37-515c-49dd-88d3-eeb77d556223","username":"admin","type":"VM.DESTROY","level":"INFO","description":"destroying Vm. Vm Id: 17","account":"admin","domainid":"a9e4b8f0-3fd5-11e3-9df7-78ca8b5a2197","domain":"ROOT","created":"2013-11-05T12:19:53+0100","state":"Started","parentid":"d0d47009-050e-4d94-97d9-a3ade1c80ee3"}
2013-11-05 12:19:53 +0100 cloudstack.event: {"id":"d0d47009-050e-4d94-97d9-a3ade1c80ee3","username":"admin","type":"VM.DESTROY","level":"INFO","description":"destroying vm: 17","account":"admin","domainid":"a9e4b8f0-3fd5-11e3-9df7-78ca8b5a2197","domain":"ROOT","created":"2013-11-05T12:19:53+0100","state":"Scheduled"}
2013-11-05 12:19:55 +0100 cloudstack.usages: {"events_flow":3}
2013-11-05 12:19:55 +0100 cloudstack.usages: {"vm_sum":1,"memory_sum":536870912,"cpu_sum":1,"root_volume_sum":1400,"data_volume_sum":0,"Small Instance":1}
...
2013-11-05 12:20:18 +0100 cloudstack.event: {"id":"11136a76-1de0-4907-b31d-2557bc093802","username":"admin","type":"SERVICE.OFFERING.CREATE","level":"INFO","description":"Successfully completed creating service offering. Service offering id=13","account":"system","domainid":"a9e4b8f0-3fd5-11e3-9df7-78ca8b5a2197","domain":"ROOT","created":"2013-11-05T12:20:18+0100","state":"Completed"}
2013-11-05 12:20:19 +0100 cloudstack.usages: {"events_flow":1}
2013-11-05 12:20:19 +0100 cloudstack.usages: {"vm_sum":1,"memory_sum":536870912,"cpu_sum":1,"root_volume_sum":1400,"data_volume_sum":0,"Small Instance":1}
</pre>
<p>
I cut some of the output for brevity, note that I do have an interval listed as `3` because I did not want to wait 300 minutes. Therefore I installed from source and patched the plugin, it should be fixed in the source soon. You might have a different endpoint and of course different keys, and don't worry about me sharing that `secret_key` I am using a simulator, that key is already gone.</p>
<p>Getting the events and usage information on stdout is interesting, but the kicker comes from storing the data in a database or a search index. In this section we show to get closer to reality and use <a href="http://www.mongodb.org">MongoDB</a> to store the data. MongoDB is an open source document database which is schemaless and stores document in JSON format (BSON actually). Installation and query syntax of MongoDB is beyond the scope of this chapter. MongoDB clusters can be setup with replication and sharding, in this section we use MongoDB on a single host with no sharding or replication. To use MongoDB as a storage backend for the events, we first need to install `mongodb`. On single OSX node this is as simple as `sudo port install mongodb`. For other OS use the appropriate package manager. You can then start mongodb with `sudo mongod --dbpath=/path/to/your/databases`. Create a `fluentd` database and a `fluentd` user with read/write access to it. In the mongo shell do:</p>
<pre>
$sudo mongo
>use fluentd
>db.AddUser({user:"fluentd", pwd: "foobar", roles: ["readWrite", "dbAdmin"]})
</pre>
<p>We then need to install the `fluent-plugin-mongodb`. Still using `gem` this will be done like so:</p>
<pre>
$sudo gem install fluent-plugin-mongo.
</pre>
<p>The complete <a href="http://docs.fluentd.org/articles/out_mongo">documentation</a> also explains how to modify the configuration of `fluentd` to use this backend. Previously we used `stdout` as the output backend, to use `mongodb` we just need to write a different `<match>` section like so:</p>
<pre>
# Single MongoDB
<match cloudstack.**>
type mongo
host fluentd
port 27017
database fluentd
collection test
# for capped collection
capped
capped_size 1024m
# authentication
user fluentd
password foobar
# flush
flush_interval 10s
</match>
</pre>
<p>Note that you cannot have multiple `match` section for the same tag pattern.</p>
<p>To view the events/usages in Mongo, simply start a mongo shell with `mongo -u fluentd -p foobar fluentd` and list the collections. You will see the `test` collection:</p>
<pre>
$ mongo -u fluentd -p foobar fluentd
MongoDB shell version: 2.4.7
connecting to: fluentd
Server has startup warnings:
Fri Nov 1 13:11:44.855 [initandlisten]
Fri Nov 1 13:11:44.855 [initandlisten] ** WARNING: soft rlimits too low. Number of files is 256, should be at least 1000
> show collections
system.indexes
system.users
test
</pre>
<p>Couple MongoDB commands will get your rolling, `db.getCollection`, `count()` and `findOne()`:</p>
<pre>
> coll=db.getCollection('test')
fluentd.test
> coll.count()
181
> coll.findOne()
{
"_id" : ObjectId("5278d9822675c98317000001"),
"events_flow" : 0,
"time" : ISODate("2013-11-05T11:41:47Z")
}
</pre>
<p>The `find()` call returns all entries in the collection. </p>
<pre>
> coll.find()
{ "_id" : ObjectId("5278d9822675c98317000001"), "events_flow" : 0, "time" : ISODate("2013-11-05T11:41:47Z") }
{ "_id" : ObjectId("5278d9822675c98317000002"), "vm_sum" : 0, "memory_sum" : 0, "cpu_sum" : 0, "root_volume_sum" : 1500, "data_volume_sum" : 0, "Small Instance" : 1, "time" : ISODate("2013-11-05T11:41:47Z") }
{ "_id" : ObjectId("5278d98d2675c98317000009"), "events_flow" : 0, "time" : ISODate("2013-11-05T11:41:59Z") }
{ "_id" : ObjectId("5278d98d2675c9831700000a"), "vm_sum" : 0, "memory_sum" : 0, "cpu_sum" : 0, "root_volume_sum" : 1500, "data_volume_sum" : 0, "Small Instance" : 1, "time" : ISODate("2013-11-05T11:41:59Z") }
{ "_id" : ObjectId("5278d98d2675c9831700000b"), "id" : "1452c56a-a1e4-43d2-8916-f83a77155a2f", "username" : "admin", "type" : "VM.CREATE", "level" : "INFO", "description" : "Successfully completed starting Vm. Vm Id: 19", "account" : "admin", "domainid" : "a9e4b8f0-3fd5-11e3-9df7-78ca8b5a2197", "domain" : "ROOT", "created" : "2013-11-05T12:42:01+0100", "state" : "Completed", "parentid" : "df68486e-c6a8-4007-9996-d5c9a4522649", "time" : ISODate("2013-11-05T11:42:01Z") }
{ "_id" : ObjectId("5278d98d2675c9831700000c"), "id" : "901f9408-ae05-424f-92cd-5693733de7d6", "username" : "admin", "type" : "VM.CREATE", "level" : "INFO", "description" : "starting Vm. Vm Id: 19", "account" : "admin", "domainid" : "a9e4b8f0-3fd5-11e3-9df7-78ca8b5a2197", "domain" : "ROOT", "created" : "2013-11-05T12:42:00+0100", "state" : "Scheduled", "parentid" : "df68486e-c6a8-4007-9996-d5c9a4522649", "time" : ISODate("2013-11-05T11:42:00Z") }
{ "_id" : ObjectId("5278d98d2675c9831700000d"), "id" : "df68486e-c6a8-4007-9996-d5c9a4522649", "username" : "admin", "type" : "VM.CREATE", "level" : "INFO", "description" : "Successfully created entity for deploying Vm. Vm Id: 19", "account" : "admin", "domainid" : "a9e4b8f0-3fd5-11e3-9df7-78ca8b5a2197", "domain" : "ROOT", "created" : "2013-11-05T12:42:00+0100", "state" : "Created", "time" : ISODate("2013-11-05T11:42:00Z") }
{ "_id" : ObjectId("5278d98d2675c9831700000e"), "id" : "924ba8b9-a9f2-4274-8bbd-c27947d2c246", "username" : "admin", "type" : "VM.CREATE", "level" : "INFO", "description" : "starting Vm. Vm Id: 19", "account" : "admin", "domainid" : "a9e4b8f0-3fd5-11e3-9df7-78ca8b5a2197", "domain" : "ROOT", "created" : "2013-11-05T12:42:00+0100", "state" : "Started", "parentid" : "df68486e-c6a8-4007-9996-d5c9a4522649", "time" : ISODate("2013-11-05T11:42:00Z") }
{ "_id" : ObjectId("5278d98d2675c9831700000f"), "events_flow" : 4, "time" : ISODate("2013-11-05T11:42:02Z") }
{ "_id" : ObjectId("5278d98d2675c98317000010"), "vm_sum" : 1, "memory_sum" : 536870912, "cpu_sum" : 1, "root_volume_sum" : 1600, "data_volume_sum" : 0, "Small Instance" : 1, "time" : ISODate("2013-11-05T11:42:02Z") }
Type "it" for more
</pre>
<p>We leave it to you to learn the MongoDB query syntax and the great aggregation framework, have fun. Of course you can get the data into elasticsearch as well :) </p>Sebastien Goasguenhttp://www.blogger.com/profile/05197845236510805309noreply@blogger.com0tag:blogger.com,1999:blog-19879822.post-38897188215850331822013-11-05T01:46:00.000-08:002013-11-05T01:46:19.566-08:00OCCI interface to CloudStack<p>CloudStack has its own API. Cloud wrappers like libcloud and jclouds work well with this native API, but CloudStack does not expose any standard API like <a href="http://occi-wg.org">OCCI</a> and <a href="http://dmtf.org/standards/cloud">CIMI</a>. We (Isaac Chiang really, I just tested and pointed him in the right direction) started working on a CloudStack backend for <a href="https://github.com/gwdg/rOCCI">rOCCI</a> using our CloudStack <a href="https://github.com/chipchilders/cloudstack_ruby_client">ruby gem</a>. The choice of rOCCI was made due to the existence of an existing Opennebula backend and the adoption of OCCI in the European Grid Initiative Federated cloud <a href="https://wiki.egi.eu/wiki/Fedcloud-tf:Testbed">testbed</a>.</p>
<p>Let's get started with installing the <a href="https://github.com/gwdg/rOCCI-server">rOCCI server</a>, this work has not yet been merged upstream so you will need to work from Isaac Chiang's fork.</p>
<pre>
git clone https://github.com/isaacchiang/rOCCI-server.git
bundle install
cd etc/backend
cp cloudstack/cloudstack.json default.json
</pre>
<p>Edit the defautl.json file to contain the information about your CloudStack cloud (e.g apikey, secretkey, endpoint).
Start the rOCCI server:</p>
<pre>
bundle exec passenger start
</pre>
<p>The server should be running on http://0.0.0.0:3000 and run the tests:</p>
<pre>
bundle exec rspec
</pre>
<p>This was tested with the CloudStack simulator and a basic zone configuration, help us test it in production clouds.</p>
<p>You can also try an OCCI client. Install the <a href="https://github.com/gwdg/rOCCI-cli">rOCCI client</a> from Github:</p>
<pre>
git clone https://github.com/gwdg/rOCCI-cli.git
cd rOCCI-cli
gem install bundler
bundle install
bundle exec rake test
rake install
</pre>
<p>You will then be able to use the OCCI client:</p>
<pre>
occi --help
</pre>
<p>Test it against the server that you are started previously. You will need a running CloudStack cloud. Either a production one or a dev instance using DevCloud. The credentials and the endpoint to this cloud will have been entered in `default.json` file that you created in the previous section. Try a couple OCCI client command:</p>
<pre>
$ occi --endpoint http://0.0.0.0:3000/ --action list --resource os_tpl
Os_tpl locations:
os_tpl#6673855d-ce9b-4997-8613-6830de037a8f
$ occi --endpoint http://0.0.0.0:3000/ --action list --resource resource_tpl
Resource_tpl locations:
resource_tpl##08ba0343-bd39-4bf0-9aab-4953694ae2b4
resource_tpl##f78769bd-95ea-4139-ad9b-9dfc1c5cb673
resource_tpl##0fd364a9-7e33-4375-9e10-bb861f7c6ee7
</pre>
<p>You will recognize the `uuid` from the templates and service offerings that you have created in CloudStack. To start an instance:</p>
<pre>
$ occi --endpoint http://0.0.0.0:3000/ --action create --resource compute
--mixin os_tpl#6673855d-ce9b-4997-8613-6830de037a8f
--mixin resource_tpl#08ba0343-bd39-4bf0-9aab-4953694ae2b4
--resource-title foobar
</pre>
<p>A handle on the resource created will be returned. That's it !</p>
<p>We will keep on improving this driver to provide a production quality OCCI interface to users who want to use a standard. In all fairness we will also work on a CIMI implementation. Hopefully some of the clouds in the EGI federated cloud will pick CloudStack and help us improve this OCCI interface. In CloudStack we aim to provide the interfaces that the users want and keep them up to date and of production quality so that users can depend on it.</p>
Sebastien Goasguenhttp://www.blogger.com/profile/05197845236510805309noreply@blogger.com0tag:blogger.com,1999:blog-19879822.post-37491905954096821422013-10-17T03:09:00.001-07:002013-10-17T03:18:25.355-07:00Why I will go to CCC13 in Amsterdam ?<p>Aside from the fact that I work full-time on Apache CloudStack, that I am on the organizing committee and that my boss would kill me if I did not go to the <a href="http://cloudstackcollab.org">CloudStack Collaboration</a> conference, there are many great reasons why I want to go as an open source enthusiast, here is why:</p>
<p>It's <a href="http://www.iamsterdam.com/">Amsterdam</a> and we are going to have a blast (the city of Amsterdam is even sponsoring the event). The venue -<a href="http://www.beursvanberlage.nl/">Beurs Van Berlage</a>- is terrific, this is the same venue where the <a href="http://hadoopsummit.org/">Hadoop summit</a> is held and where the <a href="http://aws.amazon.com/aws-summit-benelux-2013/amsterdam/">AWS Benelux Summit</a> was couple weeks ago. We are going to have a 24/7 Developer room (thanks to <a href="http://www.cloudsoftcorp.com/">CloudSoft</a>) where we can meet to hack on CloudStack and its ecosystem, three parallel tracks in other rooms and great evening events. The event is made possible by the amazing local support from the team at <a href="http://www.schubergphilis.com/">Schuberg Philis</a>, a company that has devops in its vein and organized <a href="http://www.devopsdays.org/events/2013-amsterdam/">DevOps days Amsterdam</a>. I am not being very subtle in acknowledging our sponsors here, but hey, without them this would not be possible.</p>
<p>On the first day (November 20th) is the <a href="http://cloudstackcollab.org/schedule/wednesday">Hackathon</a> sponsored by <a href="http://exoscale.ch">exoscale</a>. In parallel to the hackathon, new users of CloudStack will be able to attend a full day bootcamp run by the super competent guys from <a href="http://www.shapeblue.com/">Shapeblue</a>, they also play guitar and drink beers so make sure to hang out with them :). Even as cool is that the CloudStack community recognizes that building a Cloud takes many components, so we will have a <a href="http://jenkins-ci.org/">jenkins</a> workshop and an <a href="http://www.elasticsearch.org/">elasticsearch</a> workshop. I am big fan of elasticsearch, not only for keeping your infrastructure logs but also for other types of data. I actually store all CloudStack emails in an elasticsearch cluster. Jenkins of course is at the heart of everyone's continuous integration systems these days. Seeing those two workshops, it will be no surprise to see a DevOps track the next two days.</p>
<p>Kicking off the second day -<a href="http://cloudstackcollab.org/schedule/thursday">first day of talks</a>- we will have a keynote by <a href="http://www.jedi.be/blog/">Patrick Debois</a> the jedi master of DevOps. We will then break up into a user track, a developer track, a commercial track and for this day only a devops track with a 'culture' flavor. The hard work will begin: choosing which talk to attend. I am not going to go through every talk, we received a lot of great submissions and choosing was hard. New CloudStack users or people looking into using CloudStack will gain a lot from the case studies being presented in the user track while the developers will get a deep dive into the advanced networking features of CloudStack including SDN support -right off the bat-. In the afternoon, the case studies will continue in the user track including a talk from NTT about how they built an AWS compatible cloud. I will have to head to the developer track for a session on 'interfaces' with a talk on jclouds, a new GCE interface that I worked on and my own talk on Apache libcloud for which I worked a lot on the CloudStack driver. The DevOps track will have an entertaining talk by Michael Ducy from <a href="http://www.opscode.com/">Opscode</a>, some real world experiences by John Turner and Noel King from Paddy Power and the VP of engineering for Citrix CloudPlatform will lead an interactive session on how to best work with the open source community of Apache CloudStack.</p>
<p>After recovering from the nights events, we will head into the <a href="http://cloudstackcollab.org/schedule/friday">second day</a> with another entertaining keynote by <a href="https://twitter.com/botchagalupe">John Willis</a>. Here the choice will be hard between the storage session in the commercial track and the 'Future of CloudStack' session in the developer track. With talks from NetApp and SolidFire who have each developed a plugin in CloudStack plus our own Wido Den Hollander (PMC member) who wrote the Ceph integration the storage session will rock, but the 'Future of CloudStack' session will be key for developers, talking about frameworks, integration testing, system VMs...After lunch the user track will feature several intro to networking talks. Networking is the most difficult concept to grasp in clouds (IMHO). The storage session will continue with a talk by <a href="http://basho.com/">Basho</a> on RiakCS (also integrated in CloudStack) and a panel. The dev track will be dedicated to discussions on PaaS, not to be missed if you ask me, as PaaS is the next step in Clouds. To wrap things up, I will have to decide between a session on metering/billing, a discussion on hypervisor choice and support, and a presentation on the CloudStack community in Japan after <a href="https://twitter.com/rUv">Ruv Cohen</a> talking about trading cloud commodities. </p>
<p>The agenda is loaded and ready to fire, it will be tough to decide which sessions to attend but you will come out refreshed, energized with lots of new ideas to evolve your IT infrastructure, so one word: <a href="http://cloudstackcollab.org/event/registration">Register</a> </p>
<p><p>And of course many thanks to our <a href="http://www.cloudstackcollab.org/sponsors">sponsors</a>: Citrix, Schuberg Philis, Juniper, Sungard, Shapeblue, NetApp, cloudSoft, Nexenta, iKoula, leaseweb, solidfire, greenqloud, atom86, apalia, elasticsearch, 2source4, iamsterdam, cloudbees and 42on</p></p>Sebastien Goasguenhttp://www.blogger.com/profile/05197845236510805309noreply@blogger.com0tag:blogger.com,1999:blog-19879822.post-86663161798485455442013-10-01T05:48:00.000-07:002013-10-01T05:48:30.166-07:00A look at RIAK-CS from BASHO<p><b>Playing with Basho Riak CS Object Store</b></p>
<p>CloudStack deals with the compute side of a IaaS, the storage side which for most of us these days consists of a scalable, fault tolerant object store is left to other software. <a href="http://ceph.com/ceph-storage/">Ceph</a> led by <a href="http://www.inktank.com/">inktank</a> and <a href="http://basho.com/riak-cloud-storage/">RiakCS</a> from <a href="http://basho.com">Basho</a> are the two most talked about object store these days. In this post we look at RiakCS and take it for a quick whirl. CloudStack integrates with RiakCS for secondary storage and together they can offer an EC2 and a true S3 interface, backed by a scalable object store. So here it is.</p>
<p>While <a href="http://basho.com/riak-cloud-storage/">RiakCS</a> (Cloud Storage) can be seen as an S3 backend implementation, it is based on Riak. Riak is a highly available distributed nosql <a href="http://docs.basho.com/riak/latest/theory/why-riak/">database</a>.
The use of a consistent hashing algorithm allows riak to re-balance the data when node disappear (e.g fail) and when node appear (e.g increased capacity), it also allows to manage replication of data with an eventual consistency principle typical of large scale distributed storage system which favor availability over consistency.</p>
<p>To get a functioning RiakCS storage we need Riak, RiakCS and Stanchion. Stanchion is an interface that serializes http requests made to RiakCS.</p>
<p><b>A taste of Riak</b></p>
<p>To get started, let's play with Riak and build a cluster on our local machine. Basho has some great <a href="http://docs.basho.com/riak/latest/quickstart/">documentation</a>, the toughest thing will be to install Erlang (and by tough I mean a 2 minutes deal), but again the <a href="http://docs.basho.com/riak/latest/ops/building/installing/erlang/">docs</a> are very helpful and give step by step instructions for almost all OS.</p>
<p>There is no need for me to re-create step by step instructions since the docs are so great, but the gist is that with the quickstart guide we can create a Riak cluster on `localhost`. We are going to start five Riak node (e.g we could start more) and join them into a cluster. This is as simple as:</p>
<pre>
bin/riak start
bin/riak-admin cluster join dev1@127.0.0.1
</pre>
<p>Where `dev1` was the first riak node started. Creating this cluster will re-balance the ring:</p>
<pre>
================================= Membership ==================================
Status Ring Pending Node
-------------------------------------------------------------------------------
valid 100.0% 20.3% 'dev1@127.0.0.1'
valid 0.0% 20.3% 'dev2@127.0.0.1'
valid 0.0% 20.3% 'dev3@127.0.0.1'
valid 0.0% 20.3% 'dev4@127.0.0.1'
valid 0.0% 18.8% 'dev5@127.0.0.1'
</pre>
<p>The `riak-admin` command is a nice cli to <a href="http://docs.basho.com/riak/latest/ops/running/tools/riak-admin/">manage</a> the cluster. We can check the membership of the cluster we just created, after some time the ring will have re-balanced to the expected state.</p>
<pre>
dev1/bin/riak-admin member-status
================================= Membership ==================================
Status Ring Pending Node
-------------------------------------------------------------------------------
valid 62.5% 20.3% 'dev1@127.0.0.1'
valid 9.4% 20.3% 'dev2@127.0.0.1'
valid 9.4% 20.3% 'dev3@127.0.0.1'
valid 9.4% 20.3% 'dev4@127.0.0.1'
valid 9.4% 18.8% 'dev5@127.0.0.1'
-------------------------------------------------------------------------------
Valid:5 / Leaving:0 / Exiting:0 / Joining:0 / Down:0
dev1/bin/riak-admin member-status
================================= Membership ==================================
Status Ring Pending Node
-------------------------------------------------------------------------------
valid 20.3% -- 'dev1@127.0.0.1'
valid 20.3% -- 'dev2@127.0.0.1'
valid 20.3% -- 'dev3@127.0.0.1'
valid 20.3% -- 'dev4@127.0.0.1'
valid 18.8% -- 'dev5@127.0.0.1'
-------------------------------------------------------------------------------
</pre>
<p>You can then test your cluster by putting an image as explained in the docs and retrieving it in a browser (e.g an HTTP GET)</p>
<pre>
curl -XPUT http://127.0.0.1:10018/riak/images/1.jpg
-H "Content-type: image/jpeg"
--data-binary @image_name_.jpg
</pre>
<p>Open the browser to `http://127.0.0.1:10018/riak/images/1.jpg`
As easy as 1..2..3
</p>
<p><b>Installing everything on Ubuntu 12.04</b></p>
<p>To move forward and build a complete S3 compatible object store, let's setup everything on a Ubuntu 12.04 machine. Back to installing `riak`, get the repo keys and setup a `basho.list` repository:</p>
<pre>
curl http://apt.basho.com/gpg/basho.apt.key | sudo apt-key add -
bash -c "echo deb http://apt.basho.com $(lsb_release -sc) main > /etc/apt/sources.list.d/basho.list"
apt-get update
</pre>
<p>And grab `riak`, `riak-cs` and `stanchion`. I am not sure why but their great docs make you download the .debs separately and use `dpkg`.</p>
<pre>
apt-get install riak riak-cs stanchion
</pre>
Check that the binaries are in your path with `which riak`, `which riak-cs` and `which stanchion` , you should find everything in `/usr/sbin`. All configuration will be in `/etc/riak`, `/etc/riak-cs` and `/etc/stanchion` inspect especially the `app.config` which we are going to modify before starting everything.
Note that all binaries have a nice usage description, it includes a console, a ping method and a restart among others:
<pre>
Usage: riak {start | stop| restart | reboot | ping | console | attach |
attach-direct | ertspath | chkconfig | escript | version |
getpid | top [-interval N] [-sort reductions|memory|msg_q] [-lines N] }
</pre>
<p><b>Configuration</b></p>
Before starting anything we are going to configure every component, which means editing the `app.config` files in each respective directory. For `riak-cs` I only made sure to set `{anonymous_user_creation, true}`, I did nothing for configuring `stanchion` as I used the default ports and ran everything on `localhost` without `ssl`. Just make sure that you are not running any other application on port `8080` as `riak-cs` will use this port by default. For configuring `riak` see the <a href="http://docs.basho.com/riakcs/latest/cookbooks/configuration/Configuring-Riak/">documentation</a>, it sets a
different backend that what we used in the `tasting` phase :) With all these configuration done you should be able to start all three components:
<pre>
riak start
riak-cs start
stanchion start
</pre>
You can `ping` every component and check the console with `riak ping`, `riak-cs ping` and `stanchion ping`, I let you figure out the console access.
Create an admin user for `riak-cs`
<pre>
curl -H 'Content-Type: application/json' -X POST http://localhost:8080/riak-cs/user \
--data '{"email":"foobar@example.com", "name":"admin user"}'
</pre>
If this returns successfully this should be a good indication that your setup is working properly. In the response we recognized API and secret keys
<pre>
{"email":"foobar@example.com",
"display_name":"foobar",
"name":"admin user",
"key_id":"KVTTBDQSQ1-DY83YQYID",
"key_secret":"2mNGCBRoqjab1guiI3rtQmV3j2NNVFyXdUAR3A==",
"id":"1f8c3a88c1b58d4b4369c1bd155c9cb895589d24a5674be789f02d3b94b22e7c",
"status":"enabled"}
</pre>
Let's take those and put them in our `riak-cs` configuration file, there are `admin_key` and `admin_secret` variables to set. Then restart with `riak-cs restart`. Don't forget to also add those in the `stanchion` configuration file `/etc/stanchion/app.config` and restart it `stanchion restart`.
<p><b>Using our new Cloud Storage with Boto</b></p>
Since Riak-CS is S3 Compatible clouds storage solution, we should be able to use an S3 client like Python <a href="http://boto.s3.amazonaws.com/s3_tut.html">boto</a> to create buckets and store data. Let's try. You will need boto of course, `apt-get install python-boto` and then open an interactive shell `python`.
Import the modules and create a connection to `riak-cs`
<pre>
>>> from boto.s3.key import Key
>>> from boto.s3.connection import S3Connection
>>> from boto.s3.connection import OrdinaryCallingFormat
>>> apikey='KVTTBDQSQ1-DY83YQYID'
>>> secretkey='2mNGCBRoqjab1guiI3rtQmV3j2NNVFyXdUAR3A=='
>>> cf=OrdinaryCallingFormat()
>>> conn=S3Connection(aws_access_key_id=apikey,aws_secret_access_key=secretkey,
is_secure=False,host='localhost',port=8080,calling_format=cf)
</pre>
Now you can list the bucket, which will be empty at first. Then create a bucket and store content in it with various keys
<pre>
>>> conn.get_all_buckets()
[]
>>> bucket=conn.create_bucket('riakbucket')
>>> k=Key(bucket)
>>> k.key='firstkey'
>>> k.set_contents_from_string('Object from first key')
>>> k.key='secondkey'
>>> k.set_contents_from_string('Object from second key')
>>> b=conn.get_all_buckets()[0]
>>> k=Key(b)
>>> k.key='secondkey'
>>> k.get_contents_as_string()
'Object from second key'
>>> k.key='firstkey'
>>> k.get_contents_as_string()
'Object from first key'
</pre>
<p>And that's it, an S3 compatible object store backed by a NOSQL distributed database that uses consistent hashing, all of it in erlang. Automate all of it with Chef <a href="http://docs.basho.com/riakcs/latest/cookbooks/installing/Riak-CS-Using-Chef/">recipe</a>. Hook that up to your CloudStack EC2 compatible cloud, use it as secondary storage to hold templates or make it a public facing offering and you have the second leg of the Cloud: storage. Sweet...Next post I will show you how to use it with CloudStack.</p>Sebastien Goasguenhttp://www.blogger.com/profile/05197845236510805309noreply@blogger.com0tag:blogger.com,1999:blog-19879822.post-48827843800946995612013-09-03T02:21:00.001-07:002013-09-03T02:21:03.720-07:00CloudStack Google Summer of Code projects<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh04oFr2I7o0a8nHr4taH4H2X0IZr3zKo51bdTlgC7GOaENmVAPqjpiKvTCOL4WjIItJzY1zfkgzz3wgdSfI6SPzfy1xwfKr4VyrPd-q7o-L-GmAOd2-aOuZUT-QR6X1X4lYzmhrg/s1600/924x156xbanner-gsoc2013.png.pagespeed.ic.-hgGiilbTK.webp" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh04oFr2I7o0a8nHr4taH4H2X0IZr3zKo51bdTlgC7GOaENmVAPqjpiKvTCOL4WjIItJzY1zfkgzz3wgdSfI6SPzfy1xwfKr4VyrPd-q7o-L-GmAOd2-aOuZUT-QR6X1X4lYzmhrg/s320/924x156xbanner-gsoc2013.png.pagespeed.ic.-hgGiilbTK.webp" /></a></div>
<p><a href="http://www.google-melange.com/gsoc/homepage/google/gsoc2013">Google Summer of Code</a> is entering the final stretch with pencil down on Sept 16th and final evaluation on Sept 27th. Of the five projects CloudStack had this summer, one failed at mid-term and one led to committer status couple weeks ago. That's 20% failure and 20% outstanding results, on par with GSoC wide statistics I believe. </p>
<p>The LDAP integration has been the most productive project. Ian Duffy a 20 year old from Dublin did an outstanding job, developing his new feature in a feature branch, building a <a href="http://jenkins-ci.org/">jenkins</a> pipeline to test everything and submitting a merge request to master couple weeks ago. With 90% unittest coverage, static code analysis with <a href="http://www.sonarqube.org/">Sonar</a> in his jenkins pipeline and automatic publishing of rpms in a local yum repo, Ian exceed expectation. His code has even been already backported to the 4.1.1 release with the <a href="http://www.cloudsand.com/content/">CloudSand</a> distro of CloudStack. </p>
<p>The SDN extension project was about taking the native GRE controller in CloudStack and extend it to support XCP and KVM. Nguyen from Vietnam has done an excellent job quickly adding support for <a href="http://www.xenproject.org/developers/teams/xapi.html">XCP</a> thanks to his expertise with Xen. He is now putting the final touches on KVM support and building L3 services with <a href="http://www.opendaylight.org/">OpenDaylight</a>. The entire GRE controller was re-factored to be a plugin similar to the Nicira NVP, Midonet and BigSwitch BVS plugin. While native to CloudStack this controller brings another SDN solution to CloudStack. I expect to see his merge request before pencil down for what will be an extremely valuable project.</p>
<p>While the CloudStack UI is great, it was actually written has a demonstration of how the CloudStack API could be used to build a user facing portal. With the "new UI" project, Shiva Teja from India used <a href="http://getbootstrap.com/">boostrap</a> and <a href="http://angularjs.org/">Angular</a> to create a new UI. Originally the project suggested to use <a href="http://backbonejs.org/">backbone</a> but after feedback from the community Shiva switch to using Angular. Shiva's effort are to be commended as he truly worked on his own with in-consistent network connectivity and no local mentoring. Shiva is a bachelor student and had to learn bootstrap, angular and also Flask on his own. It must have been paying off since he is interviewing with Amazon and Goole for internships next summer. His code being independent of the CloudStack code has been committed to master in our tools directory. This creates a solid framework for other to build on and create their own CloudStack UI.</p>
<p>Perhaps the most research oriented project has been the one from Meng Han from Florida. This was no standard coding projects as it required not only to learn new technologies (aside from CloudStack) but also required investigation of the <a href="http://aws.amazon.com/elasticmapreduce/">Amazon EMR API</a>. Meng had to implement EMR in CloudStack using Apache Whirr. Whirr is a java library for provisioning of virtual machines on cloud providers. Whirr uses Apache jclouds and can interact with most cloud providers out there. Meng developed a new set of CloudStack APIs to launch hadoop clusters on-demand. At the start she had to learn CloudStack and install it, then learn the Whirr library and subsequently create a new API in CloudStack which would use Whirr to coordinate multiple node deployments. Meng's code is working but still a bit short from our goal of having a AWS EMR interface. This is partly my fault has this project could have required more mentoring. In any case, the work will go on and I expect to see an EMR implementation in CloudStack in the coming months.</p>
<p>All students faced the same challenge, not a code writing challenge but the OSS challenge and specifically learning the Apache Way. Apache is about consensus and public discussions on the mailing list. With several hundreds participants every month and very active discussion, the shear amount of email traffic can be intimidating. Sharing issues and asking for help on public mailing list is still a bit frightening. IRC, intense emailing, JIRA and git are basic tools used in all Apache project, but seldom used in academic settings. Learning these development tools and participating in a project with over a million line of code was the toughest challenge for students and the goal of GSoC. I am glad we got five students to join CloudStack this summer and tackle these challenges, if anything it is a terrific experience that will benefit their own academic endeavor and later their entire career. Great job Ian, Meng, Nguyen, Shiva and Dharmesh, we are not done yet but I wish you all the best.</p>Sebastien Goasguenhttp://www.blogger.com/profile/05197845236510805309noreply@blogger.com0tag:blogger.com,1999:blog-19879822.post-44444957888164507092013-08-27T01:27:00.001-07:002013-09-03T01:33:52.127-07:00About those Cloud APIs....<p>There has been a lot of discussions lately within the OpenStack community on the need for an AWS API interface to OpenStack nova. I followed the discussion from far via a few tweets, but I am of the opinion that any IaaS solution does need to expose an AWS interface. AWS is the leader in Cloud and has been since 2006 -yes that's seven years- Users are accustomed to it and the AWS API is the de-factor standard.</p>
<p>When Eucalyptus started, it's main goal was to become an AWS clone and in 2012 signed an <a href="http://www.eucalyptus.com/aws-compatibility/aws-agreement">agreement</a> with Amazon to offer seamless AWS support in Eucalyptus. Opennebula has almost always offered an AWS bridge and CloudStack has too, even though in total disclosure the interface was broken in the Apache CloudStack 4.1 release. Thankfully the AWS interface is now fixed in 4.1.2 release and will also be in the upcoming 4.2 release. To avoid breaking this interface we are developing a jenkins pipeline which will test it using the Eucalyptus testing <a href="https://github.com/eucalyptus/eutester/">suite</a>.</p>
<p>Opennebula recently ran a <a href="http://blog.opennebula.org/?p=4716">survey</a> to determine where to best put its efforts in API development. The results where clear with 47% of respondents asking for better AWS compatibility. There are of course developing official standards from standard organizations, most notably <a href="http://occi-wg.org">OCCI</a> from OGF and <a href="http://dmtf.org/standards/cloud">CIMI</a> from DMTF. The opennebula survey seems to indicate a stronger demand for OCCI than CIMI, but IMHO this is due to historical reasons: Opennebula early efforts in being the first OCCI implementation and Opennebula user base especially within projects like <a href="http://helix-nebula.eu">HelixNebula</a>.</p>
<p>CIMI was promising and probably still is but it will most likely face an up-hill battle since RedHat announced it's scaling back on supporting <a href="http://mail-archives.apache.org/mod_mbox/deltacloud-dev/201305.mbox/%3C518D0F79.4000901@redhat.com%3E">Apache DeltaCloud</a>. I recently heard about a new CIMI implementation project for <a href="https://github.com/StratusLab/cimi">Stratuslab</a> from some of my friends at <a href="http://sixsq.com">Sixsq</a>, it is interesting and fun because written in Clojure and I hope to see it used with <a href="https://github.com/pyr/clostack">Clostack</a> to provide a CIMI interface to CloudStack. We may be couple weeks out :)</p>
<p>While AWS is the de-facto standard, I want to make sure that CloudStack offers choices for its users. If someone wants to use OCCI and CIMI or AWS or the native CloudStack API they should be able to. I will be at the <a href="http://www.cloudplugfest.org">CloudPlugfest Interoperability</a> week in Madrid Sept 18-20 and I hope to demonstrate a brand new OCCI interface to CloudStack using <a href="https://github.com/gwdg/rOCCI-server">rOCCI</a> and CloudStack <a href="https://github.com/chipchilders/cloudstack_ruby_client">ruby gem</a>. A CloudStack contributor from Taiwan has been working on it.<p>
<p>The main issue with all these "standard" interfaces is that they will never give you the complete API of a given IaaS implementation. They by nature provide the lowest common denominator. That roughly means that the user facing APIs could be standardized but the administrator API will always remain hidden and non-standard. In CloudStack for instance, there are over 300 API calls. While we can expose a compatible interface, this will always only cover a subset of the overall API. It also brings the question of all the other AWS services: EMR, Beanstalk, CloudFormation... Standardizing on those will be extremely difficult if not impossible.</p>
<p>So yes, we should expose an AWS compatible interface, but we should also have OCCI, CIMI and of course our native API. Making those bridges is not hard, what's hard is the implementation behind it. </p>
<p>All of this would leave us with Google Compute Engine (GCE), and I should be able to bring back some good news by the end of september, stay tuned !!!</p>Sebastien Goasguenhttp://www.blogger.com/profile/05197845236510805309noreply@blogger.com0