TECHSTEP

ITインフラ関連の記事を公開してます。

ArgoCD Image Updaterを試す

今回はArgoCD Image Updaterを使ってみます。

ArgoCD Image Updaterとは

ArgoCD Image Updaterは、コンテナレジストリを定期的にチェックし、新しいイメージが配置されていれば、KubernetesマニフェストファイルやArgoCD Applicationを自動的に更新する機能を提供します。名称の通りArgoCDと一緒に使うことが前提で、ArgoCD Image Updaterがマニフェストを書き換えると、ArgoCDがそれを検知し、自動的にリソースの更新を行うような構成が可能となります。

ArgoCDはソースコードリポジトリ上のマニフェストファイルとクラスター上のリソース定義との差分を検知して、リソースの更新を行います。そのため、アプリケーションを更新するには、何らかの方法でマニフェストファイルの修正を行い、Podの再作成を行わなければなりません。

これまではCIの処理の中でマニフェストファイルの修正を行ったり、手動でファイルを修正することが多かったですが、ArgoCD Image Updaterを導入することでこの処理をカスタマイズする手間が省けると見込めます。

なお、ArgoCD Image Updaterと同じような機能を提供するプロダクトとしては、 Fluxが有名かと思います。Fluxにはイメージタグを自動更新する機能が最初から組み込まれており、 ImageRepository などのカスタムリソースを使うことで実現できます。

イメージ更新のプロセス

ArgoCD Image Updaterがどのようにイメージの更新を検知・更新するかは、ドキュメントに記載されています

  1. Kubernetes APIかArgoCD APIを使い、現在ArgoCD Applicationがクラスター上に存在するかをスキャンします。どちらのAPIを利用するかは ArgoCD Image Updaterをインストールする方法によります
  2. 見つかったApplicationの中に argocd-image-updater.argoproj.io/image-list というAnnotationが存在するかをチェックします。このAnnotationは、ArgoCD Image Updaterがチェックする対象のコンテナイメージレジストリを指定するもので、ArgoCD Image Updaterを使用する場合は必須の設定です。
  3. Annotationに設定されているイメージが、実際にApplicationによってデプロイされているかをチェックします。
  4. 指定したイメージが実際にデプロイされていれば、それをアップデート対象のイメージとして、対象のコンテナレジストリにアクセスします。そして、Applicationのファイルで指定する設定に従い、新しいバージョンのイメージがレジストリ中に存在するかをチェックします。
  5. 新しいバージョンのイメージがあれば、設定に従いイメージタグを更新します。更新方法は後述する2種類が存在します。

※参考リンク:

前提条件

前提として、ArgoCD Image Updaterは現在開発中のステータスにあるプロダクトです。そのため、将来破壊的な変更が入る可能性が高いとのことです。

また、利用するにあたり、現時点でいくつかの制限事項が存在します。

  • 更新対象となるイメージは、ArgoCD Applicationが管理するリソースのみが対象となる
  • 更新対象となるイメージは、Kustomize/Helmでマニフェストを管理するものだけが対象となる。Helmの場合はパラメータを使ってイメージタグを指定する必要がある。
  • コンテナイメージリポジトリへのアクセスに使う秘匿情報は、ArgoCD Image Updaterと同じクラスター上に存在しなければならない
  • ArgoCDから実行するロールバックには対応しておらず、ロールバック中のApplicationも更新しようとする (ArgoCDはそのようなApplicationの自動Syncを無効化する)。

※参考リンク:

ArgoCD Image Updaterを使ってみる

ここから実際にArgoCD Image Updaterを使ってみます。

事前準備

ArgoCD Image Updaterをデプロイする前に、EKSクラスター上にArgoCDをデプロイし、そこからGitHubリポジトリと同期した状態を作ります。

今回は事前に以下のリソースを用意しました。アプリケーションを修正してGitHubにPushするとCIが起動し、ECRに新しいイメージがPushされるようにします。また、GitHubリポジトリをprivateにしているため、ArgoCDがリポジトリにアクセスするよう、Kubernetes Secret リソースを用意しています。

詳細は書かないですが、使用したファイルの一部は以下に載せます。

GitHubリポジトリ中のディレクトリ構成

.
├── .github
│   └── workflows
│       └── docker-build-push.yaml
├── README.md
├── app
│   ├── Dockerfile
│   └── main.go
├── application.yaml
└── manifest
    ├── base
    │   ├── deployment.yaml
    │   └── kustomization.yaml
    └── overlays
        └── dev
            └── kustomization.yaml

