Argo CD Image Updater will make your GitOps life easier for your Sitecore setup in Kubernetes

Developers, I hope you are well out there! A new year and a lot of new promises πŸ™‚

The Sitecore User Group Conference (SUGCON) – Europe 2023, is almost upon us. This time it’s in Malaga in Spain. You should register at once => https://europe.sugcon.events/

Before we start, let’s celebrate and congratulate all the happy Sitecore MVPs. Read all about it – https://www.sitecore.com/company/newsroom/press-releases/2023/01/sitecore-announces-2023-most-valuable-professionals
Hip hip hooray πŸŽ‰πŸ˜Š

Today’s post will be all about Argo CD, yes there are others, but ArgoCD is my Number 1 πŸ™‚
What I love about ARGO is that they have a bunch of tools/services, and one of them is… Argo CD Image Updater

A tool to automatically update the container images of Kubernetes workloads that are managed by Argo CD.

The Argo CD Image Updater can check for new versions of the container images that are deployed with your Kubernetes workloads and automatically update them to their latest allowed version using Argo CD.

This means it will watch every change in your container registry, and then update your GitOps repository with the change. You can even skip the part to update in the GitOps repo and instead update directly in the Kubernetes cluster(This approach should only be done in test, never in production).

What I really like about Argo CD Image Updater is that I don’t have to update the GitOps repository anymore after every build( and push) of the docker images. Instead Argo CD Image Updater will do it for us, and that’s a HUGE win πŸ™‚

So today’s post will be about how to setup Argo CD Image Updater in an AKS(Azure Kubernetes Service) cluster and use it πŸ™‚ We will assume that you already have installed Argo CD. If not, just follow the instruction here – https://argo-cd.readthedocs.io/en/stable/getting_started/ πŸ™‚

It’s time to install Argo CD Image Updater, let’s follow the instructions => https://argocd-image-updater.readthedocs.io/en/stable/install/installation/

We will install the Image Updater in the same namespace as Argo CD, to install it we just deploy the manifest:

kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj-labs/argocd-image-updater/stable/manifests/install.yaml

Let’s have a look if it’s up? YES, success πŸ™‚

A good idea is to add some extra logging, at least in the beginning. This means we will update the ConfigMap => argocd-image-updater-config. We simply do the following kubectl command :

kubectl edit configmaps --namespace argocd argocd-image-updater-config

It will open up your text editor tool(notepad for me)

Type in you change, save and then close it πŸ™‚

data:
  log.level: debug

Ok! Next part is to add a connection to our container registry. You can read about it here => https://argocd-image-updater.readthedocs.io/en/stable/configuration/registries/

This means we will update ConfigMap => argocd-image-updater-config again, and add the following in the data section(right below log.level: debug):

  registries.conf: |
    registries:
    - name: Azure Container Registry
      prefix: mycontainerregistry.azurecr.io
      api_url: https://mycontainerregistry.azurecr.io
      credentials: pullsecret:argocd/mycontainerregistry-secret

Let me go through each “attribute”.
NAME, it’s just a name.
PREFIX, here we set the “Login server” from our Azure Container Registry
API URL, it’s the “Login server” from our Azure Container Registry but with https://
CREDENTIALS, now this part is a bit tricky πŸ™‚

According to the section => https://argocd-image-updater.readthedocs.io/en/stable/basics/authentication/#auth-registries
There are three ways:

I first went for the generic secret, but no luck 😦
*I read somewhere it could work if you used Service Principle.

But pull secret worked πŸ™‚ So, to create a pull secret, we will create a docker-registry secret. Again we will do this with a kubectl command:

kubectl -n argocd create secret docker-registry mycontainerregistry-secret --docker-server=mycontainerregistry.azurecr.io --docker-username=mycontainerregistry--docker-password=PASSWORD -o yaml --dry-run=client | kubectl -n argocd apply -f -

Let’s go through the command. But before we start, we need to set “Admin user” to Enabled in our Azure Container Registry:

Ok! We will name the secret with mycontainerregistry-secret. For –docker-server we set the “Login server” from our Azure Container Registry. And for docker-username we will use the “Username” from our Azure Container Registry. And for docker-password we will use one of the passwords from our Azure Container Registry.

Let’s check if the secret is created. Yes, success πŸ™‚

Did you notice the type: kubernetes.io/dockerconfigjson. This means we will have JSON in the secret πŸ™‚ Here is the JSON:

{
	"auths": {
		"mycontainerregistry.azurecr.io": {
			"username": "mycontainerregistry",
			"password": "PASSWORD",
			"auth": "bXljb250YWluZXJyZWdpc3RyeTpQQVNTV09SRA=="
		}
	}
}

Great! So let us run the following command to update our ConfigMap => argocd-image-updater-config.

kubectl edit configmaps --namespace argocd argocd-image-updater-config

