Deploying a Flask Python Project to Kubernetes with ArgoCD

Hakan Bayraktar
6 min readSep 26, 2024

--

In this guide, I will walk you through how to containerize your Flask application using Docker, push it to Docker Hub, and deploy it to your Kubernetes cluster with ArgoCD. This step-by-step tutorial covers the key concepts of modern CI/CD and Kubernetes deployments.

Project Structure

For this Flask application, your project files should be organized as follows:

  • Dockerfile: Builds your Flask app into a Docker image.
  • app.py: Contains the source code of your Flask app.
  • requirements.txt: Lists the dependencies for your Flask app.
  • templates/index.html: Contains the front-end part of your Flask app.
  • application.yaml: Kubernetes manifest for deploying the app.
  • manifest/deployment.yaml: Contains Kubernetes deployment configuration.
  • .github/workflows/docker-build.yml: Workflow for CI/CD with GitHub Actions.

Required Tools

  • Docker Hub account
  • GitHub repository
  • ArgoCD installation
  • Kubernetes cluster
  • kubectl CLI tool

You will also need GitHub Secrets for:

  • DOCKER_HUB_USERNAME: Your Docker Hub username.
  • DOCKER_HUB_ACCESS_TOKEN: Your Docker Hub access token.
  • PAT: Your GitHub Personal Access Token.
  • EMAIL_ADDRESS: Your GitHub email address.

How to Create a Docker Hub Access Token

To push Docker images to Docker Hub, you need an Access Token for authentication. Follow these steps:

  1. Go to Docker Hub and log in.
  2. Click on your username in the top-right corner and select Account Settings.
  3. On the left-hand menu, click Security.
  4. Under Access Tokens, click New Access Token.
  5. Name your token (e.g., github-action-token), and select Read/Write as the scope.
  6. Click Generate, and copy the token.

Make sure to save this token securely. You will use it in your GitHub Actions secrets as DOCKER_HUB_ACCESS_TOKEN

How to Create a GitHub Personal Access Token (PAT)

To authenticate and push updates to your GitHub repository:

  1. Log in to GitHub and go to Settings.
  2. Click Developer settings from the left menu.
  3. Under Personal access tokens, click Tokens (classic) and then Generate new token.
  4. Name the token (e.g., github-actions), and select these scopes:
  • repo: Full control of private repositories (if your repo is private).
  • workflow: Update GitHub Actions workflows.

5. Click Generate token, then copy and store it securely. You’ll use it as PAT in your GitHub Actions secrets.

Step 1: Build Flask App with Dockerfile

We need to containerize the Flask application. Below is the Dockerfile:

FROM python:3.9
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app.py .
COPY templates/ ./templates/
EXPOSE 5000
CMD ["python", "app.py"]

This Dockerfile sets up the required dependencies and runs your Flask app on port 5000 inside a Docker container.

requirements.txt:

blinker==1.6.2
click==8.1.6
colorama==0.4.6
Flask==2.3.2
importlib-metadata==6.8.0
itsdangerous==2.1.2
Jinja2==3.1.2
MarkupSafe==2.1.3
Werkzeug==2.3.6
zipp==3.16.2

app.py: The main Python file of your Flask app:

from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def hello():
greeting_message = "Hello from ArgoCD"
return render_template('index.html', message=greeting_message)
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=5000)

This app will simply display a “Hello from ArgoCD” message to users.

templates/index.html: The HTML template for your Flask app:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
<title>ArgoCD App</title>
</head>
<body>
<div class="container mt-5">
<h1 class="text-center">Welcome to the ArgoCD App!</h1>
<div class="alert alert-info text-center" role="alert">
{{ message }}
</div>
<footer class="text-center mt-4">
<p>© 2024 ArgoCD App</p>
</footer>
</div>
</body>
</html>

Step 2: Define Kubernetes Manifest

Once you have the Docker image, we define a Kubernetes manifest to deploy the app. Below is manifest/deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
name: flaskapp
labels:
app: flask
spec:
replicas: 1
selector:
matchLabels:
app: flask
template:
metadata:
labels:
app: flask
spec:
containers:
- name: flaskapp
image: username/argocd-python:v1.0
ports:
- containerPort: 5000
---
apiVersion: v1
kind: Service
metadata:
name: flaskservice
spec:
selector:
app: flask
ports:
- port: 80
targetPort: 5000
type: LoadBalancer

