I have deployed the application via ArgoCD successfully, and I can access it via its ingress url

The applicaiton uses the image name with latest tag, such as

image: <private_registry>/app_1_service:latest

I also manage other tags on same of tag latest, such as image:<commit_id> or image:<1.0.xxx>

Now, developers will update the codes, after commit changes, a gitlab pipeline autoamtically runs and build a new image and override to tag latest with other tags and push to private docker registry

So what's the next step in ArgoCD?

How argocd know the application is changed, and need be redeployed, and the image:latest need be pull again?

3

Best Answer


You can use ArgoCD image-updater

But before using the the image-updater, you need to install and set appropriate permission

helm repo add argo https://argoproj.github.io/argo-helmhelm install argocd-image-updater argo/argocd-image-updater

Once image-updator is up and running, then you need to set a few annotations in the Argocd application, as the update workers on different strategies

semver - Update to the latest version of an image considering semantic versioning constraintslatest - Update to the most recently built image found in a registry
digest - Update to the latest version of a given version (tag), using the tag's SHA digest
name - Sorts tags alphabetically and update to the one with the highest cardinality

latest strategies working awesome with tagging under some regex and digest more suited for testing environment.

update-strategies

You can also pull the private image from gitlab as well.

Here is the working example with helm-release

apiVersion: argoproj.io/v1alpha1kind: Applicationmetadata:annotations:argocd-image-updater.argoproj.io/image-alias.allow-tags: 'regexp:^1.3.0-SNAPSHOT.[0-9]+$'argocd-image-updater.argoproj.io/image-alias.force-update: 'true'argocd-image-updater.argoproj.io/image-alias.pull-secret: 'pullsecret:develop-namespace/develop-app-gitlab-secrets'argocd-image-updater.argoproj.io/image-alias.update-strategy: latestargocd-image-updater.argoproj.io/image-list: >-image-alias=registry.gitlab.com/myorg/my-test-imagefinalizers:- resources-finalizer.argocd.argoproj.iolabels:app.kubernetes.io/instance: develop-platformname: develop-appnamespace: argocdspec:destination:namespace: develop-appserver: 'https://kubernetes.default.svc'project: develop-app-west6-bsource:helm:releaseName: develop-appvalueFiles:- develop-platform/values.yamlpath: helm-chart/helm-chartrepoURL: 'https://gitlab.com/my-org/develop-app.git'targetRevision: stagingsyncPolicy:automated:prune: trueselfHeal: true

If you need digest or just a latest then remove this

 argocd-image-updater.argoproj.io/image-alias.allow-tags: 'regexp:^1.3.0-SNAPSHOT.[0-9]+$'

this is working base on regex.so in your case <1.0.xxx>

it can be 'regexp:^1.0.[0-9]+$'

If everything configured properly and image updater working fine then you should be able to see logs image updater logs like this

time="2022-04-27T15:18:36Z" level=info msg="Successfully updated image 'registry.gitlab.com/test-image:0.3.0-SNAPSHOT.115' to 'registry.gitlab.com/test-image:0.3.0-SNAPSHOT.118'

If you are using latest tag, the most simple way is this

  • set your k8s yaml imagePullPolicy to Always
  • add below step in gitlab-ci.yml to restart application by calling argocd api
argocd-restart:image: argoproj/argocdstage: deployvariables:GIT_STRATEGY: noneARGOCD_SERVER: "192.111.111.111:30000"# gitlab admin panel variable# ARGOCD_USERNAME: "admin"# ARGOCD_PASSWORD: "XXXXXX"before_script:- echo "ARGOCD_SERVER:$ARGOCD_SERVER"- echo "ARGOCD_APP_NAME:$ARGOCD_APP_NAME"- echo "ARGOCD_USERNAME:$ARGOCD_USERNAME"script:- argocd login "${ARGOCD_SERVER}" --insecure --username "${ARGOCD_USERNAME}" --password "${ARGOCD_PASSWORD}"- argocd app actions run "$ARGOCD_APP_NAME" restart --kind Deployment |& tee response.txt- cat response.txt# if response.txt have content, exit with error, empty response means success- if [ -s response.txt ]; then exit 1; fionly:- master- dev

