Python API and MySQL Helm Chart

This Helm chart simplifies the deployment of a Python Flask API and a MySQL database on Kubernetes. The Python API serves a list of people stored in the MySQL database, demonstrating a basic web application architecture. To extend this project we will package the application artifacts as a Helm chart for deployment into a kubernetes clusters.

The Helm chart directory structure is organized as follows:

/myapp/
.
├── Chart.yaml
├── charts
├── templates
│   ├── api-deployment.yaml
│   ├── api-service.yaml
│   ├── mysql-deployment.yaml
│   └── mysql-service.yaml
└── values.yaml

Prerequisites

Before you begin, ensure you have the following installed:

- Kubernetes cluster (e.g., minikube, kind, or a cloud-managed Kubernetes service)
- Helm (version 3.x)

Create a New Helm Chart

Create a new Helm chart (boilerplate) in your project directory. Helm charts are the packages that Helm uses to deploy applications on compute resources such as kubernetes.

helm create myapp

Python API Deployment: This template configures the deployment of the Python API application. It uses values from the values.yaml file to set various properties like the deployment name, replica count, container image, and ports.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Values.api.name }}
spec:
  selector:
    matchLabels:
      app: {{ .Values.api.name }}
  replicas: {{ .Values.api.replicaCount }}
  template:
    metadata:
      labels:
        app: {{ .Values.api.name }}
    spec:
      containers:
      - name: {{ .Values.api.name }}
        image: {{ .Values.api.image.repository }}:{{ .Values.api.image.tag }}
        ports:
        - containerPort: {{ .Values.api.port }}
        env:
        - name: DB_HOST
          value: {{ .Values.api.dbHost }}
        - name: DB_USER
          value: {{ .Values.api.dbUser }}
        - name: DB_PASSWORD
          value: {{ .Values.api.dbPassword }}
        - name: DB_DATABASE
          value: {{ .Values.api.dbDatabase }}

Python API Service: This template configures the Kubernetes Service for the Python API. It sets the service name and maps the port from the service to the container.

apiVersion: v1
kind: Service
metadata:
  name: {{ .Values.api.serviceName }}
spec:
  type: ClusterIP
  selector:
    app: {{ .Values.api.name }}
  ports:
  - port: {{ .Values.api.servicePort }}
    targetPort: {{ .Values.api.port }}

MySQL Deployment: This deployment template is for the MySQL database. It includes environment variables like the root password pulled from the values.yaml.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Values.mysql.name }}
spec:
  replicas: {{ .Values.mysql.replicaCount }}
  selector:
    matchLabels:
      app: {{ .Values.mysql.name }}
  template:
    metadata:
      labels:
        app: {{ .Values.mysql.name }}
    spec:
      containers:
      - name: mysql
        image: "{{ .Values.mysql.image.repository }}:{{ .Values.mysql.image.tag }}"
        ports:
        - containerPort: 3306
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: "{{ .Values.mysql.rootPassword }}"

MySQL Service: This service template creates a Kubernetes Service for MySQL, specifying the necessary ports and selectors.

apiVersion: v1
kind: Service
metadata:
  name: {{ .Values.mysql.serviceName }}
spec:
  selector:
    app: {{ .Values.mysql.name }}
  ports:
    - protocol: TCP
      port: 3306
      targetPort: 3306
  type: ClusterIP

Here is an example segment from a values.yaml that should correspond to the templates:

api:
  name: python-api
  replicaCount: 1
  image:
    repository: mahlomojats/python-api
    tag: latest
  port: 5000
  dbHost: mysql-service
  dbUser: root
  dbPassword: password
  dbDatabase: people_db
  serviceName: python-api-service
  servicePort: 5000

mysql:
  name: mysql
  replicaCount: 1
  image:
    repository: mahlomojats/sample-mysql
    tag: latest
  rootPassword: password
  serviceName: mysql-service

These steps complete the chart for us, and we can no proceed to publish this chart to our repositories for consumption. The chart can be use as part of your CICD pipeline and delivered to the respective compute resources. Below is an overview of what a typical installation would look like.


Installation

1. Clone the Repository

   If the chart is hosted in a Git repository, clone it locally:

   git clone [repository-url]
   cd [repository-name]/myapp


2. Install the Helm Chart

   Use Helm to deploy the chart to your Kubernetes cluster:

  helm install myapp-release ./myapp 

Replace `myapp-release` with a name of your choice for your deployment.

Configuration

The `values.yaml` file contains the configurable parameters and their default values. You can edit this file to change the default configuration or specify the settings directly through the Helm install command using the `--set` flag.

Example Configuration

mysql:
  name: mysql
  replicaCount: 1
  image:
    repository: mysql
    tag: "5.7"
  rootPassword: "securepassword"

api:
  name: python-api
  replicaCount: 1
  image:
    repository: python-api
    tag: "latest"
  port: 5000

 

Customize Configuration at Installation

To customize the configuration at the time of installation, use the `--set` flag:

helm install myapp-release ./myapp \
  --set mysql.rootPassword="newpassword",api.image.tag="v2"

Accessing the Application

After installing the Helm chart, you can forward the ports to access the Python API locally:

kubectl port-forward service/python-api-service 5000:5000

Then, visit `http://localhost:5000/` in your browser to access the API.

Upgrades and Rollbacks

To upgrade your release after modifying the chart or `values.yaml`:

helm upgrade myapp-release ./myapp

 

To rollback an upgrade:

helm rollback myapp-release

 

Uninstallation

To uninstall/delete the deployment:

helm uninstall myapp-release