Continuous Deployments of Kubernetes Applications using Argo CD GitOps & Helm Charts.

Introduction

In this article, we will learn how to easily set up Argo CD as an app of apps with Helm, deploy applications with Argo CD and subsequently manage these applications.

Outline

  • Argo CD? Helm? What are these things?
  • Now we know them, what do we want to do with them?
  • Creating a Kubernetes Cluster (on GKE)
  • Deploy Argo CD to our Kubernetes cluster
  • Connect ArgoCD to our Git repository
  • Setup Argo CD as an app of apps

Argo CD? Helm? What are these things?

Argo CD

Argo CD is a declarative, GitOps continuous delivery tool for Kubernetes.

We need Argo CD because application definitions, configurations, and environments should be declarative and version controlled. Application deployment and lifecycle management should be automated, auditable, and easy to understand.

Helm

Helm helps you manage Kubernetes applications — Helm Charts help you define, install, and upgrade even the most complex Kubernetes application.

Charts are easy to create, version, share, and publish. In this tutorial, we are mostly re-using existing charts (including one of ours). To learn how to build and publish your own charts to GitHub pages, you can check out this article.

Now we know them, what do we want to do with them?

We want to set up Argo CD on our Kubernetes cluster, and then use it to deploy other applications following the steps below:

  • Create a Kubernetes cluster or use an existing one (we would use GKE for this tutorial, others work just fine.)
  • Deploy Argo CD to our Kubernetes cluster.
  • Connect ArgoCD to our Git repository
  • Setup Argo CD as an app of apps

Creating a Kubernetes Cluster (on GKE)

If you are using the Google Cloud Platform (GCP), you can follow the instructions below to set up your Kubernetes cluster, otherwise, check out how to for AWS or Azure.

Login

                $ gcloud auth login
            

Configure project info

                $ gcloud config set project <PROJECT_ID>
$ gcloud config set compute/region <COMPUTE_REGION>
            

Create a cluster (autopilot in this case)

                $ gcloud container clusters create-auto demo-cluster \
    --region us-west1 \
    --project=dev-workloads
            

The cluster name here is ‘demo-cluster’, in the ‘us-west1' region, and the project is ‘dev-workloads.

You can log in to your cloud console environment to see the progress of the deployment.

1_c-t9cLCVBMHbavHfWIJ3aw.png

Creating a Kubernetes cluster on GKE using CLI

1__l2u9d9PaemiUDsrckpKCg.png

Created cluster

Note: The cluster can also be created using the cloud environment’s UI (but where’s the fun in that?).

Deploy Argo CD to our Kubernetes cluster

Connect to demo-cluster

                $ gcloud container clusters get-credentials demo-cluster --region us-west1 --project dev-workloads
            
1_qyU9oIPQtasxQ8mbei3TZA.png

Connect to the cluster

Install ArgoCD using its Helm Chart

Typically, we would install ArgoCD by applying its manifest and following other instructions here, but instead, we’ll use Helm to install ArgoCD because we love Helm and it makes our lives super easier (check out why in the Helm section above).

Add Argo CD Helm repository

                $ helm repo add argo-cd https://argoproj.github.io/argo-helm
            
1_A5CJ_vVUBvnCcztkzaHPLA.png

Add Argo CD Helm repository

Install Argo CD

                $ helm install argocd argo-cd/argo-cd
            
1_LDbkhiz1vAqCgczFhoCQJw.png

Install Argo CD

You can add the ‘— create-namespace’ flag and ‘-n <namespace>’ to install Argo CD in a new namespace or ‘-n <namespace>’ to do so in an existing namespace.

Confirm installation

                $ kubectl get deployment
$ kubectl get services
            
1_6EkiddVSpVPzI0wyw8ZBNA.png

Confirm ArgoCD installation

Expose the service

By default, the Argo CD API server is not exposed with an external IP. To access the API server, we can use change our server service to a load balancer, use an Ingress, or simply port forward. They all have their strengths and weaknesses (you can check them out).In this tutorial, we will be changing our service to a load balancer.

                $ kubectl patch svc argocd-server -p '{"spec": {"type": "LoadBalancer"}}'
            
1_97MJ-ucKt25ovTinG1JsaA.png

Change argocd-server to a load balancer

Now we can visit the external IP to see ArgoCD’s pretty landing page.

