Applications

Web demo app

Describe the application

We will deploy an nodejs application that return Hello world from... the hostname hosting the app. Sources available into app/webtest directory.

The application code :

'use strict';

var os = require('os');
const express = require('express');

// Constants
const PORT = 8080;
const HOST = '0.0.0.0';

// App
const app = express();
app.get('/', (req, res) => {
  res.send("Hello world from " + os.hostname() + " (" + os.release() + ")\n");
});

app.listen(PORT, HOST);
console.log(`Running on http://${HOST}:${PORT}`);

The Dockerfile to create the container image :

FROM node:8

WORKDIR /usr/src/app

COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 8080

CMD [ "npm", "start" ]

Deployment

From the kubernetes master (rake shell), create a Kubernetes deployment with file apps/webtest/kubefiles/deploy.yaml :

apiVersion: apps/v1
kind: Deployment
metadata:
  name: webtest
  labels:
    app: webtest
spec:
  replicas: 4
  selector:
    matchLabels:
      app: webtest
  template:
    metadata:
      labels:
        app: webtest
    spec:
      containers:
      - name: webtest
        image: registry.gitlab.inria.fr/pmorillo/g5k8s/webtest:latest
        ports:
        - containerPort: 8080

Create a Kubernetes service with file app/webtest/kubefiles/service.yaml :

kind: Service
apiVersion: v1
metadata:
  name:  webtest
  labels:
    app: webtest
spec:
  selector:
    app:  webtest
  ports:
  - port:  8080
    targetPort:  8080
    protocol: TCP

Create resources :

kubectl create -f /mnt/home/repos/gitlab/g5k8s/apps/webtest/kubefiles/

Show the deployment :

kubectl get all --selector=app=webtest -o wide
NAME                           READY     STATUS    RESTARTS   AGE       IP           NODE        NOMINATED NODE
pod/webtest-5848c4954c-4q4mm   1/1       Running   0          32m       10.244.4.2   kubenode3   <none>
pod/webtest-5848c4954c-gg8rt   1/1       Running   0          32m       10.244.3.2   kubenode2   <none>
pod/webtest-5848c4954c-ncvsl   1/1       Running   0          32m       10.244.1.2   kubenode1   <none>
pod/webtest-5848c4954c-s5f7w   1/1       Running   0          32m       10.244.2.3   kubenode0   <none>

NAME              TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE       SELECTOR
service/webtest   ClusterIP   10.110.132.150   <none>        8080/TCP   30m       app=webtest

NAME                      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE       CONTAINERS   IMAGES                     SELECTOR
deployment.apps/webtest   4         4         4            4           32m       webtest      pmorillon/webtest:latest   app=webtest

NAME                                 DESIRED   CURRENT   READY     AGE       CONTAINERS   IMAGES                     SELECTOR
replicaset.apps/webtest-5848c4954c   4         4         4         32m       webtest      pmorillon/webtest:latest   app=webtest,pod-template-hash=1404705107

We can see 4 replicas deployed on 4 nodes (kubenode0, kubenode1, kubenode2, kubenode3) and a service exposed on 10.110.132.150:8080.

Show logs from pods :

kubectl logs webtest-5848c4954c-4q4mm

> webtest@1.0.0 start /usr/src/app
> node server.js

Running on http://0.0.0.0:8080

Check the service

for i in $(seq 1 10); do curl http://10.110.132.150:8080; done
Hello world from webtest-5848c4954c-s5f7w (4.15.0-20-generic)
Hello world from webtest-5848c4954c-4q4mm (4.15.0-20-generic)
Hello world from webtest-5848c4954c-gg8rt (4.15.0-20-generic)
Hello world from webtest-5848c4954c-4q4mm (4.15.0-20-generic)
Hello world from webtest-5848c4954c-s5f7w (4.15.0-20-generic)
Hello world from webtest-5848c4954c-ncvsl (4.15.0-20-generic)
Hello world from webtest-5848c4954c-ncvsl (4.15.0-20-generic)
Hello world from webtest-5848c4954c-4q4mm (4.15.0-20-generic)
Hello world from webtest-5848c4954c-4q4mm (4.15.0-20-generic)
Hello world from webtest-5848c4954c-s5f7w (4.15.0-20-generic)

Expose service with external IP

Edit webtest service and replace spec.type ClusterIP by LoadBalancer :

kubectl edit svc webtest
kubectl get svc webtest
# NAME      TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
# webtest   LoadBalancer   10.47.168.86   10.158.1.1    8080:30641/TCP   6m50s

From the frontend :

curl http://10.158.1.1:8080 
# Hello world from webtest-77764787cc-qq6cz (4.19.0-8-amd64)