ArgoCD ApplicationSetによるApplication管理の効率化

 はじめに

『スタディサプリENGLISH』SREグループの巻田です。
最近、Kubernetes上でCronJobを管理するためにArgoCD ApplicationSet(1)を導入したので、それに関して紹介します!

 

以前の記事(2)でも紹介した通り、従来から『スタディサプリENGLISH』ではArgoCDを用いてKubernetesリソースの管理を行ってきました。

しかし、CronJobの数が増加し、管理が煩雑になるという問題が発生しました。そのため、manifestの整理と管理の簡略化を図るために、ArgoCD ApplicationSetを導入しました。

 

ArgoCD ApplicationSetとは

ArgoCDはApplicationの単位でKubernetesのリソースを管理します。

Applicationは他のKubernetesリソースと同様にYAML形式で記述することができますが、多くのApplicationを作成するにはその数だけYAMLを書く必要があります。

これは非常に手間がかかるだけでなく作業ミスも発生しやすい作業です。

 

ApplicationSetを使うとApplication間で共通している部分をテンプレート化することで多くのアプリケーションの生成を容易にすることができます。

 

ArgoCD ApplicationSetの使い方

 

ArgoCDの v2.3.0 以降がすでに動作している環境であればArgoCD ApplicationSetを使うために必要なArgoCD ApplicationSet Controllerも一緒にインストールされているため追加で何かインストールを行う必要はありません。

 

ApplicationSetには大きく分けてtemplategeneratorの2つの要素があります。

 

templateは生成するApplicationの雛形となる部分で、内容としてはArgoCD Applicationとほぼ同一です。

異なっている点としては {{ .values.name }} のような感じで各Applicationごとに異なる値を入れるためのプレースホルダーを入れられる点が挙げられます。

テンプレート内でのプレースホルダーの補完には設定によりgo templateの機能を使うこともできるためかなり柔軟に構成できます。

 

generatorとはtemplatedで使用するパラメーターを生成するためのものです。

パラメーターを各Application向けに手動で設定するList Generator(3)や、Git Repositoryのディレクトリ構造に応じてパラメーターを生成するGit Generator(4)をはじめとして様々なジェネレーターが用意されています。

ジェネレーターは色々と用意されているので公式のドキュメント(5)を見てみてください。

 

以下にList Generatorを使用したApplicationSetの例を示します。

 

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: guestbook
  namespace: argocd
spec:
  goTemplate: true
  goTemplateOptions: ["missingkey=error"]
  generators:
  - list:
      elements:
      - app: app1
      - app: app2
  template:
    metadata:
      name: '{{.app}}'
    spec:
      project: 'default'
      source:
        repoURL: https://example.com/example.git
        targetRevision: master
        path: apps/{{.app}}
      destination:
        server: 'https://kubernetes.default.svc'
        namespace: default

 

generatorsによって生成されたパラメーターを使ってtemplateからApplicationを生成することによりapp1app2の2つのApplicationが生成されます。

 

『スタディサプリENGLISH』 における ArgoCD ApplicationSet の活用

『スタディサプリENGLISH』においては多数のバッチJobをKubernetesのCronJobとして実行しています。

従来はそれらのCronJobごとにArgoCD Applicationを作成して、Kustomizeを用いてmanifestを生成するように設定していました。

 

しかし、それぞれのCronJobに関するArgoCD Applicationはターゲットとして指定するディレクトリとApplication名以外はほぼ同じような内容であるため、これらをApplicationSetを使用して共通化しています。

 

また、ApplicationSetを管理するためのApplicationも作成して、これだけを手動でapplyする運用にしています。
以下の図が大まかな構造です。

先述のApplicationSetを管理するのが一番上にあるbatch-jobsというApplicationで、その設定によってビルドされたマニフェストに含まれるApplicationSetのリソース(上から2段目)が作成されます。

そのApplicationSetによってそれぞれのApplication(上から3段目)が作成され、それらのApplicationによってビルドされたマニフェストによりCronJobなどのリソース(一番下の段)が作成されます。

 

 

実際に使っているApplicationSetのYAMLは以下です。 (多少改変しています)

 

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: batch-jobs
  namespace: argocd
spec:
  generators:
    - git:
        directories:
          - path: path/to/manifests/jobs/*/job/overlays/production # このパターンにマッチするディレクトリを列挙する
        repoURL: 'https://example.com/example.git'
        revision: master
        values: # テンプレートとして使う変数を定義する
          dir: '{{ .path.path }}' 
          name: '{{index .path.segments 4}}' # path を / で区切った4番目 (0-index) を指定する
  goTemplate: true
  goTemplateOptions:
    - missingkey=error
  template:
    metadata:
      name: '{{ .values.name }}'
      namespace: argocd
    spec:
      destination:
        namespace: cronjob
        server: 'https://kubernetes.default.svc'
      project: job
      source:
        path: '{{ .values.dir }}'
        repoURL: 'https://example.com/example.git'
        targetRevision: master
      syncPolicy:
        automated:
          selfHeal: true

 

これにより、指定したGit Repositoryの特定のブランチ、タグに含まれる path/to/manifests/jobs/*/job/overlays/production のパスにマッチするディレクトリを自動的に探索するようになります。

探索した結果として出てきたディレクトリの数だけApplicationが生成されるようになります。

 

ArgoCD Image Updaterとの共存

『スタディサプリENGLISH』では開発環境においてArgoCD Image Updater(6)を導入しています。

ArgoCD Image Updaterとは、コンテナレジストリにプッシュされたイメージのタグを定期的に確認して、条件に合う最も新しいバージョンのイメージを自動的に設定するソフトウェアです。

Kustomizeを参照しているArgoCD Applicationと組み合わせて使用する場合はArgoCD Applicationの設定を一部変更します。

 

しかし、この変更をApplicationSet Controllerが即座に上書きしてしまうため、以下のようにignoreApplicationDifferencesの設定を追加してこの部分の変更を無視するようにしています。

 

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  ...
spec:
  ignoreApplicationDifferences:
    - jqPathExpressions:
        - .spec.source.kustomize.images
  template: ...
  generators: ...

 

まとめ

ArgoCDのApplicationが増えてくるとそれらの管理が大変になってきます。

ArgoCD ApplicationSetの導入によって同じようなApplicationを自動生成して管理を効率化することができました。

似たような課題感をお持ちの方は是非試してみてください。

 

 

脚注

1.
https://argo-cd.readthedocs.io/en/stable/operator-manual/applicationset/
2.
https://techblog.recruit.co.jp/article-634/
3.
https://argo-cd.readthedocs.io/en/stable/operator-manual/applicationset/Generators-List/
4.
https://argo-cd.readthedocs.io/en/stable/operator-manual/applicationset/Generators-Git/
5.
https://argo-cd.readthedocs.io/en/stable/operator-manual/applicationset/Generators/
6.
https://argocd-image-updater.readthedocs.io/en/stable/