.github/workflows/docker-build-push.yaml

name: Dockerfile build and push to ECR
on:
  push:
    branches:
    - main
    paths:
    - 'app/*'
    - '.github/workflows/docker-build-push.yaml'
  workflow_dispatch:

permissions:
  id-token: write
  contents: read

env:
  IAM_ROLE_ARN: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/github-actions-role
  ECR_REGION: ap-northeast-1
  ECR_REGISTRY: ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.ap-northeast-1.amazonaws.com
  ECR_REPOSITORY: argocd-image-updater-test

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Configure AWS credentials
      uses: aws-actions/configure-aws-credentials@v1
      with:
        aws-region: ${{ env.ECR_REGION }}
        role-to-assume: ${{ env.IAM_ROLE_ARN}}
    - name: Login to ECR
      id: login-ecr
      uses: aws-actions/amazon-ecr-login@v1
    - name: Create Image Tag
      id: image-tag
      run: |
        SHA=${{ github.sha }}
        TAG=$(TZ=UTC-9 date '+%Y%m%d')-${SHA:0:7}
        echo "DOCKER_TAG=$TAG" >> $GITHUB_ENV
    - name: build and push to ECR
      id: build-image
      uses: docker/build-push-action@v2
      with:
        push: true
        file: app/Dockerfile
        tags: ${{ env.ECR_REGISTRY }}/${{ env.ECR_REPOSITORY }}:${{ env.DOCKER_TAG }}

application.yaml

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: app
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/fy0323/argocd-image-updater-test.git
    targetRevision: main
    path: manifest/overlays/dev/
  destination:
    server: https://kubernetes.default.svc
    namespace: default

manifest/base/deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-app
  labels:
    app: sample
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sample
  template:
    metadata:
      labels:
        app: sample
    spec:
      containers:
      - name: app
        image: <AWS account id>.dkr.ecr.ap-northeast-1.amazonaws.com/argocd-image-updater-test:20221112-540daf5
        ports:
        - containerPort: 8080

---
apiVersion: v1
kind: Service
metadata:
  name: sample-app
spec:
  selector:
    app: sample
  ports:
  - protocol: TCP
    name: http
    port: 80
    targetPort: 8080

manifest/base/kustomization.yaml

resources:
- deployment.yaml

manifest/overlays/dev/kustomization.yaml

resources:
- ../../base
commonLabels:
  env: develop

ArgoCD Image Updater導入前のアプリケーションは、以下のような文字列を出力します。以降のイメージ更新では、この文字列を修正して比較します。

$ kubectl run nginx --image nginx

$ kubectl exec -it nginx -- curl http://sample-app
<html><body>Hello, Argocd Image Updater</body></html>

ArgoCD Image Updaterの導入

ここから上記構成にArgoCD Image Updaterを導入します。また、ArgoCD Image UpdaterがECRを使うために追加が必要な設定もあるので、そちらも併せて設定します。

ArgoCD Image Updaterは複数のコンテナイメージリポジトリで動作することが確認されていますが、現時点でAmazon ECRはドキュメントには記載されていません。ただ、GitHub issueには設定方法が紹介されていたり、すでに本番環境で導入されている例もあるため、それらを参考にしています。

※参考:

インストール用ファイルの用意

ArgoCD Image Updaterのインストール用のファイルはGitHubに配置されています。今回はこのファイルを一部修正する必要があるため、事前に手元に用意しておきます。

IRSAの用意

ArgoCD Image Updaterがコンテナイメージの検索や更新の検知をするには、ターゲットのコンテナレジストリにアクセスする必要があります。ArgoCD Image UpdaterにECRへのアクセス権を付与するには、Image Updater Podの動作するNodeか、Pod自体にIAMポリシーを付与する必要があります。セキュリティのことを考慮すると後者のほうが望ましいため、今回はIRSA (IAM Role for Service Account) を利用します。

IRSAの設定は今回AWSマネージドコンソールから行いました(手順はこちらなどを参照してください)。ArgoCD Image Updaterが必要な権限はECRに対する読み取り権限だけなので、今回は AmazonEC2ContainerRegistryReadOnly というAWSのマネージドポリシーを付与したロールを用意しました。

また、ArgoCD Image UpdaterのService AccountがIAMロールを利用するため、マニフェストファイルを修正します。

apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/name: argocd-image-updater
    app.kubernetes.io/part-of: argocd-image-updater
  name: argocd-image-updater
  # 以降を追加
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::<AWS account id>:role/role-for-ecr-access
argocd-image-updater-config ConfigMapの修正

ECRへのアクセスを行うには、IAMの権限を所有していることに加え、アクセス用の認証トークンを使用する必要があります。このトークンは12時間ごとに無効になるため、定期的にトークンを取得する必要があります。

認証トークンを定期的に取得するにはCronJobを使う方法もありますが、今回は argocd-image-updater-configスクリプトを仕込む方法にしました。

argocd-image-updater-config はArgoCD Image Updaterのインストール時に合わせて作成されるConfigMapで、アクセス先のコンテナレジストリの情報やGitHubへのコミットメッセージなどの設定を定義するファイルです。このファイルに以下のような設定を追加します。

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-image-updater-config
  namespace: argocd
# 以降を設定
data:
  registries.conf: |
    registries:
      - name: ECR
        api_url: https://<AWS account id>.dkr.ecr.ap-northeast-1.amazonaws.com
        prefix: <AWS account id>.dkr.ecr.ap-northeast-1.amazonaws.com
        credentials: ext:/app/scripts/ecr-login.sh
        credsexpire: 10h
  ecr-login.sh: |
    #!/bin/sh
    aws ecr --region ap-northeast-1 get-authorization-token --output text --query 'authorizationData[].authorizationToken' | base64 -d

また、上記ConfigMapで取得した認証トークンをPodから利用するため、 argocd-image-updater Deploymentにも修正をします。

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/name: argocd-image-updater
    app.kubernetes.io/part-of: argocd-image-updater
  name: argocd-image-updater
spec:

(一部抜粋)

      # 以降を追加
        volumeMounts:
        - mountPath: /app/scripts
          name: ecr-login-script
      volumes:
      - configMap:
          defaultMode: 0755
          items:
          - key: ecr-login.sh
            path: ecr-login.sh
          name: argocd-image-updater-config
          optional: true
        name: ecr-login-script

最終的にArgoCD Image Updaterのデプロイに使用したマニフェストファイルは以下の通りです。

argocd-image-updater-manifest.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/name: argocd-image-updater
    app.kubernetes.io/part-of: argocd-image-updater
  name: argocd-image-updater
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::<AWS account id>:role/role-for-ecr-access
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/name: argocd-image-updater
    app.kubernetes.io/part-of: argocd-image-updater
  name: argocd-image-updater
rules:
- apiGroups:
  - ""
  resources:
  - secrets
  - configmaps
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - argoproj.io
  resources:
  - applications
  verbs:
  - get
  - list
  - update
  - patch
- apiGroups:
  - ""
  resources:
  - events
  verbs:
  - create
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/name: argocd-image-updater
    app.kubernetes.io/part-of: argocd-image-updater
  name: argocd-image-updater
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: argocd-image-updater
subjects:
- kind: ServiceAccount
  name: argocd-image-updater
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-image-updater-config
  namespace: argocd
data:
  registries.conf: |
    registries:
      - name: ECR
        api_url: https://<AWS account id>.dkr.ecr.ap-northeast-1.amazonaws.com
        prefix: <AWS account id>.dkr.ecr.ap-northeast-1.amazonaws.com
        credentials: ext:/app/scripts/ecr-login.sh
        credsexpire: 10h
  ecr-login.sh: |
    #!/bin/sh
    aws ecr --region ap-northeast-1 get-authorization-token --output text --query 'authorizationData[].authorizationToken' | base64 -d
---
apiVersion: v1
kind: ConfigMap
metadata:
  labels:
    app.kubernetes.io/name: argocd-image-updater-ssh-config
    app.kubernetes.io/part-of: argocd-image-updater
  name: argocd-image-updater-ssh-config
