Launch web app in local kubernetes using helm with monitoring. The awesome local playground tutorial for those who study DevOps!

Part 1:

  • write a basic Django application
  • pack up the application into a docker image
  • prepare a helm package (chart)

To complete the tutorial, you will need:

Django

Let's make a simple Django web application without getting into too much detail.

  1. Create a project folder:
$ mkdir django-tutorial
  1. Create a standard requirements.txt file with dependencies:
$ cat <<EOF >>requirements.txt
django==2.1.2
EOF
  1. Initialize the virtual environment and install Django in it:
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
  1. Now, we can generate a simple helloworld project using the django-admin utility
django-admin startproject helloworld
  1. This way, you're able to create a project with the following structure:
tree helloworld
helloworld
├── helloworld
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── manage.py
  1. Create a views.py file in the helloworld/helloworld folder:
cat <<EOF >>helloworld/helloworld/views.py
from django.views.generic import View
from django.http import HttpResponse

class HelloWordView(View):
    def get(self, request):
        return HttpResponse(
            "Helloword!"
        )
EOF
  1. Add path('', HelloWordView.as_view()) into urls.py:
cat <<EOF >>helloworld/helloworld/urls.py
from django.contrib import admin
from django.urls import path

from .views import HelloWordView

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', HelloWordView.as_view())
]
EOF
  1. Since the application is to be installed in the local cluster, change the ALLOWED_HOSTS parameter in settings.py (NOTE: it is unacceptable to do this in production):
ALLOWED_HOSTS = ['*']
  1. Now we have a simple application that we can run locally via python manage.py runserver and open in a browser via localhost:8000.

Docker

To install the application in k8s, you first need to create a Docker image. Select a simple base image and install Python dependencies into it. Copy the code to the image and launch the application server. The python manage.py runserver is not suitable for production, so use any WSGI-friendly server instead, e.g. Gunicorn or Uwsgi.

  1. Go to the project root folder and create a Docker file that looks the following way:
cat <<EOF >>Dockerfile
FROM python:3.7-alpine

RUN apk add python3-dev build-base linux-headers pcre-dev mariadb-connector-c-dev
RUN pip install uwsgi

WORKDIR /etc/app
COPY ./requirements.txt ./
RUN pip install -r requirements.txt

COPY ./ ./

CMD ["uwsgi", "--chdir=/etc/app", "--module=helloworld.wsgi:application", "--master", "--pidfile=/tmp/project-master.pid", "--http=0.0.0.0:8080", "--processes=5", "--uid=1000", "--gid=2000", "--harakiri=20", "--max-requests=5000", "--vacuum"]
EOF
  1. Make sure that you're using the same docker daemon as k8s does, and run an image**:**
docker build -t django-tutorial .

Helm

Helm is one of the most popular package managers for k8s.

It is recommended that we use Helm in this tutorial, as it enables us to quickly launch Grafana charts and Prometheus for the monitoring purpose; the parameters are described in the comments quite neatly, and the chart structure gives a good insight into which specific Kubernetes resources will be installed. We won't get too deep into Helm here, as there's a large number of articles that can tell about its basics, pros and cons.

So, back to creating a chart for our helloworld application.

  1. Create a base for the Helm chart.
helm create django-tutorial
  1. You should get the following structure:
django-tutorial
├── Chart.yaml
├── charts
├── templates
│   ├── NOTES.txt
│   ├── _helpers.tpl
│   ├── deployment.yaml
│   ├── ingress.yaml
│   └── service.yaml
└── values.yaml
  • Chart.yaml contains the package metadata
  • values.yaml contains chart configuration parameters
  • The templates folder contains templates for the Kubernetes resources
  • You may also find a file named requirements.yaml which contains dependencies
  • The charts folder contains packages with dependencies. You can use either of the two options: 1) keeping the list of dependencies in requirements.yaml and updating them with the helm package command; or, simply storing child charts in this folder.
  1. Change the values.yaml file, refer/link to the previously created image containing our application. Make sure that in Kubernetes you're using the same docker daemon; otherwise you'll have no access to this image.
image:
  repository: django-tutorial # Docker image name
  tag: latest 
  pullPolicy: Never # Use local image
  1. In this tutorial, we aren't going to use Ingress or LoadBalancer to access the services outside our cluster; we'll just use NodePort. NodePort is a special type of service which opens a host port within the range/interval of 30000–32767 and re-directs all the traffic from it to the defined/selected/specified service.
service:
  type: NodePort
  port: 8080
  1. In helloworld/django-tutorial/templates/deployment.yaml, change containerPort from 80 to 8080.
ports:
            - name: http
              containerPort: 8080
              protocol: TCP
  1. Install a chart with release name django-tutorial; if you don't specify the name, Kubernetes will pick a random one.
helm install . --name django-tutorial
  1. The list of releases can be viewed through a command. We now have our release set up successfully with status "Deployed":
helm ls
NAME           	REVISION	UPDATED                 	STATUS  	CHART                	APP VERSION	NAMESPACE
django-tutorial	1       	Thu Jan 10 21:51:14 2019	DEPLOYED	django-tutorial-0.1.0	1.0        	default
  1. Check the pod status:
kubectl get pods
NAME                             READY   STATUS    RESTARTS   AGE
django-tutorial-9b485585-t2hxd   1/1     Running   0          3d
  1. Now, view the list of services installed. Our application should be available at localhost:32319:
kubectl get services
NAME              TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
django-tutorial   NodePort    10.104.171.0   <none>        8080:32319/TCP   2s

In the Part 2:

  • set up the export of Django's standard metrics
  • add one custom metric
  • set up the monitoring of the application's separate segments and the monitoring of the whole cluster, with Prometheus
  • visualize these data with Grafana
  • set up alerts with Amixr

Stay tuned!