Hi, in this post I’m going to tell you how to install Argo CD and deploy a simple application stored in GitLab by ArgoCD. This post is based on the YouTube video:

What is Argo CD?

Argo CD is a GitOps tool for Kubernetes. In simple words, GitOps is an approach for deploying your applications and infrastructure when Git is a single place of truth.

Preparing the installation

Before starting an installation you need to fulfill the requirements: – Install kubectl – Prepare access to the Kubernetes cluster

There are two types of installation: multi-tenant and core.

The multi-tenant installation is the most common way to install Argo CD. This type of installation is typically used to service multiple application developer teams.

There are two types of multi-tenant installation: “Non High Availability” and “High Availability” or HA.

Furthermore, each type is divided into standard installation and installation which requires only namespace-level privileges.

The Argo CD Core installation is primarily used to deploy Argo CD in headless mode. All details about this type can be found in the official documentation.

Lastly, you can install Argo CD using Helm or Kustomize.

To conclude I am going to use standard Arg CD installation in HA mode.

The installation process

Let’s get started on our journey. Open the manifest with the HA version.

Then create the directory named “base” and the file “install.yaml” in it. Copy and paste the manifest into it.

argocd
└── base
    └── install.yaml

After that create a “kustomization.yaml” file where set “install.yaml” in the resources section.

argocd
└── base
    ├── install.yaml
    └── kustomization.yaml
$ cat ./base/kustomization.yaml 

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
- install.yaml

In my case I have one environment named test so I will create the directory “overlays” with one directory “test”.

argocd/
├── ...
└── overlays
    └── test

Why so? I tell about this structure in my video about Kustomize. I recommend it for watching to understand this program clearly.

In the directory test create a kustomization.yaml file and the directory named “files”.

argocd/
├── ...
└── overlays
    └── test
        ├── files
        └── kustomization.yaml

if you have installed the Ingress Nginx Controller you can put the Ingress manifest into the files directory.

cat ./overlays/test/files/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argo-cd-ui
  annotations:
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
  ingressClassName: nginx
  rules:
  - host: argocd.company.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: argocd-server
            port:
              name: https

Note that the domain for my Argo CD is “argocd.company.com“.

I added 1 annotation because I had redirect loops when connecting to the Argo CD web interface.

  annotations:
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"

It’s time to make customizations of the Argo CD manifest. Open your kustomization.yaml file.

vi ./overlays/test/kustomization.yaml

Firstly, paste standard strings with apiVersion and Kind.

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

Then specify files in the resources section: ingress.yaml and base directory.

resources:
- ../../base/
- ./files/ingress.yaml

Add namespace field.

namespace: argocd

After that, add the secretGenerator section with three keys: – Username – Password – Url

secretGenerator:
- name: my-repo-secret
  literals:
  - username=
  - password=
  - url=

Finally, add a patches section with one patch. This patch will set one label into the secret created by secretGenerator. Argo CD will use the credentials, configured in this secret, to access your GitLab.

patches:
  - patch: |-
      apiVersion: v1
      kind: Secret
      metadata:
        name: my-repo-secret
        labels:
          argocd.argoproj.io/secret-type: repo-creds      

Next, we need to make credentials for authenticating in the GitLab Repository. First, Create a group where the project will be stored.

Create Group in GitLab Create Group in GitLab 2 Create Group in GitLab 3

Then, create a blank project and put it into the created group. Create new project in GitLab Create new project in GitLab 2 Create new project in GitLab 3

After, Create an Access Token for ArgoCD. Create new access token Create new access token 2 Create new access token 3

Copy and paste your token in the key “password“ in secretGenerator. Copy the token

In the key URL paste the URL of your group. In the key “username” put the name of your token. In my case it is argocd.

secretGenerator:
- name: my-repo-secret
  literals:
  - username=argocd
  - password=xxxxxxxx
  - url=https://gitlab.devops-serge.com/mygroup

We are ready to install Argo CD. Open your terminal.

Create the namespace “argocd” and then Install Argo CD using the command kubectl apply with the K option.

cd overlays/test
kubectl create ns argocd
Kubectl apply –k ./

Check a status of the pods.

kubectl -n argocd get pod

pods

How to login

Let’s go into the web user interface. Add domain argocd.company.com to the /etc/hosts file. ingress /etc/hosts

argo cd main page

If you are not familiar with Ingress, watch my video about MetalLB and Ingress Nginx Controller.

Alternatively, if you don’t have installed Ingress Nginx Controller you can connect to the Argo CD web interface using the kubectl port-forward command.

kubectl port-forward service/argocd-server 9000:443 -n argocd

kubectl port-forward

The admin password is stored in the secret argocd-initial-admin-secret in the key: password. Retrieve it and log in. As you know, secrets are stored in based64 format so we need to decode it.

kubectl -n argocd get secret argocd-initial-admin-secret -o yaml | grep password

echo <BASE64_PASSWORD> | base64 -d

Let’s log in to Argo CD. log in argo cd

In SettingsRepositories, you can find one template created by our secretGenerator. Argo CD Repositories

How to deploy an Argo CD app

