Introduction

I first encountered Argo on the Civo community Slack, when it was mentioned as something exciting by Alex Ellis. After reading a little about the project, I decided to try it out, and document my experience. In the following guide, we will deploy Argo to manage GitOps in Kubernetes for two different Git repository-based projects.

What is Argo CD?

According to the official site:

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

Argo CD follows the GitOps pattern of using Git repositories as the source of truth for defining the desired application state, and manages the Kubernetes deployment of these applications.

Why Argo CD?

Again, quoting the official site:

Application definitions, configurations, and environments should be declarative and version controlled. Application deployment and lifecycle management should be automated, auditable, and easy to understand.

An Argo deployment of an application can follow a branch of a git repository, or be pinned to a particular release. Configuration of the app will be on the basis of what is defined in the repository, and that repository only.

Deployment

 Pre-Requisites

To follow along with this guide, you will have to have a Civo account with access to the managed Kubernetes service. If you do not yet have an account or are not in the #KUBE100 beta, you can register your interest here and benefit from free credit.

You will also need to have kubectl installed to manage namespaces and secrets on the cluster.

Creating the cluster

Once you have an account and are looking at your account dashboard, you should have a link to the Kubernetes panel. Inside, there is the option to create a cluster that would look like this:

Civo Kubernetes Dashboard

once created it would look like this:

Civo Managed Kubernetes Cluster

Next, we will need to ensure we can manage our cluster from the command line using kubectl. Click the link on the cluster page to download your kubeconfig file and set it as your KUBECONFIG variable.

Installing Argo CD

Once you have access to your cluster as the current context, the first thing will be, referencing the argo documentation site, to run the following in the cluster:

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

This will create a namespace with the name argocd in our cluster, and then it will install all the necessary things for argo to run.

Once everything is displayed, we will need to get the password generated by Argo to be able to login in the interface. We will do it this way:

$ kubectl get pods -n argocd -l app.kubernetes.io/name=argocd-server -o name | cut -d'/' -f 2

Now, logging in to Argo can be done in two ways, using your CLI or through the web interface. For access on the web there are two more options: the first is to create an ingress, explained on the Argo site. The second is to make a port-forward with kubectl in the following way, and is the one we will use to not expose argo to the wider internet:

kubectl port-forward svc/argocd-server -n argocd 8080:443

Now we can access the Argo CD UI using localhost:8080. Note that, as the default Argo-generated SSL certificate is self-signed, this will generate an error in your browser that you will have to bypass.

The username to the Argo web interface will be admin and the password is the one you displayed earlier using the console command above.

Adding a new repo to Argo

To start with Argo, the first thing will be to add a git repository through the menu:

Argo Management Panel

then we go to Repositories

Clicking on the link, we enter the repositories manager. Inside we click on connect Git repo using HTTPS that would open a sidebar to put the data of our git repo, in our case we will only use the url because what we will deploy in this example will be OpenFaaS, which is a public repository.

The url of the repository is https://github.com/openfaas/faas-netes

After we add it it will look like this:

Deployed Repository

Installing OpenFaaS

Requirements

So far we have Argo CD running, and the OpenFaas repo ready. The next step will be to create the cluster namespace for OpenFaaS and it is done in this way:

$ kubectl apply -f https://raw.githubusercontent.com/openfaas/faas-netes/master/namespaces.yml

after this we need to generate a password for OpenFaaS. Once generated do not forget it, or use one that you already know in place of the generator.

# generate a random password
PASSWORD=$(head -c 12 /dev/urandom | shasum| cut -d' ' -f1)

kubectl -n openfaas create secret generic basic-auth --from-literal=basic-auth-user=admin \
--from-literal=basic-auth-password="$PASSWORD"

Deploying

Once this is ready, we can go to the Argo interface and create an application by clicking on New application then fill in the fields. To make it simple, you can click on Edit as yaml and paste the following rather than input the individual fields:

apiVersion: argoproj.io/v1alpha1
metadata:
  name: openfaas