argocd cli doc: https://argo-cd.readthedocs.io/en/stable/user-guide/commands/argocd_app_actions_run/

Above solution is not suit for production, because

  • imagePullPolicy: Always means k8s always need to connect registry
  • download image everytime when restart is waste of resource
  • don't have version control

so for stg and prod, i do this.Create a helm value file only for image tag such as stg-image-tag.yaml.

image:tag: "stg-v0.0.1"

Add this file to argocd app configenter image description here

Modify gitlab-ci.yml, build image with new image tag, and commit the image tag to stg-image-tag.yaml

  • i use $CI_PIPELINE_IID as version number in image tag.
  • i have branch name for each env
docker-build:image: dockerstage: buildvariables:# REGISTRY_SERVER: 192.168.111.111# REGISTRY_USER: xxx# REGISTRY_PASSWORD: xxxbefore_script:- IMAGE_TAG="$CI_COMMIT_REF_SLUG-v0.0.$CI_PIPELINE_IID"script:- docker login -u "$REGISTRY_USER" -p "$REGISTRY_PASSWORD" $REGISTRY_SERVER- docker build .-t "$NEW_IMAGE_REPO:latest"-t "$NEW_IMAGE_REPO:$IMAGE_TAG"- docker push "$NEW_IMAGE_REPO" --all-tags- echo IMAGE_TAG=$IMAGE_TAG >> IMAGE_TAG.env- cat IMAGE_TAG.envartifacts:reports:# add IMAGE_TAG to other jobs as env vardotenv: IMAGE_TAG.envexpire_in: "86400" # 1 daycommit-image-tag:image: curlimages/curlstage: deployneeds:- job: docker-buildartifacts: truevariables:GIT_STRATEGY: noneGITLAB_PROJECT_ID: "111"GITLAB_PROJECT_TOKEN: "xxxxxxxxxxx"before_script:- echo "IMAGE_TAG:$IMAGE_TAG"script:- |cat <<EOF > body.txt{"branch":"master","commit_message":"update image tag ${IMAGE_TAG}","actions":[{"action":"update","file_path":"helm-charts/${CI_COMMIT_REF_SLUG}-image-tag.yaml","content":"image:\n tag: $IMAGE_TAG"}]}EOF- |cat <<EOF > header.txtAuthorization: Bearer ${GITLAB_PROJECT_TOKEN}Content-Type: application/jsonEOF- curl --insecure "${CI_SERVER_URL}/api/v4/projects/${GITLAB_PROJECT_ID}/repository/commits" -i --output response.txt--header @header.txt --data @body.txt--silent --write-out "%{response_code}" > response_code.txt- cat response.txt# error if response code is not 201- if [ "$(cat response_code.txt)" != "201" ]; then exit 1; fionly:- stg- prod

Then you setup a webhook so argocd will refresh image tag immediately.otherwise argocd will refresh every 3 min.enter image description here

ArgoCD supports 2 types of application syncing policies:

  1. manual: a user will login into the dashboard and update the image/chart version
  2. automatic: ArgoCD will poll the container registry at fixed interval (e.g 3 min) and check if a new image's/chart's version is available based on a pattern. You can use regex to specify the image pattern. Argo will compare the current version with the new one.

Auto sync option in ArgoCD dashboard

Here's an example of deploying helm from Jfrog artifact registry automatically:

project: defaultsource:repoURL: 'https://abc.jfrog.io/artifactory/helm'targetRevision: '*.*.*' # set your regex pattern herehelm:parameters:- name: image.tagenv: devchart: frontend-chartdestination:server: 'https://kubernetes.default.svc'namespace: defaultsyncPolicy:automated: {} # enables auto syncing