We are ready to deploy an application. I’ve prepared a simple helm chart before. How to do your helm charts you can find in one of my videos.

My helm chart consists of a configmap, deployment, and ingress.

.helm/
├── Chart.yaml
├── templates
│   ├── 0-configmap.yaml
│   ├── 1-deployment.yaml
│   └── 2-ingress.yaml
└── values.yaml

The configmap contains the index.html page. Depending on the environment (test, production, or something else), the text color will be different.

cat .helm/templates/0-configmap.yaml 
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: index-html
data:
  index.html: |
    <h1 style='color: {{ pluck .Values.env .Values.color | first | default .Values.color._default }};'>
    Hello world!
    </h1>    

The deployment contains an nginx image for a container to which the configmap will be attached.

cat .helm/templates/1-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Chart.Name }}
spec:
  selector:
    matchLabels:
      app: {{ .Chart.Name }}
  template:
    metadata:
      labels:
        app: {{ .Chart.Name }}
      annotations:
        checksum/config: >-
          {{ include (print $.Template.BasePath "/0-configmap.yaml") . | sha256sum }}          
    spec:
      containers:
      - name: {{ .Chart.Name }}
        image: nginx:alpine3.19
        volumeMounts:
        - name: index-html-volume
          mountPath: /usr/share/nginx/html/index.html
          subPath: index.html
        ports:
          - containerPort: 80
      volumes:
      - name: index-html-volume
        configMap:
          name: index-html

Of course, there is a service for the deployment too.

---
apiVersion: v1
kind: Service
metadata:
  name: {{ .Chart.Name }}
spec:
  selector:
    app: {{ .Chart.Name }}
  ports:
  - name: http
    port: 80
    targetPort: 80
    protocol: TCP

Host in the ingress depends on the environment Values.env too.

---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: {{ .Chart.Name }}
spec:
  ingressClassName: nginx
  rules:
  - host: {{ pluck .Values.env .Values.domain | first | default .Values.domain._default }}
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: {{ .Chart.Name }}
            port:
              number: 80

If the helm chart is deployed in the test environment the domain will be my-program-test.company.com

cat .helm/values.yaml

Below you can see the color of the text that will be used in the “test” environment.

domain:
  test: my-program-test.company.com
color:
  test: green

You can download this helm chart from my git repository.

Put the helm chart into the created project in GitLab. Push an existing folder

The helm chart is uploaded. uploaded helm chart

The next step is to configure Argo CD for monitoring this repository and deploy the helm chart to the cluster. To do it in ArgoCD there is an object called Application.

On the screen, you can see an example of the Application. Argo CD Application

In my case, I want to deploy an application that will synchronize other applications stored in the test-apps directory. I’ve prepared this application before.

cat << EOF | tee 1> /dev/null argocd-app/argocd-test.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: argocd-test
  namespace: argocd
spec:
  project: default
  source:
    repoURL: ''
    path: test-apps
    targetRevision: main
  destination:
    server: 'https://kubernetes.default.svc'
    namespace: argocd
  syncPolicy:
    automated:
      selfHeal: true

Let’s create a repository for these apps. creating the repo for Argo CD apps

Then push the application to the repository. Use the “Push an existing folder” section. the repo for Argo CD apps

Open the repository and copy the link from the Clone with HTTPS section. Paste it in the repoURL field.

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: argocd-test
  namespace: argocd
spec:
  source:
    repoURL: 'https://gitlab.devops-serge.com/mygroup/argocd-app.git'

Clone with HTTPS

Push your changes to the repository.

After that apply the manifest with the application using kubectl.

cd argocd-app
kubectl apply -f argocd-test.yaml

Check the application in the ArgoCD user interface. Argo CD app

There is an error. I have not created test-app path yet. Argo CD App Error

Create the directory and push it into the remote repository. Then recheck the application.

mkdir argocd-app/test-apps
argocd-app/
└── test-apps

Refresh the application. The application was synced. The application was synced

Everything looks good.

Finally, deploy the helm chart using ArgoCD. To do it you need to create an application again. I’ve done it before. You can see it below.

cat << EOF | tee 1> /dev/null argocd-app/test-apps/my-program.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-program-test
  namespace: argocd
spec:
  project: default
  source:
    targetRevision: main
    repoURL: 'https://gitlab.devops-serge.com/mygroup/myproject.git'
    path: .helm
    helm:
      releaseName: my-program-test
      valueFiles:
        - values.yaml
      values: |
        env: test
  destination:
    server: 'https://kubernetes.default.svc'
    namespace: my-program-test
  syncPolicy:
    automated:
      selfHeal: true
    syncOptions:
    - CreateNamespace=true
EOF

Push the application to the remote repository.

git add .
git commit -m 'add repoURL'
git push

You can see below that our main application deployed the my-program application in the cluster. main app deployed the my-program app

Let’s look at the my-program application. my-program app

Let’s look at the main page of my-program. I need to add the domain name in my /etc/hosts file again. ingress /etc/hosts

You can see that everything works smoothly. the main page of my program

That’s it. We’ve installed Argo CD and deployed the simple application. See you!