Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
215 lines (145 sloc) 9.35 KB

+++ dep = 2 title = "Draft Design" authors = [ "Matt Fisher matt.fisher@microsoft.com" ] created = 2017-10-18 +++

Introduction

This document outlines the general design principles of Draft; what it does, how it works, what it can (and cannot) do, as well as define its intended audience and place in the market.

What Draft Does

Draft makes it easy to build applications that run on Kubernetes. Draft targets the "inner loop" of a developer's workflow: as they hack on code, but before code is committed to version control.

Once the developer is happy with changes made via Draft, they commit and push to version control, after which a continuous integration (CI) system takes over. Draft builds upon Helm and the Kubernetes Chart format, making it easy to construct CI pipelines from Draft-enabled applications.

What Draft Does Not Do

Draft is not any of the following, nor should it be used as the following:

  • a tool to be used in production deployments
  • a tool to be used in replacement for a CI/CD pipeline
  • a PaaS like Deis Workflow

The motivation behind why Draft should not be designed around these workflows is because it is purely intended to be used for a very quick development workflow when writing applications for Kubernetes. Production use cases such as secure signing, packaging and verification of chart deployments are all things handled through Helm. Since Draft creates helm-compatible artifacts, the artifacts created using Draft can then be passed along the toolchain to Helm.

Architecture

Draft has only one major component: the Draft client.

The Draft client is a command-line client, as the name suggests. The client is responsible for the following domains:

  • Building and pushing a Docker image to the Docker registry
  • Combining a chart and image to build a release through Tiller
  • Installing and upgrading charts by interacting with Tiller
  • Interacting with plugins

The Draft client interfaces with the Kubernetes API server, a Docker registry and a Tiller (Helm server) instance.

Under the covers, Draft works with several components to achieve this architecture:

  • A Kubernetes cluster - hosts the applications deployed by Draft
  • A Docker Engine - builds application source code using a Dockerfile
  • A Docker Registry - stores the artifacts built from draft up
  • The Helm Tiller server - deploys the image artifacts to the Kubernetes cluster

Rationale

Early versions of Draft was originally designed around a client/server architecture: Draft and Draftd. Draft would package and ship uploads to Draftd, while Draftd would build the docker image, push to a registry and deploy to Kubernetes using Helm. This came with a number of limitations, most notably:

  • draft init controls were often clunky and cumbersome
  • Running a docker daemon in-cluster was incredibly insecure
  • the Docker daemon only worked on clusters with overlayfs as the backing filesystem
  • RBAC controls between draft, draftd and tiller was complex
  • TLS configuration between draft, draftd, docker, the docker registry and tiller was also complex
  • alternative builder runtimes could not be implemented, at least not without bloating the system setup
  • docker registry authentication would only work on a small subset of systems
  • client and server-side extensions were limited in scope

Draft Workflow

Draft starts with draft create. In this case, you must use a Draft pack (a preconfigured template for your chart) to tell Draft how to use your source code.

When draft create is executed on an application, Draft performs a deep search on the current directory to determine the language, then starts iterating through the packs available in $(draft home)/packs. If it finds a pack that matches the language description, it will then use that pack to bootstrap the application.

Draft's smart pack detection can be overridden with the --pack flag. The detection logic will not be run and Draft will bootstrap the app with the specified pack, no questions asked.

Draft provides some default packs, but it's easy to add custom ones. DEP 3 goes into more detail on the Draft Pack format, and DEP 4 explains how to extend Draft with more language packs.

Start from scratch

If you want to start with an application, you can simply run draft create and it will scaffold a chart and a Dockerfile for you.

Start from a Dockerfile

Say you have an application that is already Dockerized, but not Helm-ified. Draft can start from your existing Dockerfile and create a new app:

$ ls
Dockerfile
src/
$ draft create
--> Draft detected the primary language as Python with 85.990338% certainty.
--> Ready to sail
$ ls
chart/
Dockerfile
draft.toml
src/

In the example above, draft create constructed a new Helm Chart for you, and stored it alongside your source code so that you can add it to version control, and even manually edit it.

Start from an existing Chart

If you've already created Kubernetes applications, you can start with an existing chart and begin using Draft. There are a few patterns you may need to follow to meet the expectations for Draft, but this is a matter of a few minutes of work; not a complete refactoring.

In this case, you don't even need draft create. You can just create the directory structure, add a draft.toml and sail onward.

Deploying your code

When you run draft up, Draft deploys your code to your Kubernetes cluster for you. It does the following:

  • Packages your code using a docker build.
  • Sends your code to a Docker Registry.
  • Installs (or upgrades) your chart using Helm

Take to Production

When you're done with development, Draft's "first class" objects are all supported by the Kubernetes toolchain. Deploy the chart to your production cluster in whatever way suits you, be it through a CI/CD pipeline or a helm install.

For docs on taking your chart to production, see Helm's Best Practices on Charts.

Reference Implementation

Imagine an app named my-app, which contains a Dockerfile and some source:

myapp/
 Dockerfile
 src/
   app.py

After running draft create, this directory would have a chart built for it:

myapp/
 chart/
   python/
     Chart.yaml
     templates/
       deployment.yaml
       service.yaml
     values.yaml
 Dockerfile
 src/
   app.py

The chart/ directory is a complete Helm chart, tailored to your needs.

Inside of the values.yaml file, Draft configures images for your chart:

image:
  repository: gcr.io/bacongobbler/myapp
  tag: 0.1.0

This information is then available to all of your Helm charts. (e.g. via {{.Values.image.repository}})

The contents of the templates/ directory are determined by the particular Pack you've used.

Example applications that can be deployed using Draft can be found in the examples/ directory in the Draft project.

Q&A

Can I have multiple Draft charts in the same repo?

At this time, no. You can however use a requirements.yaml in your chart to note what your chart depends on.

Can I modify the chart, or do I have to accept whatever the pack gives me?

You can modify the contents of the chart/ directory as you wish. Consider them part of your source code.

Keep in mind that there are certain values injected from Draft into the chart which you'll likely want to use:

image:
  repository: quay.io/bacongobbler/myapp  # the full name of the image
  tag: 08db751                            # the release of the image in the registry
basedomain: example.com                   # the base domain configured with the ingress controller
ondraft: true                             # metadata to demonstrate this was deployed using Draft

How do I add an existing chart to Draft?

Just copy (helm fetch) it into the chart/ directory. You need to tweak the values file to read from image.repository and image.tag if you want draft to regenerate Docker images for you. See above.

How do I deploy applications to production?

Draft is a developer tool. While you could simply use draft up to do this, we'd recommend using helm package in conjuction with a CI/CD pipeline.

Remember: You can always package a Draft-generated chart with helm package and load the results up to a chart repository, taking advantage of the existing Helm ecosystem.

User Personas and Stories

Persona: Inexperienced Kube Dev

This user wants to just work in their normal environment, but be able to deploy to Kubernetes without any extra work.

Persona: Kubernetes App Developer

This user knows all about Kubernetes, but doesn't enjoy the hassle of scaffolding out the same old stuff when testing changes. This user wants a starting point to deploy in-progress changes to a cluster.

  • As a user, I want to create a new Kubernetes app...
    • from scratch
    • from existing code
    • from a Dockerfile
    • from a chart
    • from some Kubernetes manifest files
  • As a user, I want my app deployed quickly to a dev cluster
  • As a user, I want to code, and have the deployed version auto-update
  • As a user, I want to be as ignorant of the internals as possible, but still be able to GSD.
  • As a user, I want to be able to hand off code artifacts without having to prepare them.
You can’t perform that action at this time.