---
apiVersion: v1
kind: Secret
metadata:
  labels:
    app.kubernetes.io/name: argocd-image-updater-secret
    app.kubernetes.io/part-of: argocd-image-updater
  name: argocd-image-updater-secret
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/name: argocd-image-updater
    app.kubernetes.io/part-of: argocd-image-updater
  name: argocd-image-updater
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: argocd-image-updater
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app.kubernetes.io/name: argocd-image-updater
    spec:
      containers:
      - command:
        - /usr/local/bin/argocd-image-updater
        - run
        env:
        - name: APPLICATIONS_API
          valueFrom:
            configMapKeyRef:
              key: applications_api
              name: argocd-image-updater-config
              optional: true
        - name: ARGOCD_GRPC_WEB
          valueFrom:
            configMapKeyRef:
              key: argocd.grpc_web
              name: argocd-image-updater-config
              optional: true
        - name: ARGOCD_SERVER
          valueFrom:
            configMapKeyRef:
              key: argocd.server_addr
              name: argocd-image-updater-config
              optional: true
        - name: ARGOCD_INSECURE
          valueFrom:
            configMapKeyRef:
              key: argocd.insecure
              name: argocd-image-updater-config
              optional: true
        - name: ARGOCD_PLAINTEXT
          valueFrom:
            configMapKeyRef:
              key: argocd.plaintext
              name: argocd-image-updater-config
              optional: true
        - name: ARGOCD_TOKEN
          valueFrom:
            secretKeyRef:
              key: argocd.token
              name: argocd-image-updater-secret
              optional: true
        - name: IMAGE_UPDATER_LOGLEVEL
          valueFrom:
            configMapKeyRef:
              key: log.level
              name: argocd-image-updater-config
              optional: true
        - name: GIT_COMMIT_USER
          valueFrom:
            configMapKeyRef:
              key: git.user
              name: argocd-image-updater-config
              optional: true
        - name: GIT_COMMIT_EMAIL
          valueFrom:
            configMapKeyRef:
              key: git.email
              name: argocd-image-updater-config
              optional: true
        - name: IMAGE_UPDATER_KUBE_EVENTS
          valueFrom:
            configMapKeyRef:
              key: kube.events
              name: argocd-image-updater-config
              optional: true
        image: quay.io/argoprojlabs/argocd-image-updater:latest
        imagePullPolicy: Always
        livenessProbe:
          httpGet:
            path: /healthz
            port: 8080
          initialDelaySeconds: 3
          periodSeconds: 30
        name: argocd-image-updater
        ports:
        - containerPort: 8080
        readinessProbe:
          httpGet:
            path: /healthz
            port: 8080
          initialDelaySeconds: 3
          periodSeconds: 30
        volumeMounts:
        - mountPath: /app/config
          name: image-updater-conf
        - mountPath: /app/config/ssh
          name: ssh-known-hosts
        - mountPath: /app/.ssh
          name: ssh-config
        - mountPath: /app/scripts
          name: ecr-login-script
      serviceAccountName: argocd-image-updater
      volumes:
      - configMap:
          items:
          - key: registries.conf
            path: registries.conf
          - key: git.commit-message-template
            path: commit.template
          name: argocd-image-updater-config
          optional: true
        name: image-updater-conf
      - configMap:
          name: argocd-ssh-known-hosts-cm
          optional: true
        name: ssh-known-hosts
      - configMap:
          name: argocd-image-updater-ssh-config
          optional: true
        name: ssh-config
      - configMap:
          defaultMode: 0755
          items:
          - key: ecr-login.sh
            path: ecr-login.sh
          name: argocd-image-updater-config
          optional: true
        name: ecr-login-script

ArgoCD Image Updaterのデプロイ

上記修正を行ったマニフェストファイルをデプロイします。

$ kubectl apply -n argocd -f argocd-image-updater-manifest.yaml
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
導入後の動作確認

ArgoCD Image Updaterをデプロイ後、作成したPodからECRにアクセスし、コンテナイメージを検索できるかを確認します。ArgoCD Image UpdaterはCLIも用意されており、作成したPodからコマンドを実行することで、簡易的な動作確認をとることができます。