And add the connection info(to the container registry):

The last thing we need to do is to restart the Image Updater. I was going crazy here, and I could not understand why the Image Updater had no access to our Azure Container registry. But after a restart, everything worked. To restart we kill the pod, and it will create itself again πŸ™‚

So now the Image Updater has access to our Azure Container Registry. Next will be to configure/tell our ArgoCD applications how to update images.

There are many ways to configure the ArgoCD application => https://argocd-image-updater.readthedocs.io/en/stable/configuration/images/#configuring-images-for-update

There are four update strategies:

  • semver Update to the tag with the highest allowed semantic version
  • latest Update to the tag with the most recent creation date
  • name Update to the tag with the latest entry from an alphabetically sorted list
  • digest Update to the most recent pushed version of a mutable tag

By default, it’s set to use semver, and that’s what we will use πŸ™‚

If you want the Image Updater to update the image directly in your Kubernetes cluster, I would recommend you go for digest. You will have a tag like :latest and then the Image Updater will watch the “digest changes” in your repository. Don’t forget to add the annotation => argocd-image-updater.argoproj.io/myalias.update-strategy: digest

So let’s have a look at one of our ArgoCD applications and see the benefits of using ArgoCD Image Updater:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: nextjs-myapp
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/sandbox/GitOps.Test
    targetRevision: main
    path: k8/Sandbox/specs/nextjs-myapp
  destination:
    server: https://kubernetes.default.svc
    namespace: default
  syncPolicy:
    automated:
      selfHeal: true  
      prune: false

This is a “standard” ArgoCD application. Which will listen to changes(to be more specific, it will listen to changes in the kustomize file) in the path k8/Sandbox/specs/nextjs-myapp in GitOps.Test repository.

Here is the kustomization file for MyApp:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
images:
- name: nextjs-myapp
  newName: mycontainerregistry.azurecr.io/sandbox-nextjs-myapp-test
  newTag: v1.0.1
resources:
- _deployment.yaml
- _pdb.yaml
- _service.yaml
- _hpa.yaml 

Let’s visualize it with a CI/CD workflow(GitHub Actions):

  • Developer creates a PR and merges it to the test branch.
  • A GitHub Action generates and pushes the docker image(gives it a proper tag name) to the Azure Container Registry.
  • The second GitHub Action updates the GitOps repository(the kustomization file) with the new image tag.

ArgoCD listens to the changes in the GitOps repository and syncs the changes to the Kubernetes cluster.


But with ArgoCD Image Updater, we don’t need the step that updates the GitOps repository. That means that the CI/CD workflow will now look like this:

So how do we do this? Well, all we have to do is to update the ArgoCD application MyApp, with “annotations”:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: nextjs-myapp
  namespace: argocd
  annotations:
    argocd-image-updater.argoproj.io/image-list: myalias=mycontainerregistry.azurecr.io/sandbox-nextjs-myapp-test:*
    argocd-image-updater.argoproj.io/write-back-method: git       
    argocd-image-updater.argoproj.io/git-branch: main      
    argocd-image-updater.argoproj.io/write-back-target: kustomization
    argocd-image-updater.argoproj.io/myalias.force-update: "true" 
spec:
  project: default
  source:
    repoURL: https://github.com/sandbox/GitOps.Test
    targetRevision: main
    path: k8/Sandbox/specs/nextjs-myapp
  destination:
    server: https://kubernetes.default.svc
    namespace: default
  syncPolicy:
    automated:
      selfHeal: true  
      prune: false

Let’s go through the annotations!

argocd-image-updater.argoproj.io/image-list:
This tells Image Updater what repository to watch,Β myalias=mycontainerregistry.azurecr.io/sandbox-nextjsproxy-myapp-test:*. (The reason for using an alias is that it’s the recommended approach) We set the name to our repository, and with the tag *, it means it will allow anything. This is not recommended. Instead, we should have something like this :~1(It will listen to changes as long as they are in version 1). But since we are using Image Updater in TEST, then theΒ :*Β is perfect for our needsΒ πŸ™‚

argocd-image-updater.argoproj.io/write-back-method:
This tells Image Updater to write to our GitOps repo, meaning it will update the GitOps repo with the latest changes(image tag) from the Azure Container registry.

argocd-image-updater.argoproj.io/git-branch:
This tells what git branch the Image Updater should use.

argocd-image-updater.argoproj.io/write-back-target:
Since we are using Kustomize, the value kustomization means that the Image Updater will update the Kustomize file in our repo.

And that’s it, now we have a running ArgoCD Image Updater that listens to changes in the container registry and then automatically updates the GitOps repository!

If you are still not convinced that Image Updater is your best GitOps friend(in your test environment), then you should check out what my favorite devops guy, DevOpsToolkit, has to say πŸ™‚

That’s all for now folks πŸ˜Š


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.