Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Step5: app-of-apps

Step4 までは Application リソースは手動で適用していました。しかし、この状態だと Application 自体に対する更新 (例えば TLA を追加したり、TLA に渡す値を変更したりなど) は手動で argocd app create --upsert を打つ必要があり、GitOps の理念に反してしまいます。Application のマニフェストも Argo CD に管理させるにはどうしたらよいでしょうか?

実は Application リソースも単なる Kubernetes のリソースであり、Argo CD によってデプロイすることができます。つまり、Application を作成する Application を作ることができます。この考え方を app-of-apps と言います。

app-of-apps の考え方を採用すると、Kubernetes クラスタごとにひとつだけ手動で Application を適用すればよくなります。他の Application は、この Application によって自動的にデプロイされます。

他の Application リソースをデプロイする Application リソースは慣習的に *-apps と名付けられます。

大規模な Kubernetes クラスタの場合、app-of-apps の階層を多段にすることがあります。例えば サイボウズの Kubernetes 環境では以下のように Application が3層構造になっています(※)。それぞれの Application は一個下の階層の Application をデプロイし、最下層の Application は Deployment や Service といった具体的なリソースをデプロイします。

Application何個あるのか管理者
root-appKubernetes クラスタごとにひとつKubernetes クラスタの管理者
*-apps(Kubernetes cluster, チーム) ごとにひとつそのチームに属する人
サービスごとの Application(Kubernetes cluster, 環境, サービス) ごとにひとつ同上

※ 実際にはもっと複雑ですが、このハンズオンではかなり単純化して説明しています。

app-of-apps を導入する

それでは hello-server も app-of-apps に移行してみましょう。このハンズオンでは単純化のために app-of-apps の階層は2層にします。つまり、root-app が直接 {dev,staging,prod}-hello-server という Application 群をデプロイする構成にします。

まず、Step4 で作ったリソースを削除して環境をキレイにしておきます。

argocd app delete dev-hello-server
argocd app delete staging-hello-server
argocd app delete prod-hello-server

次に、hello-apps リポジトリ側の準備をします。まず、ディレクトリレイアウトを少し変えましょう。hello-apps リポジトリのトップに hello-server ディレクトリを作成し、既存のファイルをすべてその下に移動させます。

mkdir hello-server
git mv dev prod staging hello-server.libsonnet hello-server

次にルートとなる Application を作ります。このハンズオンでは一つの Kubernetes クラスタの中にすべての環境を収めているため、ルートとなる Application はひとつで十分です。

hello-apps リポジトリのトップに root-app というディレクトリを作成し、その下に root-app.yaml という名前で Application のマニフェストを配置します。

mkdir root-app
editor root-app/root-app.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: root-app
  namespace: argocd
  finalizers:
  - resources-finalizer.argocd.argoproj.io
spec:
  project: default
  source:
    # 自分のリポジトリのURLに合わせて書き換えてください
    # hello-server ではなく hello-apps を参照することに注意
    repoURL: https://github.com/YOUR_NAME/hello-apps
    targetRevision: main
    # デプロイする Application リソースがあるディレクトリを指定
    path: hello-server
    directory:
      # サブディレクトリにある *.jsonnet もデプロイ対象に含める
      recurse: true
  destination:
    server: https://kubernetes.default.svc
    # ここで指定した namespace よりも各マニフェストに書かれている .metadata.namespace のほうが優先される。
    namespace: argocd
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

ここで一旦 hello-apps で git commit & git push しておいてください。

それでは、root-app をデプロイしてみましょう。

# Application が存在しないことを確認しておく
argocd app list

# root-app を作成
argocd app create -f root-app/root-app.yaml

# root-app が {dev,staging,prod}-hello-server を作成してくれるので
# ある程度待つと Application が4つ表示されるようになる
argocd app list

# Pod や Deployment などもそれぞれの namespace に作成されている
kubectl get all -n prod-hello-server

これで app-of-apps の導入ができました。{dev,staging,prod}-hello-server が Argo CD によって管理されるようになったため、Git 上でマニフェストが更新されれば自動的に対応する環境にデプロイされます。手動でのオペレーションは必要ありません (このハンズオンの環境では argocd app sync を手で打つ必要がありますが)。

唯一 root-app だけは更新時に手動で argocd app create --upsert する必要があります。しかし root-app はめったに変更しないでしょうから、コストとしては許容範囲内だと思います。

動作確認

せっかくなので、Application を更新してみましょう。

hello-server.libsonnetvalue: 'Hello (%s)' % env, の部分を value: 'Hello World (%s)' % env, に書き換えて commit & push し、argocd app sync root-app してください。各 Application が自動的に更新され、新しい value が反映されるはずです。

ここで dev, staging, prod が一斉に更新されたことに気付いた人もいるかもしれません。実は現在の hello-apps の作りでは dev → staging → prod と段階を踏むようにはなっていません。これを行うには hello-server と同様、hello-apps にも develop, main, release のようにブランチを作り、root-app から各環境ごとに異なるブランチを参照するようにする必要があります。興味がある人はぜひやってみてください。

以上でハンズオンは終わりです。 私達は GitHub 上のコードの変更 (hello-serverhello-apps も両方) に自動で追従する Kubernetes 環境を構築できました。 お疲れ様でした!