$ kubectl exec -it argocd-image-updater-ddbf7df64-prgk6 -n argocd -- argocd-image-updater test <AWS account id>.dkr.ecr.ap-northeast-1.amazonaws.com/argocd-image-updater-test --credentials ext:/app/scripts/ecr-login.sh --registries-conf-path /app/config/registries.conf
DEBU[0000] Creating in-cluster Kubernetes client
INFO[0000] retrieving information about image            image_alias= image_name=<AWS account id>.dkr.ecr.ap-northeast-1.amazonaws.com/argocd-image-updater-test registry_url=<AWS account id>.dkr.ecr.ap-northeast-1.amazonaws.com
DEBU[0000] rate limiting is disabled                     prefix=<AWS account id>.dkr.ecr.ap-northeast-1.amazonaws.com registry="https://<AWS account id>.dkr.ecr.ap-northeast-1.amazonaws.com"
INFO[0000] Loaded 1 registry configurations from /app/config/registries.conf
INFO[0000] /app/scripts/ecr-login.sh                     dir= execID=2d322
INFO[0003] /app/scripts/ecr-login.sh                     dir= execID=d8ba2
INFO[0004] Fetching available tags and metadata from registry  application=test image_alias= image_name=<AWS account id>.dkr.ecr.ap-northeast-1.amazonaws.com/argocd-image-updater-test registry_url=<AWS account id>.dkr.ecr.ap-northeast-1.amazonaws.com
INFO[0004] Found 3 tags in registry                      application=test image_alias= image_name=<AWS account id>.dkr.ecr.ap-northeast-1.amazonaws.com/argocd-image-updater-test registry_url=<AWS account id>.dkr.ecr.ap-northeast-1.amazonaws.com
DEBU[0004] found 3 from 3 tags eligible for consideration  image=<AWS account id>.dkr.ecr.ap-northeast-1.amazonaws.com/argocd-image-updater-test
INFO[0004] latest image according to constraint is <AWS account id>.dkr.ecr.ap-northeast-1.amazonaws.com/argocd-image-updater-test:20221112-5cd2a03  application=test image_alias= image_name=<AWS account id>.dkr.ecr.ap-northeast-1.amazonaws.com/argocd-image-updater-test registry_url=<AWS account id>.dkr.ecr.ap-northeast-1.amazonaws.com

※参考リンク:

ArgoCD Image Updaterの動作確認

ここからArgoCD Image Updaterを使ってコンテイメージの更新を行います。

コンテナイメージの更新方法

ArgoCD Image Updaterによるイメージの更新方法は大きく2つあり、動作中の Application リソースに直接編集を加える ( write-back-method: argocd ) か、GitHubリポジトリに向けてイメージを修正するコミットを作成する ( write-back-method: git ) かになります。

※参考リンク:

write-back-method: argocd

argocd による更新は、ArgoCD APIを通してパラメータの上書きを行います。デフォルトではこちらの方法が設定されます。

この方法はArgoCD Web UIやCLIによってアプリケーションを更新する場合に適している方法です。Image Updaterによる変更はマニフェストファイル等には保存されず、既存のApplicationを削除し再作成した場合、Image Updaterによる更新は反映されません。

こちらの方法では、ソースコードリポジトリに定義されたマニフェストとは異なる定義のアプリケーションが動作することになるため、GitOpsの原則からは外れた使い方となりますが、プロジェクトによってはこちらを採用するケースもあるようです。

write-back-method: git

git による更新は、パラメータの上書きのためにgitを利用します。この方法を有効にすると、ターゲットブランチ配下で .argocd-source-<appName>.yaml というファイルが作成され、更新するイメージの名称が更新されます。これにより、Image Updaterによるパラメータの上書きがgitに保存され、Gitopsの原則に従う形で更新することが可能となります。

動作確認: argocd

まずは argocd のほうを試します。事前に以下のようにApplicationファイルを修正します。

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: app
  namespace: argocd
  # 以下のannotationsを追加
  annotations:
    argocd-image-updater.argoproj.io/write-back-method: argocd
    argocd-image-updater.argoproj.io/image-list: app=<AWS account id>.dkr.ecr.ap-northeast-1.amazonaws.com/argocd-image-updater-test
    argocd-image-updater.argoproj.io/app.update-strategy: latest
spec:
  project: default
  source:
    repoURL: https://github.com/fy0323/argocd-image-updater-test.git
    targetRevision: main
    path: manifest/overlays/dev/
  destination:
    server: https://kubernetes.default.svc
    namespace: default

metadata.annotations に追加した項目について補足です。

  • argocd-image-updater.argoproj.io/write-back-method : Updaterによるイメージの上書き方法を指定します。 argocd / git のいずれかを指定可能です。
  • argocd-image-updater.argoproj.io/image-list : ターゲットとなるコンテナレジストリを指定します。ここではコンテナレジストリ名のエイリアスを設定することができます。今回は app という名称でエイリアスを設定します。
  • argocd-image-updater.argoproj.io/app.update-strategy : アップデートの対象とするコンテナイメージをどう特定するか定義します。これは image-list で設定したレジストリに対して設定し、 semver / latest / digest などの方法を指定できます。今回はレジストリ内で作成された最新バージョンのイメージを対象とする latest を指定してます。

