Create A Simple Python Web Application That Interacts With Your Kubernetes Cluster

Create A Simple Python Web Application

Introduction

In this article, we will be creating a very simple web application using the popular python web framework, Django that can interact with your kubernetes cluster. One of the main reasons why you would want to develop something like this is if you want some of your users (perhaps within the company) a simple straightforward solution to provide limited view and access to the cluster. So instead of going through the tedious process of managing individual users, tokens and setting up RBAC permissions, you can just provide a single window for them to easily gain access as well as maybe perform some basic updates.

Here are some other use-cases of why you’d want to provide another layer of access to your cluster.

  • Reporting - There could be a separate team in your company that would want to look at how your pod behaves or scales in a period of time and you’d want to provide a simple UI for them instead of providing this manually in an interval. You can even improve this with an automated email or even export data to a csv file.
  • Security - Since you basically must control what action can be taken or what can be viewed at the application level, you don’t need to worry about scenarios where users can have incorrect permissions and have access to areas of your cluster where they shouldn’t.
  • Troubleshooting and Support - There may be cases where support and troubleshooting is handled by a team other than your development team. So you may provide them a simple to use web page that will allow users to view pod logs to aid with their investigation. Customizability - While it's true that there are many 3rd party tools that provide another layer of access to your cluster, there may be a chance that the specific set of features you’re looking for are not supported out of the box. Creating your own web application, gives you the freedom to extend and customize your application depending on whatever you need.

Why Python?

One of the neat features of Kubernetes is to allow programmatic access to the Kubernetes API. Kubernetes provides a client library based on python which we will be using in this article.

Python is one of the most versatile programming languages today and one of the most widely used programming languages in the field of DevOps. If you’re someone who is new to programming and wants to get started, you can’t go wrong with the Python programming language. It’s still the top programming language to learn to date. The best thing about Python is that there are globally-recognized certifications from Python Institute that you can add to your credentials. These certifications don’t expire, so you take them with you wherever you go.

The Python Institute has three levels of python programming certification:

  1. PCEP™ – Certified Entry-Level Python Programmer
  2. PCAP™ – Certified Associate in Python Programming
  3. PCPP™ – Certified Professional in Python Programming 1 and 2

Obtaining these certifications not only amplifies your skills and career as a Python programmer, but also aligns your python programming capabilities to best practices and standards. KodeKloud has amazing courses on these Python certifications that will help you gain the skills needed to pass both PCEP and PCAP certifications. You can check them out here:

  1. KodeKloud: Certified Python Entry-Level Programmer – PCEP Certification Prep Course
  2. KodeKloud: Certified Associate in Python Programming – PCAP Certification Prep Course

All of KodeKloud courses have interactive labs straight to your browser where you can practice what you’ve learned and further speed up your progress. They also have a course on the Golang programming language. Golang is another programming language that is quickly rising in terms of trends in the DevOps community. You can check out Kodekloud’s Golang course here if you’re interested. Aside from these, KodeKloud also has other courses that will overall help you become a great DevOps engineer. So definitely check them out.

In this article, we will be using the Django web framework. It is a feature-rich web framework for python. It allows us to quickly develop a page with minimal commands and a few lines of code. It is the most popular python framework available today, it has support for multitudes of add-ons and plugins and with great popularity comes great support from the community as well and you can expect long-term updates. Now you don’t have to know the Django framework in-depth to follow along. In fact, you can use different python frameworks available if that is what you prefer. We’ll just be using this framework to further speed up the process so we don’t have to write everything from scratch. We’ll be going through each step from installation to bringing up the first web page.

1. Setup a test Kubernetes cluster using Minikube

Minikube allows us to run an entire single-node Kubernetes cluster on our local computer. Minikube is usually used for creating a sandbox for learning and testing Kubernetes features and commands. In this project we’ll be setting up a simple minikube cluster that will be later referenced by our python web application. You can follow this guide if you wish to install minikube on your local machine.

Once minikube is installed, we can simply run the following command to start our Kubernetes cluster:

:~/kubernetes$ minikube start

This should download and set up the latest version of Kubernetes to your local machine.

😄  minikube v1.25.2 on Debian bookworm/sid
✨  Using the docker driver based on existing profile
👍  Starting control plane node minikube in cluster minikube
🚜  Pulling base image ...
🏃  Updating the running docker "minikube" container ...
🐳  Preparing Kubernetes v1.23.3 on Docker 20.10.12 ...
    ▪ kubelet.housekeeping-interval=5m
🔎  Verifying Kubernetes components...
    ▪ Using image gcr.io/k8s-minikube/storage-provisioner:v5
🌟  Enabled addons: storage-provisioner, default-storageclass
🏄  Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default

Once minikube is up, we can now run kubectl commands to interact with our Kubernetes cluster.

:~/kubernetes$ kubectl get nodes
NAME       STATUS   ROLES                  AGE   VERSION
minikube   Ready    control-plane,master   43h   v1.23.3