1_355e-p2mdikWXBMYjwuFJA.png

Argo CD UI login page

Login to Argo CD

Fetch ArgoCD’s default password and login (username is ‘admin’).

                $ kubectl get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d; echo
            
1_b8PscGodjJo66eKGi5Qxcw.png

Application page

Connect ArgoCD to our Git repository

We’ll set up a git repository on Github and point our Argo CD configuration to a directory/folder in this repo. The orientation here is that, for the sake of maintainability, we can add manifests to this directory and Argo CD will automatically deploy these apps.

Picture it this way, we add a root application resource, and every other app is a child of this app. The root application will generate manifests for other applications, ArgoCD will watch this application and synchronize any application generated by it (Don’t think about it too much).

This way, we need to only add one application manually, and yes, that’s the root application.

Setup Git repository

In this tutorial, we will use an existing repository but you can create a new one if you need to. What is important is having a folder for all your Argo CD manifests.

1_SfpFGOajFRDulTOblSobFA.png

Argo CD directory (the empty YAML is not important)

Connect ArgoCD to our git repo

1_Rfa4Nvl2btdSvsEBZczlDA.png

Open the repository management menu and click ‘Repositories’

1_CS_hTVJX6_q1ivM6YYexVA.png

Connect repo using a method convenient for you (we use SSH)

1_PBtjf9imr4QKx164VGZIxw.png

Configure repo connection info

To get your SSH key, use:

                cat ~/.ssh/id_rsa
            

Find more info on SSH here.

1_kP0Iwo8dW0nokBjphi5GHA.png

Successfully connected repo

Setup Argo CD as an app of apps

Create the root application

1_2wJ7T7fteNS1qKJskct86w.png

App creation page

1_1CQpDR74X9JjCJV3sLfb7Q.png

App configuration

  • The application name is custom to you. We use root here because, well, every other app will grow from it.
  • The project name is your Argo CD project name. By default, it’s ‘default’. Other projects can be customized to control activities.
  • Sync policy determines if you want this app to synchronize automatically or manually from its source. It’s set to ‘Manual’ by default.
  • The ‘prune resources’ option is checked when we want Argo to delete resources when they are no longer defined on Git. All options are unchecked by default.
  • The ‘self heal’ option is checked if we want Argo to force the state defined in Git to the cluster even when the cluster is different.
  • The ‘set deletion finalizer’ option is checked when we want to add a deletion finalizer to this app. What this finalizer does is delete both the app and resources on the cluster when it is no longer defined on Git.

1_BCVqwMCDS6tgz7NnPEzVqA.png

App configuration

  • The repository URL is the git repository we previously configured.
  • Revision can be branches or tags. We can set up different apps for different branches or tags based on our pain point if we wish to.
  • The path is where we want Argo to watch for manifest(s). Since we created a folder for it in our case, that is where we will point to.

1_8OItX_GGG4GFAFZpMihrdQ.png

App configuration

  • The cluster URL is our destination cluster (usually default).
  • The namespace is the destination namespace we want to use.

1__JdfLmX7mPW_hNCCcsSPJg.png

New application

Deploy other applications using their Helm charts

Traditionally, in Argo CD, we can deploy applications with configurations in manifests that are the same as those we run ‘kubectl apply’ on. However, in our case, we use Helm charts (because it’s easier).

This is usually a 3 step process:

  • Find the Helm chart for the app — we can find manifests in chart repositories eg. Bitnami, Artifact hub, and many others (just google it).
  • Prepare manifest in our ‘ArgoCD-Apps’ folder.
  • Sync

The steps are the same for all apps we want to deploy, except there are special requirements sometimes.

Example: Deploying Nginx

  • Find chart

A standard Nginx chart can be found here.

  • Prepare manifest

                apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: nginx
  namespace: default
  finalizers:
    - resources-finalizer.argocd.argoproj.io
spec:
  destination:
    namespace: nginx
    server: https://kubernetes.default.svc
  project: default
  source:
    chart: nginx-ingress
    repoURL: https://helm.nginx.com/stable
    targetRevision: 0.14.0
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
    - CreateNamespace=true
            
1_bSTED3wnDvELMUDImeakag.png

Nginx app configuration

Most of these properties are common to Kubernetes deployment manifests.