※参考リンク:

上記マニフェストファイルをデプロイします。

$ kubectl apply -f argocd-image-updater-test/application.yaml
application.argoproj.io/app configured

この状態でアプリケーションのほうを修正し、新しいコンテナイメージを作成します。しばらくすると、Applicationの状態が OutOfSync となり、差分ができていることが確認できます。

$ argocd app list
NAME  CLUSTER                         NAMESPACE  PROJECT  STATUS     HEALTH   SYNCPOLICY  CONDITIONS  REPO                                                     PATH                    TARGET
app   https://kubernetes.default.svc  default    default  OutOfSync  Healthy  <none>      <none>      https://github.com/fy0323/argocd-image-updater-test.git  manifest/overlays/dev/  main

ここからSyncをしてPodを更新すると、アプリケーションに修正内容が反映されたことが確認できます。

$ argocd app sync app
TIMESTAMP                  GROUP        KIND   NAMESPACE                  NAME    STATUS    HEALTH        HOOK  MESSAGE
2022-11-15T16:58:00+09:00            Service     default            sample-app    Synced   Healthy
2022-11-15T16:58:00+09:00   apps  Deployment     default            sample-app  OutOfSync  Healthy
2022-11-15T16:58:00+09:00   apps  Deployment     default            sample-app  OutOfSync  Healthy              deployment.apps/sample-app configured
2022-11-15T16:58:00+09:00            Service     default            sample-app    Synced   Healthy              service/sample-app unchanged
2022-11-15T16:58:00+09:00   apps  Deployment     default            sample-app    Synced  Progressing              deployment.apps/sample-app configured

(以降割愛)

$ kubectl exec -it nginx -- curl http://sample-app
<html><body>Hello, Argocd Image Updater 20221115-01</body></html>

参考: イメージタグ更新時のArgoCD Image Updaterログ

$ kubectl logs -n argocd argocd-image-updater-ddbf7df64-prgk6 -f

(一部抜粋)

time="2022-11-15T07:54:51Z" level=info msg="Starting image update cycle, considering 1 annotated application(s) for update"
time="2022-11-15T07:54:51Z" level=warning msg="\"latest\" strategy has been renamed to \"newest-build\". Please switch to the new convention as support for the old naming convention will be removed in future versions." image_alias=app image_name=<AWS account id>.dkr.ecr.ap-northeast-1.amazonaws.com/argocd-image-updater-test registry_url=<AWS account id>.dkr.ecr.ap-northeast-1.amazonaws.com
time="2022-11-15T07:54:51Z" level=info msg="Setting new image to <AWS account id>.dkr.ecr.ap-northeast-1.amazonaws.com/argocd-image-updater-test:20221115-a1fbb26" alias=app application=app image_name=argocd-image-updater-test image_tag=20221115-5938771 registry=<AWS account id>.dkr.ecr.ap-northeast-1.amazonaws.com
time="2022-11-15T07:54:51Z" level=info msg="Successfully updated image '<AWS account id>.dkr.ecr.ap-northeast-1.amazonaws.com/argocd-image-updater-test:20221115-5938771' to '<AWS account id>.dkr.ecr.ap-northeast-1.amazonaws.com/argocd-image-updater-test:20221115-a1fbb26', but pending spec update (dry run=false)" alias=app application=app image_name=argocd-image-updater-test image_tag=20221115-5938771 registry=<AWS account id>.dkr.ecr.ap-northeast-1.amazonaws.com
time="2022-11-15T07:54:51Z" level=info msg="Committing 1 parameter update(s) for application app" application=app
time="2022-11-15T07:54:52Z" level=info msg="Successfully updated the live application spec" application=app
time="2022-11-15T07:54:52Z" level=info msg="Processing results: applications=1 images_considered=1 images_skipped=0 images_updated=1 errors=0"

動作確認: git

続いて git のほうも試します。今回はApplicationマニフェストargocd-image-updater.argoproj.io/write-back-method の修正を行い、再度デプロイします。

$ kubectl apply -f argocd-image-updater-test/application.yaml
application.argoproj.io/app configured

$ kubectl describe app -n argocd app
Name:         app
Namespace:    argocd
Labels:       <none>
Annotations:  argocd-image-updater.argoproj.io/app.update-strategy: latest
              argocd-image-updater.argoproj.io/image-list: app=<AWS account id>.dkr.ecr.ap-northeast-1.amazonaws.com/argocd-image-updater-test
              argocd-image-updater.argoproj.io/write-back-method: git
