One Command to Kubernetes with Docker Compose

Written by: Sebastien Goasguen
4 min read

This article was originally published on Sebastien Goasguen’s blog and we are sharing it here for Codeship readers. Sebastien is an EMEA Open Source Cloud Computing Evangelist for Citrix. You can find out more about him on his blog.

I hadn't looked at Kubernetes in over a month. It's a fast paced project, so it's hard to keep up. If you haven't looked at Kubernetes, it's roughly 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.

What I find very interesting with Kubernetes is the concept of replication controllers. 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's great for scaling when the load dictates it, but it's also great when you want to replace a container with a new image. Kubernetes also exposes a concept of services -- basically a way to expose a container application to all the hosts in your cluster as if it were running locally. Think of the ambassador pattern of the early Docker days but on steroids.

All that said, you want to try Kubernetes. I know you do. So here's one command to try it out.

Use Docker Compose to run Kubernetes with Docker

We're going to use docker-compose like we did with Mesos in this article. And thanks to this How To, we're going to run Kubernetes on a single host with containers. That means that all the Kubernetes components (the "agent", the "controller," and various controllers) will run in containers.

Install compose on your Docker host, if you do not have it yet:

curl -L https://github.com/docker/compose/releases/download/1.1.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose

Then create this YAML file. Call it, say, k8s.yml:

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.14.1
  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.14.1
  net: "host"
  privileged: true
  command: /hyperkube proxy --master=http://127.0.0.1:8080 --v=2

And now, one command:

$ docker-compose -f k8s.yml up -d

Quickly thereafter, you'll see a bunch of containers pop up:

$ docker ps
CONTAINER ID        IMAGE
56c36dc7bf7e        nginx:latest
a17cac87965b        kubernetes/pause:go
659917e61d3e        gcr.io/google_containers/hyperkube:v0.14.1
caf22057dbad        gcr.io/google_containers/hyperkube:v0.14.1
288fcb4408c7        gcr.io/google_containers/hyperkube:v0.14.1
820cc546b352        kubernetes/pause:go
0bfac38bdd10        kubernetes/etcd:2.0.5.1
81f58059ca8d        gcr.io/google_containers/hyperkube:v0.14.1
ca1590c1d5c4        gcr.io/google_containers/hyperkube:v0.14.1

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 hosts 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 were 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.

With all of those up, grab the kubectl binary. That's your Kubernetes client that you will use to interact with the system. The first thing you can do is list the nodes:

$ ./kubectl get nodes
NAME        LABELS    STATUS
127.0.0.1   <none>    Ready

Now start your first container:

./kubectl run-container nginx --image=nginx --port=80

That's a simple example where you can actually start a single container. You'll want to group your containers that need to be colocated and write a POD description in YAML or JSON, then pass that to kubectl. But it looks like they extended kubectl to take single container start up. That's handy for testing.

Now list your pods:

$ ./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
nginx-p2sq7   172.17.0.4   nginx                nginx

You see that there are 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...

It automatically created a replication controller (rc):

$ ./kubectl get rc
CONTROLLER   CONTAINER(S)   IMAGE(S)   SELECTOR              REPLICAS
nginx        nginx          nginx      run-container=nginx   1

You can have some fun with the resize capability right away and see a new container pop up:

$ ./kubectl resize --replicas=2 rc nginx
resized

Now that's fine and dandy, but there's no port exposed on the host. You can't access your application on the outside. That's where you want to define a service. Technically, it's 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:

$ ./kubectl expose rc nginx --port=80 --public-ip=192.168.33.10

Now open your browser 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 one command. You'll get more of that good stuff in my book, if I manage to finish it. Wish me luck.

This article shows how to use one command to run Kubernetes with Docker. Make sure to read the companion piece to this post: "One Command to Mesos with Docker Compose", also by Sebastien Goasguen.

Stay up to date

We'll never share your email address and you can opt out at any time, we promise.