Getting started with Kubernetes
I recently started playing with Kubernetes and deployed a simple Express app as practice. You can follow along after you have installed minikube for your OS.
You can then follow along this tutorial after cloning the my github repo.
Node applications
We are going to build two Express apps: the main app responds with Hello World
and the health app responds to /health and /readiness requests.
node-app
:
GET /
=> Hello World
health-app
GET /health
=> 200
GET /readiness
=> 200
The official NodeJS site has a great little article about building a node docker image so I will not go over that again here.
Let's just take a look at the two server.js
files for our main and health apps.
// ~/learn/kubernetes/app/health/server.js
'use strict';
const express = require('express');
// Constants
const PORT = 8081;
// App
const app = express();
app.get('/health', function (req, res) {
res.sendStatus(200);
});
app.get('/readiness', function (req, res) {
res.sendStatus(200);
});
app.listen(PORT);
console.log('Running on http://localhost:' + PORT);
// ~/learn/kubernetes/app/main/server.js
'use strict';
const express = require('express');
// Constants
const PORT = 8080;
// App
const app = express();
app.get('/', function (req, res) {
res.send('Hello world\n');
});
app.listen(PORT);
console.log('Running on http://localhost:' + PORT);
Docker images
Let's build, tag and push the docker images for both applications:
~ app/main$ docker build -t tzumby/node-web-app .
~ app/health$ docker build -t tzumby/node-health .
~ app/health$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tzumby/node-web-app 1.0.0 ba16f4d69b5c 2 hours ago 649.3 MB
tzumby/node-health latest 9f6d6f6b8f78 About an hour ago 649.3 MB
You will need to create an account on hub.docker.com and push your images there:
~$ docker login
~$ docker push tzumby/node-web-app:latest
~$ docker push tzumby/node-health:latest
Kubernetes pods
A pod is a group of one or more Docker containers that run in a shared context. That means they share the same IP address and port space, same volumes attached to the pod etc.
Our pod will start two containers for each of the Docker images we built in the previous step.
apiVersion: v1
kind: Pod
metadata:
name: node-app
labels:
app: node-app
spec:
containers:
- name: node-app
image: tzumby/node-web-app:1.0.0
ports:
- name: http
containerPort: 8080
resources:
limits:
cpu: 0.2
memory: "10Mi"
- name: node-health
image: tzumby/node-health:latest
ports:
- name: health
containerPort: 8081
livenessProbe:
httpGet:
path: /health
port: 8081
scheme: HTTP
initialDelaySeconds: 5
periodSeconds: 15
timeoutSeconds: 5
readinessProbe:
httpGet:
path: /readiness
port: 8081
scheme: HTTP
initialDelaySeconds: 5
timeoutSeconds: 1
Notice how we're exposing different ports for each app, namely 8080 and 8081.
Let's create the pod now using the kubectl tool:
~ kubernetes$ kubectl create -f pods/node-app.yaml
~ kubernetes$ kubectl get pods
NAME READY STATUS RESTARTS AGE
node-app 2/2 Running 0 1h
It may take a few second for the pod to run both containers because docker will have to download the two images from the Docker hub.
Let's setup an ad-hoc port forwarding from our host machine to the kubernetes cluster in order to test the main app.
~ kubernetes$ kubectl port-forward node-app 10080:8080
Open another terminal and let's curl the root url:
~ kubernetes$ curl http://127.0.0.1:10080
Hello world
Next
I'm very excited about using Kubernetes for a real-world setup and over the next few posts I will more concepts such as Services, Deployments and Volumes in a future post.