Draft is a tool built for developers who do their dev work against a Kubernetes environment (whether it be a live cluster of a Minikube instance).
It really helps speed up development time by helping out with the code -> build -> run -> test dev cycle. It does this by scaffolding out a Dockerfile and Helm Chart template pack customised for your app with a single command and then by building and deploying your application image to your Kubernetes environment with a second.
Setting up Draft and a basic .NET Core Web API project
First off, make sure you have already set up your kubectl configuration to be able to talk to your Kubernetes cluster, and have also setup and configured Helm.
Set the Draft binary up in a known system path on your machine after downloading it from the Draft Releases page.
Run draft init
to initialise Draft. It’ll drop it’s configuration in a subdirectory of your user profile directory called .draft.
Create a new .NET Core 2.1 ASP.net project and select Web API as the type.
Open a shell and navigate over to the root project directory of your new .NET Core 2.1 app. E.g. cd solution\projectname
Run draft create
to setup Draft with your new project. This is where the Draft magic happens. Essentially, Draft will:
- Detect your application code language. (In this case csharp)
- Create a Dockerfile for your app
- Set up a Helm chart and necessary template structure to easily deploy your app into Kubernetes direct from your development machine
You should see output similar to this:
PS C:\git\draftdotnetcorewebapi\draftdotnetcorewebapi> draft create --> Draft detected JSON (97.746232%) --> Could not find a pack for JSON. Trying to find the next likely language match... --> Draft detected XML (1.288026%) --> Could not find a pack for XML. Trying to find the next likely language match... --> Draft detected csharp (0.914658%) --> Ready to sail
At this point you could run draft up
and if you have a container registry setup for Draft on your machine already, it would build and push your Docker image and then deploy your app into Kubernetes. However, if you don’t yet have a container registry setup for Draft you’ll need to do that first.
draft config set registry docker.io/yourusernamehere
PS, just make sure your local development machine has credentials setup for your container registry. E.g. Docker Hub.
Run your app with Draft (and help from Helm)
Now run draft up
PS C:\git\draftdotnetcorewebapi\draftdotnetcorewebapi> draft up Draft Up Started: 'draftdotnetcorewebapi': 01CH1KFSSJWDJJGYBEB3AZAB01 draftdotnetcorewebapi: Building Docker Image: SUCCESS ⚓ (45.0376s) draftdotnetcorewebapi: Pushing Docker Image: SUCCESS ⚓ (10.0875s) draftdotnetcorewebapi: Releasing Application: SUCCESS ⚓ (3.3175s) Inspect the logs with `draft logs 01CH1KFSSJWDJJGYBEB3AZAB01`
Awesome. Draft built your application into a Docker image, pushed that image up to your container registry and then released your application using the Helm Chart it scaffolded for you when you initially ran draft create.
Take a look at Kubernetes. Your application is running.
kubectl get deployments
PS C:\git\draftdotnetcorewebapi\draftdotnetcorewebapi> kubectl get deployments NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE draftdotnetcorewebapi-csharp 1 1 1 1 7m
Iterating on your application
So your app is up and running in Kubernetes, now what?
Let’s make some changes to the Helm chart to get it deploying using a LoadBalancer (or NodePort if you’re using Minikube). Let’s also add a new Api Controller called NamesController
that simply returns a JSON array of static names with a GET request.
using Microsoft.AspNetCore.Mvc; namespace draftdotnetcorewebapi.Controllers { [Route("api/[controller]")] [ApiController] public class NamesController : ControllerBase { [HttpGet] public ActionResult<IEnumerable> Get() { return new string[] { "Wesley", "Jean-Luc", "Damar", "Guinan" }; } } }
Change your charts/csharp/values.yaml file to look like this (use NodePort if you’re trying this out with Minikube):
using Microsoft.AspNetCore.Mvc; # Default values for c#. # This is a YAML-formatted file. # Declare variables to be passed into your templates. replicaCount: 1 image: pullPolicy: IfNotPresent service: name: dotnetcore type: LoadBalancer externalPort: 8080 internalPort: 80 resources: limits: cpu: 1 memory: 256Mi requests: cpu: 250m memory: 256Mi ingress: enabled: false
Run draft up
again. Your app will get built and released again. This time you’ll have a LoadBalancer service exposed and your updated application with the new API endpoint will be available within seconds.
This time however Draft was clever enough to know that it didn’t need a new Helm release. Using Helm, it determined that an existing release was already in place and instead did a helm upgrade
underneath the covers. Test it for yourself with a helm list
PS C:\git\draftdotnetcorewebapi\draftdotnetcorewebapi> helm list NAME REVISION UPDATED STATUS CHART NAMESPACE draftdotnetcorewebapi 2 Wed Jun 27 23:10:11 2018 DEPLOYED csharp-v0.1.0 default
Check the service’s External IP / URL and try it out by tacking on /api/names on the end to try out the new Names API endpoint.
PS C:\git\draftdotnetcorewebapi\draftdotnetcorewebapi>PS C:\git\draftdotnetcorewebapi\draftdotnetcorewebapi> kubectl get service draftdotnetcorewebapi-csharp -o wide NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR draftdotnetcorewebapi-csharp LoadBalancer 100.66.92.87 aezzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz.us-east-2.elb.amazonaws.com 8080:31381/TCP 32m app=draftdotnetcorewebapi-csharp
Draft clean up
To take your app down and delete the Helm release, simply issue a draft delete
on the command line.
PS C:\git\draftdotnetcorewebapi\draftdotnetcorewebapi> helm list NAME REVISION UPDATED STATUS CHART NAMESPACE draftdotnetcorewebapi 2 Wed Jun 27 23:10:11 2018 DEPLOYED csharp-v0.1.0 default
Check the service’s External IP / URL and try it out by tacking on /api/names on the end to try out the new Names API endpoint.
PS C:\git\draftdotnetcorewebapi\draftdotnetcorewebapi> draft delete app 'draftdotnetcorewebapi' deleted
That’s all there is to it.
Draft really helps ease the monotony and pain of setting up a new project and getting it all working with Docker and Kuberenetes. It vastly improves your development cycle times too. Check it out and start using it to save time!