こんにちは
- ArgoCD を使用している
- Kustomizeでリソースを管理している
- ArgoCD Resource Hooksで同じ Job を複数のリソースで使用したい
2020/11/08 現在で上記の条件下に存在する問題の、詰まり bility がかなり高かったので記録として残しておきます
シンプルに実装する
ArgoCD Resource Hooks は ArcdCD の sync の特定のタイミング(Sync 前、中、Sync 成功時、Sync 失敗時)に Job を実行できる機能です。
条件 3 の「同じ Job」とは同一の yaml から生成される Job を示しています。 Kustomize を利用する事で「yaml を読み込む」という事ができるため、同一の yaml から生成される Job を複数のリソースの Resource Hooks に利用すると言った事が可能です。(DRY にかけて良いですね)
ここで発生する問題点としては、「同一タイミングで同一 namespace 内で複数の Resource Hooks が発火したときに名前が衝突して実行に失敗する」という事です。 同じ yaml から生成される Job はそのままだと当然同じ/metadata/name を持ちますのでこう言った事が起こってしまいます。
そこで使用するのがgenerateName
です。これは kubernetes の機能でリソースの生成時にランダムな名前をつけてくれます。
generated value - Kubernetes API Concepts
name: if generateName is set, name will have a unique random name
Job の/metadata/name の代わりに/metadata/generateName を使用する事で先程のリソースの名前の衝突を防ぐ事ができますね。 実際に ArgoCD Resource Hooks の公式のページのサンプルには/metadata/generateName が使用されています
これで解決!ですね
ところがどっこい問題点
ここで発生する問題は「kustomize が/metadata/name を持たないリソースをうまく扱ってくれない」というものです。以下に issue が上がっています。
Unable to handle 2+ resources kinds using generateName: #586
issue の通りですが、kustomization.yaml
にてresources
句を使用して、/metadata/generateName を使用したリソースを読み込もうとすると「/metadata/name が無いぜ!」と怒られるという問題です。
/metadata/generateName のエラーを上手く避ける作戦で実装する
/metadata/generateName のエラーを上手く避ける作戦とは、patchesJSON6902 を使用して/metadata/name を途中で/metadata/generateName に書き換えるというものです。
これによって先程の resources で読み込む際のエラーを回避する事ができます。この作戦は上記の issue のディスカッション内にも記載がありますが、以下に紹介されている作戦です。
Support generateName for application resources
これで解決!ですね
ところがどっこい問題点
次に発生する問題は patchesJson6902 を使用した特定の状況でエラーが発生するというものです。
patchesJson6902 with operation “move” fail under certain circumstances.
- use patchesJson6902 with operation move
- move /metadata/name
- patchesJson6902 has several targets
- several targets has same group, target, and kind When use the above resource from other kustomization.yaml with resources statements, the following errors occur
僕が挙げた issue ですが解決される事なく close されました()、なので未解決です
これによってまたもや失敗します、ちなみに似たようなものに patches というものがありますが patchesJSON6902 の代わりに patches を使用しても同様の問題が発生します
さらに上記エラーの回避を試みる
上記 issue には回避の方法があります、注目すべきはここです
When use the above resource from other kustomization.yaml with resources statements, the following errors occur
resources 句で読み込もうとする際にのみ発生するという点です。 そのため、DRY 原則からは少し外れますが、Job を読み込む各リソースの kustomization.yaml 側で patchesJSON6902 を利用して/metadata/name を/metadata/generateName に置き換えをします resource 句で読み込んだ段階では/metadata/name なので一つ目の issue をクリア、そして読み込んだ後に patchesJSON6902 を使用するので二つ目の issue をクリアという魂胆です
また、この作戦のめんどくさいポイントとしては、patch のためのファイルを current ディレクトリ以下に置かなければいけないという点です。 そのため、例えば 300 リソースに Job を登録したい場合、kustomization.yaml を 300 リソース分変更して、さらに patchesJSON6902 用の patch ファイルを 300 リソース分おいて回る必要があります。(深いため息)
ところがどすこい問題点
Suffix generateName is always 62135596800 #181
何と ArgoCD 側で generateName の生成をミスっていて全てのリソースの名前がsome-operation-{git_hash}-presync-62135596800
という名前になってしまうという問題です。(本来はsome-operation-{git_hash}-presync-{suffix}
となるはず)
最終的な実装
妥協に妥協を重ねて結局以下のように実装を行いました。
- Job 側はしょうがないので/metadata/name を使用
- Job を読み込む各リソースの kustomization.yaml 側で patchesJSON6902 を利用して/metadata/name の値を namespace 内でコンフリクトしないように頑張って uniq にする
終わりに
この数々の issue に先週 1 週間を潰しました。偶然 ArgoCD と kustomize がバグが絶妙に噛み合って地獄のコンボとなっていました。