Draft for Kubernetes - A Prototyping Tool

Navigate to:

OverviewDraft for Kubernetes

Draft for Kubernetes is a tool to help prototype microservices and expose them on a publicly available domain. This makes quickly iterating on things like webhooks or APIs quick and painless. Draft utilizes docker, Helm, and Kubernetes Ingress Controllers to make your ‘drafts’ publicly available in a hurry. Under the hood, it generates a generic Dockerfile and helm chart for your application to get you up and running quickly. The helm chart creates an ingress resource to expose your chart at a url. You will need the following running for this walkthrough:

  1. A Kubernetes Cluster
  2. A domain name you can add A or CNAME records to
  3. An account at quay.io or hub.docker
  4. A working Helm installation
    • Install instructions can be found here.
  5. A golang development environment
    • Draft also supports basic python, ruby, php, node, and java applications.

In this walkthrough, we are going to first install the dependencies for Draft, then create our sample application, install Draft and deploy our app.

Installing Draft Dependencies

An Ingress Controller creates a loadBalancer with a Public IP (or a CNAME record on AWS) to expose your applications to the internet. It is a quick and secure abstraction for routing traffic into the applications running on your cluster. To install an Ingress Controller, use the Nginx Ingress provided by helm:

# Install Ingress Controller
$ helm install stable/nginx-ingress --namespace=kube-system --name=nginx-ingress
# Wait for load balancer to have IP
$ kubectl --namespace kube-system get services -w nginx-ingress-nginx-ingress-controller

# If you have an existing ingress controller find its IP 
echo $(kubectl get svc --namespace kube-system nginx-ingress-nginx-ingress-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}')

Once you get the IP or CNAME you can create the appropriate DNS record. Make it something like *.draft.mydomain.mytld. The steps to do this will vary depending on where your domain is registered. I use What’s My DNS to check propagation. Once you see that the change has propagated, you should get the following response from curl:

$ curl foo.draft.mydomain.mytld
default backend - 404
Note: If you want to know more about default backends, I've found this article scintillating reading.

Prepare Golang App

Make a new project directory and create a golang application. I’ve used a simple server:

// main.go
 package main

import (
  "log"
  "net/http"
)

func sayHello(w http.ResponseWriter, r *http.Request) {
  message := "hello world\n"
  w.Write([]byte(message))
}

func main() {
  http.HandleFunc("/", sayHello)
  err := http.ListenAndServe(":8080", nil)
  if err != nil {
    log.Fatal("ListenAndServe: ", err)
  }
}

You will also want to add some type of dependency management to your application. This is because of the script Draft uses to detect different application types. The golang pack looks to see if there is a glide.yaml, Godeps/Godeps.json, or vendor/vendor.json file in your project. If you are using glide, a simple glide create will satisfy this requirement.

Install Draft

Download the draft binary for your OS and move it into your path. After that you will need to run draft init with some arguments:

draft init --set
 registry.url=docker.io,
 registry.org=mydockerorg,
 registry.authtoken=$(echo '{"username":"myDockerUsername","password":"myDockerPassword","email":"[email protected]"}' | base64),
 basedomain=mydomain.mytld
Note: Be sure to run the above command all on one line with no spaces between the different key=value pairs! Also, I had some trouble getting the Google Container Registry to work, but it seems to be supported.

This spins up a draftd deployment and some draft pods in your kube-system namespace. These help manage the connection with the docker image repository.

Deploy Your App!

Phew! That was a lot of setup! Now that this is done, it’s time to use Draft! The first command to run is draft create. That will scaffold out your helm chart (/chart) and /Dockerfile. It will also create a draft.toml that allows you to control different environments for your application as well as where it is installed in your cluster. To give your app a name (the default works just fine too!) edit draft.toml:

[environments]
  [environments.development]
    name = "cool-beans"
    namespace = "draft"
    watch = true
    watch_delay = 2

Then run draft up and watch the magic happen:

$ draft up
 --> Building Dockerfile
 Step 1 : FROM golang:onbuild
 # Executing 3 build triggers...
 Step 1 : COPY . /go/src/app
 Step 1 : RUN go-wrapper download
 ---> Running in 825771ecaf59
 ...
 # Some docker output...
 ...
 --> Deploying to Kubernetes
 --> Status: DEPLOYED
 --> Notes:
http://cool-beans.mydomain.mytld to access your application

Watching local files for changes...

This will build your docker image, push your docker image to the configured container registry under the {{ .environments.development.name }} repository, and run helm install on the preconfigured helm chart at the root of the repo! It might take a second for all the resources to spin up and for the Ingress to register your new application, but you will be able to curl your application at that address:

$ curl http://cool-beans.mydomain.mytld
 hello world

But, to see the real magic, make a change to your application:

// main.go

func sayHello(w http.ResponseWriter, r *http.Request) {
  message := "I don't know Margo...\n"
  w.Write([]byte(message))
}

Draft will rebuild your image and push those changes live with a helm upgrade:

$ curl http://cool-beans.mydomain.mytld
 I don't know Margo...

Hooking in a datasource or performing more advanced actions is just a handler edit away now!