Some pointers:

  • The namespace in the metadata (line 5) is used within Argo while the namespace in the spec (line 10) is used in the Kubernetes cluster.
  • A finalizer (line 6) is used so that if we remove this app from Git, it is not only deleted on Argo but its resources are also deleted on the Kubernetes cluster.
  • The source info (line 13) points to where our helm chart is located eg. in this case, our Nginx chart is located in(repoURL) https://helm.nginx.com/stable, where its name is ‘nginx-ingress’ and the latest version when this article was written is ‘0.14.0'. Sometimes the version is a dynamic value eg. HEAD.

1_EZdq33ac22WgeKLUw1Wb0w.png

Source info from Nginx Helm chart

  • Sync

Our synchronization is done automatically since we set it that way.

1_ali8k_aFbXdUOrpKDi4Fwg.png

Nginx deployed after adding manifest

Click the ‘nginx’ app

1_8f-XHC7gWUA-angH0A8m9Q.png

Nginx deployed with all its resources

We can see traffic (network) information using the network view

1_Vy2ZOXL5lt1nrRV1n0fB5Q.png

Nginx network view

We can visit the Load Balancer IP address

1_qF4EfktQGQR3YoQSKSqfyg.png

Nginx Ingress

Navigate back to applications and click the root application

1_8GVH5kNleTeGm51JvLQ_Kw.png

root application

From the image above, we can see that the ‘nginx’ application is represented as a child of the ‘root’ application. This is a basic representation of the ‘app of apps’ concept.

From here on out, your deployment process is basically on autopilot (on some level). All we’ll keep doing is add manifests and maybe customize them if we need to. Let’s add Grafana and Prometheus apps.

Example 2: Deploying Grafana

  • Find chart

  • Prepare manifest

                apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: grafana
  namespace: default
  finalizers:
    - resources-finalizer.argocd.argoproj.io
spec:
  destination:
    namespace: monitoring
    server: https://kubernetes.default.svc
  project: default
  source:
    chart: grafana
    repoURL: https://grafana.github.io/helm-charts
    targetRevision: 6.32.11
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
    - CreateNamespace=true
            

  • Sync

1_xAHPt1VJ0Oq2ENfTJR8x7Q.png

Grafana app created

1_WBbzjdZ2-3AkPPWeCePrgw.png

Grafana resources created

1_gNzEfAsZBtaV34LzY8dMpw.png

Grafana created as a child of the root application

That’s it. Let’s do the same for Prometheus (you can try to do this one yourself before following the instructions below).

Example 3: Deploying Prometheus

  • Find chart

  • Prepare manifest

                apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: prometheus
  namespace: default
  finalizers:
    - resources-finalizer.argocd.argoproj.io
spec:
  destination:
    namespace: monitoring
    server: https://kubernetes.default.svc
  project: default
  source:
    chart: prometheus
    repoURL: https://prometheus-community.github.io/helm-charts/
    targetRevision: 15.12.0
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
    - CreateNamespace=true
            

  • Sync

1_Y40vy5TsmZ2GBlIny2O4eQ.png

Prometheus app created

1_iDAzTk2BzCcB4EoBErnkIg.png

Prometheus resources created

The error here is because of a GKE autopilot permission we don’t have, don’t bother.

1_e4odMapw7kp1YWFy4wrPfQ.png

Prometheus created as a child of the root application

In this article, we were able to learn:

  • How to set up Argo CD on a Kubernetes cluster using Helm.
  • Basic configurations on Argo CD.
  • How to connect Argo CD to our Github repo.
  • How to use Argo CD to deploy other applications quickly and in a less error-prone way.

TBH, one way or another, something will work. — Timothy Olaleke

Suggested things to explore:

  • Customizing resource properties the GitOps way (by customizing the manifests). Eg. adding a load balancer to our Grafana app so we can access it externally.
  • Other deployment methods eg. tag-based deployments.
  • Using other ‘Kinds’ of deployments eg. ‘Ingresses’.

References


Pawfives by
Pawfives by:

Only registered users can post comments. Please, login or signup.

Start blogging about your favorite technologies and get more readers

Join other developers and claim your FAUN account now!

Avatar

Merrygold Odey

DevOps Engineer

@m3rryqold
Building solutions for the next generation | Software Engr | DevOps Engineer | Cooking @hostspaceng 😁 | Blockend Engineer Supreme 😁
Stats
21

Influence

755

Total Hits

1

Posts