Skaffold: Local development with Kubernetes

Zubair Haque
3 min readOct 12, 2022

--

Skaffold is an amazing tool for doing local development with a kubernetes cluster. I’m able to locally test my changes, without having to re-deploy all the time. The productivity boost for our dev teams, is speeding up feature development and enabling a faster release cycle.

I started using Skaffold for all new projects in my current position, well for any new microservice in our ETL data pipeline and it works pretty well on a minikube cluster.

Getting Started with tooling

Let’s get our minikube cluster setup. Install minikube locally by using homebrew:

$ brew install minikube

Make sure it was installed successfully:

$ minikube version

Output:

minikube version: v1.27.1commit: fe869b5d4da11ba318eb84a3ac00f336411de7ba

Start minikube:

$ minikube start

Use the minikube addon to enable the ingress nginx controller:

$ minikube addons enable ingress

Install skaffold on your machine:

$ brew install skaffold

Validate that the install was successful:

$ skaffold version

The skaffold docs talk about their init command, which is pretty easy to run:

$ skaffold init 

So if your project has no kubernetes manifests yet, the init command tries to bootstrap your project for you. Now you can interact with all common cli tools such as kubectl & kustomize

Getting started with our app

For this skaffold demo, we’re going to create a basic NodeJS app. Add your package.json to the root directory of this project:

{
"name": "skaffold-nodejs-project",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "nodemon src"
},
"repository": {
"type": "git",
"url": ""
},
"dependencies": {
"body-parser": "^1.19.0",
"cors": "^2.8.5",
"express": "^4.17.1"
},
"devDependencies": {
"chai": "^4.3.4",
"mocha": "^9.0.2",
"nodemon": "^2.0.12",
"supertest": "^6.1.3"
}
}

Now create a src directory and create a file called index.jsand add:

const express = require('express');

const app = express();

app.get('/', (request, response) => {
response.status(200).send({ message: 'Local Development: Hello World!' });
});

app.listen(3000, () => {
console.log('Server is running!');
});

In the example above we have the following:

request: we define a route handler to make a simple GET request. The app 
will send back a 200 response and display:

"Local Development: Hello World!"

on the browser.

our app will listen in on port 3000, here is a list of other places where you will need to make changes to accommodate for this:

Dockerfile: we're going to EXPOSE port 3000 right before we run npm start
service.yaml: the Service manifest port will be set to 3000
deployment.yaml: the Deployment manifest will set the containerPort to 3000

Create a Dockerfile, skaffold will use this Dockerfile to build your images:

FROM node:16.18.0 AS build

WORKDIR /app

COPY package.json .

RUN npm install

COPY . .

EXPOSE 3000

CMD [ "npm", "run", "start" ]

Creating the Deployment Manifest File

apiVersion: apps/v1
kind: Deployment
metadata:
name: app
labels:
app: app
spec:
replicas: 1
selector:
matchLabels:
app: app
template:
metadata:
labels:
app: app
spec:
containers:
- name: app
image: express-app
resources:
limits:
memory: 512Mi
cpu: "1"
ports:
- containerPort: 3000

Creating the Service Manifest File

Now we need to create a service manifest for your deployment & that looks like this:

apiVersion: v1
kind: Service
metadata:
name: app-svc
spec:
type: NodePort
selector:
app: app
ports:
- port: 3000
targetPort: 3000

Add your skaffold.yaml file

apiVersion: skaffold/v2beta21
kind: Config

profiles:
- name: dev
activation:
- command: dev
build:
artifacts:
- image: express-app
context: .
sync:
manual:
- src: 'src/**/*.js'
dest: .

If you look at the example above you’ll see that the manual sync rule must point out the src of where the files live and the dest field, which is the relative path of your image.

Bringing up your local cluster:

skaffold dev --port-forward

Now in this output, we can see:

Listing files to watch...
- express-app
Generating tags...
- express-app -> express-app:ca56ce4
Checking cache...
- express-app: Found Locally
Tags used in deployment:
- express-app -> express-app:c1365267f7badf38c83efb341be2521a041ac566d5796fbf38ca6ac7348774d6
Starting deploy...
- deployment.apps/app created
- service/app-svc created

that the deployment & service was created. Now, when any js file changes, Skaffold will continuously apply the deployment.yaml file & build your changes,

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

Zubair Haque
Zubair Haque

Written by Zubair Haque

The Engineering Chronicles: I specialize in Automated Deployments

No responses yet

Write a response