Kubernetes Cluster Requirements #
Create Namespace for the Flask-App #
Create a namespace for the deployment of the Python Flask web application, the same namespace must be defined in the Argo CD application manifest:
# Create a namespace
kubectl create namespace flask-app
GitLab Host Keys #
Scan GitLab Host Keys #
From the node where the Argo CLI is installed (or any other host that can resolve the GitLab DNS name), scan the host keys of GitLab:
# List the GitLab host keys
ssh-keyscan gitlab.jklug.work
Shell output:
# gitlab.jklug.work:22 SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.7
gitlab.jklug.work ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPUxIo1glUPlmYJDbAOvHlRd/qjxdIEJCtBlcFLCMXECbRdp9IN/qePZdFtOnMWWVNvi8qy+7V8XbIFbzHoYwcg=
# gitlab.jklug.work:22 SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.7
gitlab.jklug.work ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDHAQj15hmfv3OwTY3RAPwx1UlZ8p4qgtAHiZ9hngfJTSScO1kf40oL3Ek5NVKSGYZQ4w6ozBFHKO3l6tHn8nPeD7mUk/nW2U5w9yYpcRyFknn/u/Z0QreHAkI8fg6LI4n+2QYFF1rZbIemtCG33FozwrWKJ+/UsJYLnuQ2fenjcvkwPYx7NKV07RtQ3xYvkFVdWQGFJK8pLG9UcsanwZbH2nVPbv3i9KKI9xxWmJDh9JOoLhG6JipNN4Q4CoodfR9k9A2PY88dEykMInSGzFddOqbHLyISO8H1oJrofPzovPR07f+bDBK6iGIqRSW00k6mM0RFkPPo9tulLJ87DgB84jVrtYGp71wmV9PQ8jPB1uaDx5JtRNc0G+IWlIzTy8hFW9djELdTdQmfxeaCceyn1AmuXhpwZin64WTqztXj29s1olZ0+Uchh2FGpEjvlVqveeMmgAQkQezidqVHKKwinW1zdeSaBaZkS0JpLtxNpA86vBnhtYE8Z4CaQAvoQXU=
# gitlab.jklug.work:22 SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.7
gitlab.jklug.work ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH6GrjO8VqbiFMwtOfaEuKd3bV2vb7jH4r5Xl9PW1TFY
# gitlab.jklug.work:22 SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.7
# gitlab.jklug.work:22 SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.7
Add GitLab Host Keys to Argo CD #
Open the Argo CD webinterface an add the GitLab host keys:
-
Go to: “Settings” > “Repository certificates and known hosts”
-
Click “ADD SSH KNOWN HOSTS”
-
Paste the GitLab SSH keys in the text box, one entry per line, it should look like this:
gitlab.jklug.work ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPUxIo1glUPlmYJDbAOvHlRd/qjxdIEJCtBlcFLCMXECbRdp9IN/qePZdFtOnMWWVNvi8qy+7V8XbIFbzHoYwcg=
gitlab.jklug.work ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDHAQj15hmfv3OwTY3RAPwx1UlZ8p4qgtAHiZ9hngfJTSScO1kf40oL3Ek5NVKSGYZQ4w6ozBFHKO3l6tHn8nPeD7mUk/nW2U5w9yYpcRyFknn/u/Z0QreHAkI8fg6LI4n+2QYFF1rZbIemtCG33FozwrWKJ+/UsJYLnuQ2fenjcvkwPYx7NKV07RtQ3xYvkFVdWQGFJK8pLG9UcsanwZbH2nVPbv3i9KKI9xxWmJDh9JOoLhG6JipNN4Q4CoodfR9k9A2PY88dEykMInSGzFddOqbHLyISO8H1oJrofPzovPR07f+bDBK6iGIqRSW00k6mM0RFkPPo9tulLJ87DgB84jVrtYGp71wmV9PQ8jPB1uaDx5JtRNc0G+IWlIzTy8hFW9djELdTdQmfxeaCceyn1AmuXhpwZin64WTqztXj29s1olZ0+Uchh2FGpEjvlVqveeMmgAQkQezidqVHKKwinW1zdeSaBaZkS0JpLtxNpA86vBnhtYE8Z4CaQAvoQXU=
gitlab.jklug.work ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH6GrjO8VqbiFMwtOfaEuKd3bV2vb7jH4r5Xl9PW1TFY
- Click “CREATE” to save the entry
GitLab Deploy Key: For Argo CD #
Create SSH Key Pair #
Create a SSH key pair, on the Argo CD CLI host and add the public key to GitLab:
# Create SSH RSA key pair: 4096 bit
ssh-keygen -t rsa -b 4096 -f argocd_repo_key
# Copy the public SSH key
cat argocd_repo_key.pub
Add Public SSH Key to GitLab Repository #
Add the public SSH key to the GitLab repository with the Helm chart:
-
Go to: (Project) “Settings” > “Repository”
-
Expand the “Deploy keys” section
-
Click “Add new key”
-
Paste the value of the
argocd_repo_key.pub
public SSH key -
Define a title like “argocd_repo_key”
-
Click “Add key”
GitLab Project Access Token #
Create Project Access Token #
Create a “Project Access Token” in the flask-app-code
project used by Argo CD to access the GitLab Registry of the project:
-
Go to: (Project) “Settings” > “Access Tokens”
-
Click “Add new token”
-
Define a token name like
registry-token
-
Define the scope of the token: “read_registry” Grants read-only access to container registry images on private projects.
-
Click “Create project access token”
-
Copy the project access token, it should look like this:
glpat-Fkm7_j_1Bo4158eyETjV
Copy Project Token User #
For each project token, a bot user is created. Copy the name of the user:
-
Go to: (Project) “Manage” > “Members”
-
Copy the
registry-token
username from the members section, it should looks like this:
# Copy project member "registry-token"
project_29_bot_39e3a29271544817376626f4e17b4d50
Create GitLab Registry Secret #
# Create a secret with the GitLab access token
kubectl create secret docker-registry gitlab-registry-secret \
--docker-server=gitlab-registry.jklug.work \
--docker-username=project_29_bot_39e3a29271544817376626f4e17b4d50 \
--docker-password=glpat-Fkm7_j_1Bo4158eyETjV \
--docker-email=juergen@jklug.work \
--namespace=flask-app
# Shell output:
secret/gitlab-registry-secret created
Verify the Secret #
# List secret details
kubectl get secret gitlab-registry-secret -o yaml -n flask-app
# Shell output:
apiVersion: v1
data:
.dockerconfigjson: eyJhdXRocyI6eyJnaXRsYWItcmVnaXN0cnkuamtsdWcud29yayI6eyJ1c2VybmFtZSI6InByb2plY3RfMjlfYm90XzBmODgwY2FjN2YwYjE0YjU4ZTFhMjk4MzM3NzRlYjQxIiwicGFzc3dvcmQiOiJnbHBhdC1BS1NGeENSWkJtY19FTUpabXcyVyIsImVtYWlsIjoianVlcmdlbkBqa2x1Zy53b3JrIiwiYXV0aCI6ImNISnZhbVZqZEY4eU9WOWliM1JmTUdZNE9EQmpZV00zWmpCaU1UUmlOVGhsTVdFeU9UZ3pNemMzTkdWaU5ERTZaMnh3WVhRdFFVdFRSbmhEVWxwQ2JXTmZSVTFLV20xM01sYz0ifX19
kind: Secret
metadata:
creationTimestamp: "2024-12-06T11:39:23Z"
name: gitlab-registry-secret
namespace: flask-app
resourceVersion: "13851"
uid: 598f2c8b-5325-4f49-a448-1290efffa3ba
type: kubernetes.io/dockerconfigjson
Argo CD Setup #
Connect GitLab Repository #
Add the GitLab repository to Argo CD, this allows Argo CD to access and manage the repository using the specified SSH private key:
# Connect a GitLab repository via SSH: Define path to private SSH key "argocd_repo_key"
argocd repo add git@gitlab.jklug.work:python/flask-app-helm.git --ssh-private-key-path argocd_repo_key
# Shell output:
Repository 'git@gitlab.jklug.work:python/flask-app-helm.git' added
The GitLab repository should now be availble in the Argo CD webinterface under: “Settings” > “Repositories”
Verify GitLab Repository #
# List connected GitLab repositories
argocd repo list
# Shell output:
TYPE NAME REPO INSECURE OCI LFS CREDS STATUS MESSAGE PROJECT
git git@gitlab.jklug.work:python/flask-app-helm.git false false false false Successful
Create an Argo CD Application #
Manifest Version #
Create an Argo CD application named flask-web-app
that points to the Kubernetes manifests in the specified GitLab repository and deploys them to the default namespace of the Kubernetes cluster.
# Create a manifest for the application
vi flask-web-app.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: flask-web-app
namespace: argocd
spec:
project: default
source:
repoURL: git@gitlab.jklug.work:python/flask-app-helm.git
targetRevision: main
path: helm-chart
destination:
server: https://kubernetes.default.svc
namespace: flask-app
syncPolicy:
automated:
prune: true
selfHeal: true
# Apply the application manifest
kubectl apply -f flask-web-app.yaml
# Shell output:
application.argoproj.io/flask-web-app created
CLI Version #
# Create Argi CD application
argocd app create flask-web-app \
--project default \
--repo git@gitlab.jklug.work:python/flask-app-helm.git \
--revision main \
--path helm-chart \
--dest-server https://kubernetes.default.svc \
--dest-namespace flask-app \
--sync-policy automated \
--auto-prune \
--self-heal
# Shell output:
application 'flask-web-app' created
Explanation #
-
flask-web-app
Name of the application. -
--project default
Specifies the built-in project that exists in every ArgoCD installation. -
--repo:
The Git repository URL. -
--revision main:
The branch or commit to track. -
--path
The sub-path within the repository containing the manifest/chart. -
--dest-server https://kubernetes.default.svc
The destination cluster. -
--dest-namespace
The namespace where the application will be deployed. -
--sync-policy automated
Enables automated synchronization. -
--auto-prune
Ensures resources that are removed from the Git repository are pruned. -
--self-heal
ArgoCD automatically corrects any differences by applying the desired state from the Git repository to the cluster.
Verify the Argo CD Application #
# Verify Argo CD application
argocd app get flask-web-app
# Shell output:
Name: argocd/flask-web-app
Project: default
Server: https://kubernetes.default.svc
Namespace: flask-app
URL: https://argocd.jklug.work/applications/flask-web-app
Source:
- Repo: git@gitlab.jklug.work:python/flask-app-helm.git
Target: main
Path: helm-chart
SyncWindow: Sync Allowed
Sync Policy: Automated (Prune)
Sync Status: Synced to main (1f90590)
Health Status: Progressing
GROUP KIND NAMESPACE NAME STATUS HEALTH HOOK MESSAGE
Service flask-app flask-app Synced Healthy service/flask-app created
apps Deployment flask-app flask-app Synced Progressing deployment.apps/flask-app created
Very Flask Web App Deployment #
# List resources in the "flask-app" namespace
kubectl get all -n flask-app
# Shell output:
NAME READY STATUS RESTARTS AGE
pod/flask-app-5b5946578f-lpgqf 1/1 Running 0 17s
pod/flask-app-5b5946578f-p7rvx 1/1 Running 0 17s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/flask-app ClusterIP 10.108.139.47 <none> 8080/TCP 17s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/flask-app 2/2 2 2 17s
NAME DESIRED CURRENT READY AGE
replicaset.apps/flask-app-5b5946578f 2 2 2 17s
# Create a port forwarding
kubectl port-forward service/flask-app 8080:8080 -n flask-app
# Curl the Flask application (in a new shell)
curl http://localhost:8080
# Shell output:
Hi there from Python Flask application
Manually Trigger Synchronization #
# Manually trigger the synchronization of the application with the Git repository
app sync flask-web-app --prunene
# Shell output:
TIMESTAMP GROUP KIND NAMESPACE NAME STATUS HEALTH HOOK MESSAGE
2024-12-07T17:35:31+00:00 Service flask-app flask-app Synced Healthy
2024-12-07T17:35:31+00:00 apps Deployment flask-app flask-app Synced Healthy
2024-12-07T17:35:32+00:00 Service flask-app flask-app Synced Healthy service/flask-app unchanged
2024-12-07T17:35:32+00:00 apps Deployment flask-app flask-app Synced Healthy deployment.apps/flask-app configured
2024-12-07T17:35:32+00:00 apps Deployment flask-app flask-app OutOfSync Progressing deployment.apps/flask-app configured
Name: argocd/flask-web-app
Project: default
Server: https://kubernetes.default.svc
Namespace: flask-app
URL: https://argocd.jklug.work/applications/flask-web-app
Source:
- Repo: git@gitlab.jklug.work:python/flask-app-helm.git
Target: main
Path: helm-chart
SyncWindow: Sync Allowed
Sync Policy: Automated (Prune)
Sync Status: Synced to main (c65793d)
Health Status: Progressing
Operation: Sync
Sync Revision: c65793dd73e4951cf680c1a6c3d3e9adb06a0c0f
Phase: Succeeded
Start: 2024-12-07 17:35:31 +0000 UTC
Finished: 2024-12-07 17:35:32 +0000 UTC
Duration: 1s
Message: successfully synced (all tasks run)
GROUP KIND NAMESPACE NAME STATUS HEALTH HOOK MESSAGE
Service flask-app flask-app Synced Healthy service/flask-app unchanged
apps Deployment flask-app flask-app Synced Progressing deployment.apps/flask-app configured
Delete Argo CD Application #
# Delete the Argo CD application
argocd app delete flask-web-app