Share

The software team implements Continuous Integration and Delivery (CI/CD) pipelines or workflows to quickly build and release software to market. These pipelines are mostly built using tools like Jenkins and Spinnaker to automate the delivery process of cloud-native applications. The DevOps team continues to focus on making the development and deployment process more efficient.

Large and medium enterprises will have multiple teams working on various microservices getting deployed into public clouds. And the CI/CD pipelines will serve the best to deploy the code into production at scale.

But the teams who run Kubernetes in their production environments gradually realize the benefits of the GitOps style delivery model instead of a push-based CI/CD pipeline. And Argo CD is the best software to achieve GitOps and arguably is also getting adopted like wildfire these days. In this blog, I will explain how to achieve CI/CD using Argo CD and Jenkins.(Spoiler alert: I’ll be using Argo Image Updater.)

CI/CD pipeline using Argo CD Image Updater, Docker Hub and Jenkins

If you are using Jenkins for continuous integration, you would currently generate Docker images and store them in a container registry like Docker Hub. And then, you would manually update the manifest files in Git and trigger a CD pipeline (typically Spinnaker or GitHub Action) to deploy the new container image in the Kubernetes cluster. 

If you are a DevOps person or platform engineer, you can re-architect your pipeline to integrate Argo CD as a part of the CI/CD process and practice GitOps. 

The easier way to do this is to use Argo Image Updater, a component of Argo CD used to automatically update Kubernetes workload resources when there is a change in the container image version. 

Note: The Argo Image Updater is built to implement update strategies such as tracking registries to track new container images & updating manifest files with the new images based on criteria such as the latest semantic versioning. 

Once your images are uploaded to a registry, you can leverage Argo Image-Updater (as shown in Fig A) to sense the recent updation to the image path and update manifest files (Deployment resource) in the Git repository. And once the change to a manifest file is approved and merged with the master branch, the Argo CD controller will automatically sense the deviation between the target cluster and the Git definition. Argo will synchronize the Kubernetes cluster with the desired state upon approval. 

CI/CD pipeline using Argo CD Image Updater and Jenkins

Prerequisite:

  1. Docker Hub 
  2. Kubernetes 
  3. Argo CD installed in a namespace argocd

You check out how to install Argo CD using HELM or manifest file.

Steps to use Argo Image Updater with Docker registry and Argo

Please follow the steps below to integrate Argo Image Updater with your registry and Argo to enable the seamless deployment of applications.

  1. Install Argo Image Updater
  2. Create local Image Updater account in Argo CD
  3. Granting RBAC to Argo Image Updater in Argo
  4. Configure Argo CD endpoints in Image Updater
  5. Configure API access token secret for Image Updater
  6. Create an application in Argo
  7. Update image using Image updater and deploy the application using Argo

Install Argo Image Updater

  1. Run below command to install image updater
  2. It is installed in same argocd namespace ( this is sort-of-mandatory)
				
					kubectl apply -n argocd -f
				
			

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

OUTPUT:

serviceaccount/argocd-image-updater created

role.rbac.authorization.k8s.io/argocd-image-updater created

rolebinding.rbac.authorization.k8s.io/argocd-image-updater created

configmap/argocd-image-updater-config created

configmap/argocd-image-updater-ssh-config created

secret/argocd-image-updater-secret created

deployment.apps/argocd-image-updater created

 

Create a local Image-Updater account in Argo CD

1. Add an account called  image-updater with appropriate API permissions.

2. Edit the argocd-cm configmap 

				
					kubectl edit cm argocd-cm  -n argocd
				
			

3. Add below content in the configmap in the data section. To provide the permission to image-updater to get updation of an application in Argo CD. 

				
					data:
  accounts.image-updater: apiKey
				
			

4. Login to the ArgoCD via CLI to use argocli

				
					argocd login --username=xxx --password=xxxx <ARGOCD URL>
				
			

5. Generate the access token for the image-updater account

				
					argocd account generate-token --account image-updater --id image-updater
				
			

6. Save this TOKEN will be used other places

Granting RBAC permissions to Image Updater in Argo CD

After creating the image-updater account, we need to provide the read and update permissions to the accounting Argo CD. 

1. Edit the argocd-rbac-cm configmap 

				
					kubectl edit cm argocd-rbac-cm  -n argocd
				
			

2. Add below rules to the rbac cm and save it 

				
					 policy.csv: |
    p, role:image-updater, applications, get, */*, allow
    p, role:image-updater, applications, update, */*, allow
    g, image-updater, role:image-updater

				
			

Configure Argo CD endpoint in image-updater configmap

Similarly, we will also change the configuration in Argo Image Updater to allow the application to make changes to resources on-demand.  

1. Run below command to edit endpoint in the image-update configmap

				
					kubectl edit cm argocd-image-updater-config  -n argocd
				
			

2. Add below content to the configmap

				
					data:
  applications_api: argocd
  argocd.server_addr: <Argo CD server URL without https>
  argocd.grpc_web: "true"
  argocd.insecure: "false"
  argocd.plaintext: "false"


INFO:
  argocd.server_addr: <FQDN or IP of your Argo CD server>
  # Whether to use GRPC-web protocol instead of GRPC over HTTP/2
  argocd.grpc_web: "true"
  # Whether to ignore invalid TLS cert from Argo CD API endpoint
  argocd.insecure: "false"
  # Whether to use plain text connection (http) instead of TLS (https)
  argocd.plaintext: "false"