API Version:  argoproj.io/v1alpha1
Kind:         Application

(以下割愛)

この状態でアプリケーションのほうを修正し、新しいコンテナイメージを作成します。しばらくすると、GitHubのほうに新しいファイルが作られていることが確認できます。

$ git pull origin main
$ ls -la manifest/overlays/dev/
total 0
drwxr-xr-x 1 testadm testadm 4096 Nov 15 17:33 .
drwxr-xr-x 1 testadm testadm 4096 Nov 12 10:08 ..
-rw-r--r-- 1 testadm testadm  118 Nov 15 17:33 .argocd-source-app.yaml # 新規追加されたファイル
-rw-r--r-- 1 testadm testadm   52 Nov 12 10:08 kustomization.yaml

$ cat .argocd-source-app.yaml
kustomize:
  images:
  - <AWS account id>.dkr.ecr.ap-northeast-1.amazonaws.com/argocd-image-updater-test:20221115-7f8b2c9

またApplicationの状態も OutOfSync となり、差分ができていることが確認できます。これをSyncすることで、アプリケーションへの修正が反映されたことが確認できます。

$ argocd app list
NAME  CLUSTER                         NAMESPACE  PROJECT  STATUS     HEALTH   SYNCPOLICY  CONDITIONS  REPO                                                     PATH                    TARGET
app   https://kubernetes.default.svc  default    default  OutOfSync  Healthy  <none>      <none>      https://github.com/fy0323/argocd-image-updater-test.git  manifest/overlays/dev/  main

$ argocd app sync app
TIMESTAMP                  GROUP        KIND   NAMESPACE                  NAME    STATUS    HEALTH        HOOK  MESSAGE
2022-11-15T17:12:27+09:00            Service     default            sample-app    Synced   Healthy
2022-11-15T17:12:27+09:00   apps  Deployment     default            sample-app  OutOfSync  Healthy
2022-11-15T17:12:27+09:00            Service     default            sample-app    Synced   Healthy              service/sample-app unchanged
2022-11-15T17:12:27+09:00   apps  Deployment     default            sample-app  OutOfSync  Healthy              deployment.apps/sample-app configured
2022-11-15T17:12:27+09:00   apps  Deployment     default            sample-app    Synced  Progressing              deployment.apps/sample-app configured

(以降割愛)

$ kubectl get pods
NAME                          READY   STATUS    RESTARTS   AGE
nginx                         1/1     Running   0          65m
sample-app-74b49d7856-ln75h   1/1     Running   0          30s

$ kubectl exec -it nginx -- curl http://sample-app
<html><body>Hello, Argocd Image Updater 20221115-02</body></html>

なお、 git 方式の場合、以降はイメージタグは .argocd-source-app.yaml を参照します。そのため、git 方式でImage Updaterを有効にすると、 例えば手動でマニフェストファイル (今回なら deployment.yaml ) のイメージタグを更新しても、起動するPodには反映されません。

参考: イメージタグ更新時のArgoCD Image Updaterログ

$ kubectl logs -n argocd argocd-image-updater-ddbf7df64-prgk6 -f

(一部抜粋)

