TT Lab
はじめる
学ぶ 学習パス コース

GitOpsとArgo CD

画面のボタンはどこから来るのか

TT Labで続きを見る

一言でいうと

Argo CDのリソースアクションは、argocd-cmに書いた2つのLuaの断片で作られます。何を見せるかを決めるdiscovery.luaと、何を変えるかを決めるaction.luaです。argocd admin settings resource-overridesで、サーバーなしで試せます。

なぜボタンが必要だったのか

GitOpsの約束は「クラスターを変える道は、リポジトリ1つだけ」です。ところが現場では、この約束は完全には守られません。設定がキャッシュに入り込んでいて、Podを一度立ち上げ直す必要があるとき、デプロイを少し止める必要があるとき、障害中に1つだけ増やす必要があるときがあります。こうしたことには共通点があります。リポジトリに書く値が変わるのではありません。コミットするものがないのにコミットを要求すると、人々は結局kubectlに行きます。

リソースアクションは、この隙間を埋めます。残るいくつかをあらかじめ定義された変換にして画面のボタンとして出し、そのボタンを押せる人をRBACで決め、誰が押したかを記録に残します。任意のkubectlの代わりに、決まったアクションだけが可能になるというのが核心です。

どう動くのか

argocd-cmの1つのキーに、2つの断片が入ります。

resource.customizations.actions.example.com_Widget: |
  discovery.lua: |
    actions = {}
    actions["pause"] = {}
    actions["resume"] = {["disabled"] = true}
    if obj.spec ~= nil and obj.spec.paused == true then
      actions["pause"] = {["disabled"] = true}
      actions["resume"] = {}
    end
    return actions
  definitions:
  - name: pause
    action.lua: |
      obj.spec.paused = true
      return obj

discovery.luaは、このリソースにどのボタンを見せるかを決めます。アクション名をキーにしたテーブルを返し、値にdisabledを真として入れれば、そのボタンがグレーアウトされます。ここで重要な設計上の決定が1つあります。状態を見てボタンを有効にしたり無効にしたりする判断が、画面ではなくこのコードにあることです。すでに止まっているものをまた止めるボタンが、そもそも押せなくなります。

definitionsのaction.luaは、リソースを受け取って変更されたリソースを返します。新しいオブジェクトを作るのではなく、入ってきたobjを直してreturnする方式なので、意図しないフィールドも一緒に触れやすいです。そのため、run-actionが結果をまるごと見せず、変わったフィールドだけをdiffで見せることが重要です。アクションが手を付けた場所が、一目でわかります。

Luaの側でよく引っかかることが2つあります。1つ目は、配列の添字が1から始まることです。最初のコンテナはcontainers[1]です。2つ目は、存在しないフィールドを読むとnilで、nilに算術演算をするとスクリプトが落ちることです。値を読んで計算するアクションには、確認が必要です。

最後に、このCLIの性質を1つ知っておく必要があります。list-actionsとrun-actionは、argocd-cmだけを読みます。Deploymentのrestartのように、Argo CDの中に入っている組み込みのアクションは、このコマンドには出てこず、設定がなければ「アクションが設定されていない」と答えます。画面と違うからと慌てることはなく、このコマンドが自分で書いたルールだけを試すという意味だと読めばよいです。

現場での姿

アクションを導入したチームが最初に出会う誤解は、「ボタンを押せば直る」というものです。アクションは、クラスターのオブジェクトを変えるだけで、リポジトリは変えません。自動同期と自己修復が有効なら、次の調整で元に戻ります。そのため、アクションは元に戻ってもかまわないことにだけ使います。立ち上げ直しが代表的です。元に戻ってはいけない変更は、やはりコミットで行う必要があります。

2つ目は、静かな故障です。Operatorをバージョンアップしたらフィールド名が変わったのに、action.luaはそのままです。ボタンは相変わらず見えていて、押しても何も起きないか、見当違いの場所に値を書き込みます。エラーが出ないほうが、より危険です。そのため、アクションにもサンプルと期待値を表にまとめておく習慣が必要です。このラボの最後のステップがそれです。

このラボ環境の限界

ラボのPodには、Argo CDコントローラーも画面もありません。ボタンを実際に押してみたり、アクションの権限をRBACで止めて拒否されるのを見たりすることは、ここではできません。その代わり、discovery.luaとaction.luaを実際に実行するコードがCLIの中にあるので、どのボタンが見えて何が変わるかは、まったく同じ結果で確認できます。そして、アクションが作った変更は、kwokクラスターに直接上げて、結果を目で見ます。

次のラボですること

空のConfigMapで、このコマンドが何を読むかをまず確認します。そのあと、Widgetにpauseを作り、状態に応じてresumeと交互にグレーアウトさせ、値を読んで計算するscale-upを加えます。組み込みの種類であるDeploymentにもアクションを付けてイメージを固定し、その結果をkwokクラスターに適用して確認します。最後に、アクションがすることを表にまとめて、一度に検査するスクリプトを作ります。