Let’s go ahead and create an nginx pod that we can later fetch from our python web application.

:~/kubernetes$ kubectl run nginx --image=nginx
pod/nginx created
:~/kubernetes$ kubectl get pods
NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          34s

Alright, so we should be done with the Kubernetes setup. Let’s go ahead and proceed to create our python web application.

2. Install Python 3

In order to get started with our web application, you will need to have the latest python version installed on your computer. If you don’t have it yet, you can go to the official Python download page and download and install the latest version and the one that matches your operating system.

Once installed, you can verify the version by running the command:

:~$ python3 --version
Python 3.10.4

3. Installing prerequisites

Once python is installed on your computer, let’s install pip3. Pip3 is the official package manager for python. We can add different packages and features to our python project by installing them through pip. We’ll be using pip to install other packages we need in order to bootstrap our project. Now for this project, I’m using a debian-based linux distribution so if you’re on a different operating system the process may be different.

We can install pip3 by executing the command:

:~$ sudo apt-get install python3-pip

After the installation, we can verify the version with this command:

:~$ pip3 --version
pip 22.1.2 from ~/.local/lib/python3.10/site-packages/pip (python 3.10)

Once pip3 is installed, let’s go ahead and install pipenv. Pipenv allows us to package our python project in its own environment. Any packages that we install in our project would only take effect in the virtual environment that pipenv provides. Thus, making our host computer safe from any possible breaking changes.

To install pipenv let’s run this command:

:~$ pip3 install pipenv

Note: once pipenv is installed, you may also need to add the directory where it was installed to your host computer’s $PATH

Let’s verify if pipenv was installed successfully by verifying its version.

:~$ pipenv --version
pipenv, version 2022.6.7

4. Creating our project

Now, let’s go ahead and create our project folder and name it a cluster.

:~$ cd ~
:~$ mkdir cluster
:~$ cd cluster
:~/cluster$ 

Then install the Django package through pipenv.

:~/cluster$ pipenv install django

This will create 2 new files, Pipfile and Pipfile.lock. These files keep track of different packages installed in our project as well as list down the versions used at the time of installation. This will also create a virtual environment to enclose the entire project.
Now that the Django package has been installed, let’s go inside the virtual environment that pipenv created for this project. This is so that any commands we execute should only affect the project and not the host computer.

:~/cluster$ pipenv shell
Launching subshell in virtual environment...
:~/cluster$ source ~/.local/share/virtualenvs/cluster-G7emmHve/bin/activate
(cluster) :~/cluster$ 

We can now use different Django commands. Let’s go ahead and initialize our project with the following command.

(cluster) :~/cluster$ django-admin startproject cluster .

This will create all the necessary files to bootstrap your Django project.

One of the created files is called manage.py. This file allows us to directly interact with our django application so instead of using django-admin we’ll use manage.py to further execute django commands into our project.

Let’s now run our project through a development server that django-admin provides with the following command:

(cluster) :~/cluster$ python3 manage.py runserver

Notice that it mentions migrations. We won’t be using any database for this project so we can ignore this.

Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).

You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
June 11, 2022 - 09:23:11
Django version 4.0.5, using settings 'cluster.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

It should output the URL where our app can be accessible. Now our project is up and running.

5. Creating our first application

Now, let’s go and create our first application by running the command:

(cluster) :~/cluster$ python3 manage.py startapp home

This should create a new folder in our project called home with a different set of files.

We will need to register our new app in the settings.py file of our project by simply adding the name of the application of the INSTALLED_APPS list.

6. Adding a template

Now for this project, let’s set a goal that when a user accesses the url /cluster/nodes, it will display the node information of our cluster. And when the user accesses the URL /cluster/pods it will then display pods information in the cluster.

Let’s go ahead and create a new directory named templates in the home folder. Then create two html files, first one is nodes.html and then pods.html. It should look like this.

Then let’s put in a bit of content inside the two files so we can later identify if we’re able to access them successfully.

Next, we’ll update the home/views.py file and add two functions that will point to those HTML files we created earlier.

Next, let’s create a new file called urls.py inside the home folder with the contents below. Notice how we were importing views.py in order for us to reference the function we created earlier.

Then finally, we update cluster/urls.py and register the new urls.py we created earlier inside the home folder with a path /cluster

And that's it! Let’s test both routes and see if they’re working correctly.

7. Installing the Kubernetes package

Now that we’ve completed the initial pages for our web application, it’s time to add the kubernetes-client package to our project. To do that, we just need to execute the following command:

(cluster) :~/cluster$ pipenv install kubernetes
/usr/lib/python3/dist-packages/pkg_resources/__init__.py:116: PkgResourcesDeprecationWarning: 0.1.43ubuntu1 is an invalid version and will not be supported in a future release
  warnings.warn(
Courtesy Notice: Pipenv found itself running within a virtual environment, so it will automatically use that environment, instead of creating its own for any project. You can set PIPENV_IGNORE_VIRTUALENVS=1 to force pipenv to ignore that environment and create its own instead. You can set PIPENV_VERBOSITY=-1 to suppress this warning.
Installing kubernetes...
Adding kubernetes to Pipfile's [packages]...
✔ Installation Succeeded 
Pipfile.lock (79baf8) out of date, updating to (3c871c)...
Locking [dev-packages] dependencies...
Locking [packages] dependencies...
Building requirements...
Resolving dependencies...
✔ Success! 
Updated Pipfile.lock (3c871c)!
Installing dependencies from Pipfile.lock (3c871c)...
  🐍   ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ 1/1 -- 00:00:00
To activate this project's virtualenv, run pipenv shell.
Alternatively, run a command inside the virtualenv with pipenv run.
(cluster) :~/cluster$ 

To verify if it’s been successfully added to the project, you can check out the contents of the Pipfile file. It should add Kubernetes under packages. Once installed, this will now allow us to import Kubernetes modules.

8. Kubernetes client API endpoints

The kubernetes-client for python includes a wide array of API endpoints you can use to interact with a Kubernetes cluster. All methods are organized and categorized by class. You can refer to the full list here to see what methods are available and you can use them in your python application.

9. Updating the nodes page

Let’s go ahead and put some functionality to our nodes page and actually have it display nodes information from our cluster. In home/views.py let’s modify the display_nodes function we created earlier.
home/views.py

from django.shortcuts import render
from django.http import HttpResponse
from kubernetes import client, config

# Create your views here.
def display_nodes(request):
    config.load_kube_config()
    v1 = client.CoreV1Api()
    nodes = v1.list_node().items
    return render(request, 'nodes.html', {'data': nodes})

Let’s go through each line of code we added here. First, we imported the client and config module from the Kubernetes package.

from kubernetes import client, config

Then we loaded are ~/.kubeconfig file which will then load our local minikube cluster.

config.load_kube_config()

Then we created a new CoreV1Api() object from the client module. Now the reason why we’re using CoreV1Api is If you look at the list of methods and classes from the kubernetes-client documentation, there’s a method there called list_node which would allow us to pull information related to nodes from our cluster. list_node method is under the CoreV1Api class.

v1 = client.CoreV1Api()

We then assign the values from the list_node method to variable named nodes. Afterward, we pass that value in the render function as a data parameter.

return render(request, 'nodes.html', {'data': nodes})

If we print the value of nodes here, we are presented with a dictionary. Inside that dictionary, there’s a list called items. This list contains information about each node in the cluster. Since we’re using minikube which is a single-node Kubernetes cluster, we should expect to only see 1 node inside this list.

{'api_version': 'v1',
 'items': [{'api_version': None,
            'kind': None,
            'metadata': {'annotations': {'kubeadm.alpha.kubernetes.io/cri-socket': '/var/run/dockershim.sock'.....

Now our home/templates/nodes.html should now have a variable named data that contains the information about the nodes in our cluster. Let’s pull some information about our node.

home/templates/nodes.html

<h1>You're in the Nodes page!</h1>
{% for item in data %}
    {{ item.metadata.name }}
    <hr>
    {{ item.metadata.labels }}
    <hr>
    {{ item.status }}
{% endfor %}

Let’s refresh our browser and now we see that the nodes page is now displaying the name, labels, and status of the only node in the cluster.

10. Updating the Pods page

For the pods page, we’ll apply the same changes. But instead of using the list_pods method, in order to list pods, we can use the list_pod_for_all_namespaces method which will allow us to display information for pods in all namespaces.

home/views.py

def display_pods(request):
    config.load_kube_config()
    v1 = client.CoreV1Api()
    all_pods = v1.list_pod_for_all_namespaces()
    return render(request, 'pods.html', {'data': all_pods.items})

Since the data for all components in Kubernetes shares almost the same data structure, we can also reference data similar to our nodes page.

home/templates/pods.html

<h1>You're in the Pods page!</h1>
{% for item in data %}
    {{ item.metadata.name }}
    <hr>
    {{ item.metadata.labels }}
    <hr>
    {{ item.status }}
{% endfor %}

Our Pods page now displays information on pods currently running in the cluster.

Conclusion

In this project we are just fetching data from the cluster however, there’s a ton of functionality you can add to your web application such as creating or modifying objects in your Kubernetes cluster. You can find more information on the different APIs you can utilize in the python kubernetes-client’s github repository.

This simple project should give you an idea of what’s possible when using the kubernetes-client with your python web application. it’s a little rough since we’re basically displaying raw data to the page. But of course, the design and presentation of these pages can be further improved as well as customized with the help of additional CSS or front-end frameworks depending on what your particular requirements are.

If you’re looking to learn more about Python or Kubernetes, KodeKloud offers a wide variety of DevOps courses that covers these subjects. Having a single subscription gives you access to all their courses from beginner all the way to certification courses. The labs included in their courses can be accessed straight to your browser and are built to challenge you and further solidify what you learn as you go.