In this Kubernetes manifest:

  • Deployment defines how your Flask app will run on Kubernetes, specifying the image and container port.
  • Service exposes the app via a LoadBalancer, routing traffic from port 80 to port 5000.

ArgoCD Application Sync

Once you have defined your Kubernetes manifest (manifest/deployment.yaml), ArgoCD will automatically pick up changes and deploy them to your cluster. There is no need to manually apply the manifests using kubectl.

Step 3: Automate CI/CD with GitHub Actions

Next, let’s automate the process of building and pushing the Docker image to Docker Hub using GitHub Actions.

Create a GitHub Actions file at .github/workflows/docker-build.yml:

name: Build and Deploy to Kubernetes

on:
push:
branches:
- main
paths-ignore:
- 'manifest/deployment.yaml'

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v2
with:
token: ${{ secrets.PAT }}

- name: Log in to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}

- name: Build and push Docker image
run: |
docker build -t ${{ secrets.DOCKER_HUB_USERNAME }}/flask-app:${{ github.run_number }} .
docker push ${{ secrets.DOCKER_HUB_USERNAME }}/flask-app:${{ github.run_number }}

- name: Update Kubernetes manifest
run: |
sed -i 's#image: .*#image: ${{ secrets.DOCKER_HUB_USERNAME }}/flask-app:${{ github.run_number }}#g' manifest/deployment.yaml
git config --local user.email "${{ secrets.EMAIL_ADDRESS }}"
git config --local user.name "${{ github.actor }}"

git add manifest/deployment.yaml
git commit -m "Update image version to workflow #${{ github.run_number }}"
git push https://x-access-token:${{ secrets.PAT }}@github.com/${{ github.actor }}/argocd-python.git main

With this configuration, every time code is pushed to the main branch, it builds the Docker image and pushes it to Docker Hub.

Step 4: Deploy with ArgoCD

ArgoCD is a powerful tool for continuous delivery on Kubernetes. It automatically syncs your Git repository to a Kubernetes cluster.

First, install ArgoCD in your Kubernetes cluster:

kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/v2.1.3/manifests/install.yaml

Once ArgoCD is installed, you need to expose its dashboard externally using a LoadBalancer service:

argocd-service.yaml:

apiVersion: v1
kind: Service
metadata:
name: argocd-server
namespace: argocd
spec:
type: LoadBalancer
selector:
app.kubernetes.io/name: argocd-server
ports:
- port: 80
targetPort: 8080
protocol: TCP
name: http
- port: 443
targetPort: 8080
protocol: TCP
name: https

Apply this service to expose the ArgoCD dashboard:

kubectl apply -f argocd-service.yaml

You can retrieve the LoadBalancer IP with:

kubectl get svc -n argocd

Access the ArgoCD dashboard by entering this IP into your browser. Use the default admin username and retrieve the password with:

kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 --decode

Step 5: Sync Application with ArgoCD

For ArgoCD to automatically sync and deploy your application, define an application manifest like this:

application.yaml:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: flask-app
namespace: argocd
spec:
destination:
namespace: default
server: https://kubernetes.default.svc
source:
path: manifest
repoURL: 'https://github.com/username/argocd-python'
targetRevision: main
project: default
syncPolicy:
automated:
prune: true
selfHeal: true

Apply the manifest to register the application with ArgoCD:

kubectl apply -f application.yaml

Now ArgoCD will automatically sync and deploy your Flask app to Kubernetes. Any changes pushed to your GitHub repository will trigger ArgoCD to update your Kubernetes deployment.

Conclusion

In this tutorial, you’ve learned how to containerize a Flask app, automate the CI/CD process using GitHub Actions, and deploy the app to a Kubernetes cluster using ArgoCD. This workflow is a practical demonstration of continuous delivery and modern deployment techniques. You can find the complete project on GitHub.

--

--

No responses yet