spec:
  destination:
    namespace: openfaas
    server: 'https://kubernetes.default.svc'
  source:
    path: chart/openfaas
    repoURL: 'https://github.com/openfaas/faas-netes'
    targetRevision: HEAD
    helm:
      valueFiles:
        - values.yaml
  project: default
  syncPolicy:
    automated:
      prune: false
      selfHeal: true

Once you have done this, click on save and create and voila. Now we can see how the app syncs itself and it will look something like this:

Argo Synced

Creating the ingress for OpenFaaS

Once this is done we can create the ingress for OpenFaaS in the following way. Note that you will have to change the host value! Your host line would be the url that the Civo cluster administration panel gives you. In my case this was 00a663e6-aed2-4dad-9a5b-6903751c08f7.k8s.civo.com.

Create the following file as openfaas-ingress.yaml on your computer:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: openfaas-ingress
  namespace: openfaas
  annotations:
    kubernetes.io/ingress.class: traefik
spec:
  rules:
  - host: openfaas.00a663e6-aed2-4dad-9a5b-6903751c08f7.k8s.civo.com
    http:
      paths:
      - path: /
        backend:
          serviceName: gateway
          servicePort: 8080

Using kubectl apply the ingress:

$ kubectl apply -f openfaas-ingress.yaml

Now you should be able to visit the URL of your cluster host, in my case openfaas.00a663e6-aed2-4dad-9a5b-6903751c08f7.k8s.civo.com. Have a play with the help of the documentation here.

If any changes are made to the master branch of the OpenFaaS repository, these would be automatically synced through Argo to your particular deployment. GitOps!

One more test

After finishing the above guide, I wanted to try if Argo would work for other projects, and decided to try. We will repeat the option of adding a new repo but this time we are going to use the Docker voting app example found at https://github.com/dockersamples/example-voting-app. Once this is done, we will create a namespace in our Kubernetes cluster using kubectl create namespace vote. Then we will create a new application in the Argo interface, just like in the OpenFaaS example above. This time, this is the yaml:

apiVersion: argoproj.io/v1alpha1
metadata:
  name: vote
spec:
  destination:
    namespace: vote
    server: 'https://kubernetes.default.svc'
  source:
    path: k8s-specifications
    repoURL: 'https://github.com/dockersamples/example-voting-app'
    targetRevision: HEAD
  project: default
  syncPolicy:
    automated:
      prune: false
      selfHeal: true

This is a bit different from the previous one since in this case I will use the k8s-specifications directory to deploy, since this directory contains all the yaml for kubernetes, so we can see it works also for deployments without helm. Now for the ingress for this project:

Save the following as vote-ingress.yaml, once again changing the host lines to be the URL of your civo cluster, preserving the vote and result prefix:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: vote-ingress
  namespace: vote
  annotations:
    kubernetes.io/ingress.class: traefik
spec:
  rules:
  - host: vote.00a663e6-aed2-4dad-9a5b-6903751c08f7.k8s.civo.com
    http:
      paths:
      - path: /
        backend:
          serviceName: vote
          servicePort: 5000
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: result-ingress
  namespace: vote
  annotations:
    kubernetes.io/ingress.class: traefik
spec:
  rules:
  - host: result.00a663e6-aed2-4dad-9a5b-6903751c08f7.k8s.civo.com
    http:
      paths:
      - path: /
        backend:
          serviceName: result
          servicePort: 5001

Once again, apply the ingress:

$ kubectl apply -f vote_ingress.yaml
ingress.extensions/vote-ingress created
ingress.extensions/result-ingress created

Now you can visit your equivalents of vote.00a663e6-aed2-4dad-9a5b-6903751c08f7.k8s.civo.com to vote and result.00a663e6-aed2-4dad-9a5b-6903751c08f7.k8s.civo.com for see the results.

At the end the dashboard of Argo look like this: Two Applications deployed

Conclusion

Well now I think that everything is ready. I hope you liked Argo CD, I still have some more tests to do but everything points to it being a great tool to run GitOps. The above are simple examples, but you could easily deploy an application from your own repository, push changs and see them reflected in your cluster deployment as soon as Argo refreshes.