time="2022-11-15T08:06:52Z" level=info msg="Starting image update cycle, considering 1 annotated application(s) for update"
time="2022-11-15T08:06:52Z" level=warning msg="\"latest\" strategy has been renamed to \"newest-build\". Please switch to the new convention as support for the old naming convention will be removed in future versions." image_alias=app image_name=<AWS account id>.dkr.ecr.ap-northeast-1.amazonaws.com/argocd-image-updater-test registry_url=<AWS account id>.dkr.ecr.ap-northeast-1.amazonaws.com
time="2022-11-15T08:06:53Z" level=info msg="Setting new image to <AWS account id>.dkr.ecr.ap-northeast-1.amazonaws.com/argocd-image-updater-test:20221115-7f8b2c9" alias=app application=app image_name=argocd-image-updater-test image_tag=20221115-a1fbb26 registry=<AWS account id>.dkr.ecr.ap-northeast-1.amazonaws.com
time="2022-11-15T08:06:53Z" level=info msg="Successfully updated image '<AWS account id>.dkr.ecr.ap-northeast-1.amazonaws.com/argocd-image-updater-test:20221115-a1fbb26' to '<AWS account id>.dkr.ecr.ap-northeast-1.amazonaws.com/argocd-image-updater-test:20221115-7f8b2c9', but pending spec update (dry run=false)" alias=app application=app image_name=argocd-image-updater-test image_tag=20221115-a1fbb26 registry=<AWS account id>.dkr.ecr.ap-northeast-1.amazonaws.com
time="2022-11-15T08:06:53Z" level=info msg="Committing 1 parameter update(s) for application app" application=app
time="2022-11-15T08:06:53Z" level=info msg="Starting configmap/secret informers"
time="2022-11-15T08:06:53Z" level=info msg="Configmap/secret informer synced"
time="2022-11-15T08:06:53Z" level=info msg="Initializing https://github.com/fy0323/argocd-image-updater-test.git to /tmp/git-app2064956039"
time="2022-11-15T08:06:53Z" level=info msg="rm -rf /tmp/git-app2064956039" dir= execID=839c5
time="2022-11-15T08:06:53Z" level=info msg="secrets informer cancelled"
time="2022-11-15T08:06:53Z" level=info msg="configmap informer cancelled"
time="2022-11-15T08:06:53Z" level=info msg=Trace args="[rm -rf /tmp/git-app2064956039]" dir= operation_name="exec rm" time_ms=2.52375
time="2022-11-15T08:06:53Z" level=info msg="git fetch origin --tags --force" dir=/tmp/git-app2064956039 execID=1bda6
time="2022-11-15T08:06:54Z" level=info msg=Trace args="[git fetch origin --tags --force]" dir=/tmp/git-app2064956039 operation_name="exec git" time_ms=926.411977
time="2022-11-15T08:06:54Z" level=info msg="git config user.name argocd-image-updater" dir=/tmp/git-app2064956039 execID=82001
time="2022-11-15T08:06:54Z" level=info msg=Trace args="[git config user.name argocd-image-updater]" dir=/tmp/git-app2064956039 operation_name="exec git" time_ms=5.418636
time="2022-11-15T08:06:54Z" level=info msg="git config user.email noreply@argoproj.io" dir=/tmp/git-app2064956039 execID=87e8b
time="2022-11-15T08:06:54Z" level=info msg=Trace args="[git config user.email noreply@argoproj.io]" dir=/tmp/git-app2064956039 operation_name="exec git" time_ms=5.845921
time="2022-11-15T08:06:54Z" level=info msg="git checkout --force main" dir=/tmp/git-app2064956039 execID=29d9f
time="2022-11-15T08:06:54Z" level=info msg=Trace args="[git checkout --force main]" dir=/tmp/git-app2064956039 operation_name="exec git" time_ms=10.429219
time="2022-11-15T08:06:54Z" level=info msg="git clean -fdx" dir=/tmp/git-app2064956039 execID=434ff
time="2022-11-15T08:06:54Z" level=info msg=Trace args="[git clean -fdx]" dir=/tmp/git-app2064956039 operation_name="exec git" time_ms=6.051158
time="2022-11-15T08:06:54Z" level=info msg="git add /tmp/git-app2064956039/manifest/overlays/dev/.argocd-source-app.yaml" dir=/tmp/git-app2064956039 execID=b8197
time="2022-11-15T08:06:54Z" level=info msg=Trace args="[git add /tmp/git-app2064956039/manifest/overlays/dev/.argocd-source-app.yaml]" dir=/tmp/git-app2064956039 operation_name="exec git" time_ms=11.407465
time="2022-11-15T08:06:54Z" level=info msg="git commit -a -F /tmp/image-updater-commit-msg2947554435" dir=/tmp/git-app2064956039 execID=07c3b
time="2022-11-15T08:06:54Z" level=info msg=Trace args="[git commit -a -F /tmp/image-updater-commit-msg2947554435]" dir=/tmp/git-app2064956039 operation_name="exec git" time_ms=32.495799
time="2022-11-15T08:06:54Z" level=info msg="git push origin main" dir=/tmp/git-app2064956039 execID=068e8
time="2022-11-15T08:06:55Z" level=info msg=Trace args="[git push origin main]" dir=/tmp/git-app2064956039 operation_name="exec git" time_ms=1042.2358430000002
time="2022-11-15T08:06:55Z" level=info msg="Successfully updated the live application spec" application=app
time="2022-11-15T08:06:55Z" level=info msg="Processing results: applications=1 images_considered=1 images_skipped=0 images_updated=1 errors=0"