Example : Using k3s local 

  argocd.grpc_web: "true"
  argocd.insecure: "true"
  argocd.plaintext: "false"
  argocd.server_addr: 10.43.80.249

				
			

Configure API access token secret for image-updater

To ensure the communication between Argo Image Updater is securely accessing Argo CD, create a secret for image-updater to communicate with the Argo CD application. 

1. Create a secret file in the namespace where image-updater is installed

				
					kubectl create secret generic argocd-image-updater-secret \
  --from-literal argocd.token=$YOUR_TOKEN --dry-run -o yaml |
  kubectl -n argocd apply -f -
				
			

2. Restart the image-updater pod with the below command to reflect the changes

				
					kubectl -n argocd rollout restart deployment argocd-image-updater 
				
			

You have successfully created the setup between Argo Image updater and Argo CD. Now we will proceed by creating an application in Argo CD, configuring a Git repo and target cluster for deployment. 

Create an application in Argo CD

To create an application I will use the Issuegen application with a service and a deployment resource. 

Issuegen application with a service and a deployment resource.

1. Inside the Deployment resource I have used the image with tag v3.0.6 (version). You can have your image and path defined under the spec in the Deployment yaml file. 

2. Then you can create an application in Argo CD 

create an application in Argo CD
click on new app create an application Argo CD

3. Argo will throw an out-of-sync status, but you can sync it. 

Note: In case you want to know more, then read my previous blogs configuring private Git repositories in Argo CD and multicluster K8S cluster in Argo CD.

Update the image using Image Updater

This is the final step, where we will first let the Image Updater identify the application name and docker-registry path. So that when we update the image version in Docker registry, Image Updater will update the manifest file automatically. 

1. Create a new Kustomization.yaml in the location of manifest files located. With Kustomization.yaml Argo Image Updater will automatically come to know there are images inside the manifest files. 

Create a new Kustomization.yaml argo image updater

2. Create the github repo secret to access the repo in the namespace of argocd installed. This is to allow image-updater to access Git repo and update the manifest files when there is change in the image (in container registry )

				
					kubectl create secret generic githubsecret\
  --from-literal username=gihubusername --from-literal password=gihubpassword -n argocd  
				
			

3. Add annotation to the application as required. Image-updater should know which application to monitor based on the branch URL, or image URL or secret path. 

Branch annotation: (Branch name of the repo)

				
					argocd-image-updater.argoproj.io/git-branch=main
				
			

Image annotation:   (Image with patch version tag with v3, tilde symbol matches the version ‘~’ )

				
					 argocd-image-updater.argoproj.io/image-list=docker.io/opsmxdev/issuegen:~v3
				
			

Secret annotation:(githubsecret with namespace)

				
					argocd-image-updater.argoproj.io/write-back-method: git:secret:argocd/githubsecret
				
			

4. Click on app details

click on app details

5. Edit imageupdater application in Argo

imageupdater application in Argo

6. Add annotation to the application and save it.

7. Update the docker registry with the latest image. In this case I have updated it to v3.10.24. Usually this part will be done automatically using Jenkins pipeline. 

Update the docker registry with the latest image

8. Once the image is updated, you can go to Argo UI and refresh the application. In the background, Image Updater will poll and notice there is a new image with tag v3 and will update the change in the application resource (Deployment).

9. A new file will be created with app name suffix  by the Argo Image Updater itself. 

10. Argo CD will consider the new image v3.10.24 in the Deployment file during the run-time.

Argo CD will consider the new image

11. Your application will show OutOfSync status. Once you manually sync the application to deploy the latest image, a new version of image will be deployed in the issuegen application pod.

Troubleshooting:-

1. IF you don’t have kustomisation file  error will appear like below(ignore if not )

Unable to create application: application spec for imageupdatetest is invalid: InvalidSpecError: Unable to generate manifests in kubernetes: rpc error: code = Unknown desc = `kustomize edit set nameprefix — image` failed exit status 1: Error: Missing kustomization file ‘kustomization.yaml’. Usage: kustomize edit set nameprefix [flags] Examples: The command set nameprefix acme- will add the field “namePrefix: acme-” to the kustomization file if it doesn’t exist, and overwrite the value with “acme-” 

2. Image-updater pods  successful logs will be like this

time=”2022-12-08T12:03:40Z” level=info msg=”Successfully updated the live application specapplication=imageupdater

time=”2022-12-08T12:03:40Z” level=info msg=”Processing results: applications=1 images_considered=1 images_skipped=0 images_updated=1 errors=0

Next Step

In case you have any queries wrt to implementing the CI/CD pipeline using Argo then please feel free to contact us 24*7 support. If you need to save all the hassle and get started with enterprise-wide GitOps deployment, then use OpsMx Enterprise for Argo (OEA) which comes with all the bells and whistles for security and scale requirements for your software delivery. 

Mahesh Kumar K

DevOps Engineer at OpsMx. Certified Kubernetes Administrator| Docker | CI/CD | AWS | Spinnaker | Argo | Bash script | Helm | Jenkins | SCM | automation and Configurations

Link

0 Comments

Submit a Comment

Your email address will not be published.

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