1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

プロモーションプラットフォーム「Kargo」を調査した

Posted at

株式会社スリーシェイクで2ヶ月間の期限付きインターンを行いました。インターンではKargoというKubernetesのプロモーションプラットフォームについて技術調査を行いました。

この記事では、Kargoについて紹介した後、インターン期間で発見したKargoのメリットを述べて、最後にKargoのデモを行います。

記事化については、株式会社スリーシェイク様の許可を得ております。

Kargoとは

KargoAkuityが開発している、検証環境からテスト、本番環境へのデプロイまでのデプロイフローを実装、管理するためのプロモーションプラットフォームです。オープンソースで公開されており、https://github.com/akuity/kargo から確認することができます。

Kargoでは、Gitリポジトリの更新やk8sへの反映など、デプロイ時に行う様々な手順を”プロモーションタスク”とみなしており、Kargoはこのプロモーションタスクの実装・管理を支援するためのツールとして作られたと説明しています。

また、KargoはKargo単体で使用することができますが、Argo CDなどの他のツールと併用することも可能です。

Kargoを使用すると、使用するFreightを指定するだけでコンテナのバージョンアップやYAMLファイルの編集とGitリポジトリの変更、Gitリポジトリへのpushなどが自動で行えます。

Kargoで使用する単語

Kargoの説明をするにあたって、Kargo独自の単語や役割について、説明していきます。

ここでは、WarehouseとStage、Promotion Step、Promotion Task、Promotion Templateについて取り上げます。

なお、紹介時に使用しているスクリーンショットはKargo v1.5.3を使用しているため、一部公式ドキュメントで紹介されているスクリーンショットとUIが異なる場合があります。

Warehouse

Warehouseは、Gitリポジトリやコンテナイメージ、Helmチャートリポジトリなどを監視し、変更を検知したら新しいバージョン含めたFreightリソースを作成します。

以下はWarehouseの例です。このWarehouseは”guestbook”という名前で、Dockerイメージ”guestbook”とGitリポジトリ”kargo-advanced.git”を監視しています。

warehouse.png

Freight

デプロイ可能なバージョン群が列挙される場所です。Warehouseで検知されると、Freightリソースが作成されてFreightに出現します。

以下はFreightの例です。Warehouseの例と同じDockerイメージ・Gitリポジトリを使用しています。1時間前に作成された、Gitリポジトリのコミットがeb05af2 でコンテナイメージタグがv0.0.10 のFreightと、1分前に作成された、Gitリポジトリのコミットがeb05af2 でコンテナイメージタグがv0.0.11 のFreightがあります。各Freightの左側にある赤や緑などの色は、後述するStageの色と対応しており、Freightが各色に対応するStageで適用されていることを示しています。

freight.png

Stage

Stageとは、プロモーションにおけるターゲットのことです。各Stageにおいて、新たなFreightがpromoteされた際に実行すべき処理を定義することができます。

なお、Stageはしばしば環境と捉えられることもあります。以下の画像はdev, staging, ab-test, prodの4つのStageを用意した際のイメージです。それぞれのStageは開発環境、ステージング環境、テスト環境、本番環境をイメージして作られています。なお、テスト環境はテストの種類に応じて、本番環境は各リージョンに対応する形で、Stage数が増えていることに注意してください。

stages.png

Promotion Step

KargoにはPromotion Taskと呼ばれる、Stageにpromoteした際に実行する処理をまとめる機構があります。

Promotion Stepでは、GitリポジトリにコミットやPRを作成する、Argo CDを更新する、HTTPリクエストを送信するなど、promoteされた時に実行したい処理のパラメータなどを定義することができます。

以下はPromotion Stepの例です。このStepでは、git-cloneを実装しています。一つずつ見ていきます。

varsではrepoURLとしてリポジトリURLを変数化しています。次にstepsのusesで使用するStepを指定し、configでリポジトリURLを指定しています。また、checkoutの箇所ではcheckoutするコミットIDとブランチ名を指定し、それぞれをcheckoutするpathを指定しています。

git-clone
  vars:
  - name: repoURL
    value: https://github.com/satsuki2200/kargo-advanced.git
  steps:
  - uses: git-clone
    config:
      repoURL: ${{ vars.repoURL }}
      checkout:
      - commit: ${{ commitFrom(vars.repoURL).ID }}
        path: ./src
      - branch: env/${{ ctx.stage }}
        path: ./out
        create: true

Promotion Task

Promotion TaskではいくつかのPromotion Step処理をひとまとめにすることができ、Stageにpromoteされたときに実行したい処理が複数ある際に、あらかじめPromotion Taskで定義しておくことができます。

このTaskは再利用可能であるため、複数のStageで使用することが可能です。

以下はPromotion Taskの例です。なお、こちらからも確認できます。このYAMLファイルでは、Promotion Stepのgit-clonegit-clearkustomize-buildgit-commitgit-pushargocd-updateを定義して、それらをpromote というTask名で定義しています。

promotiontasks.yaml
apiVersion: kargo.akuity.io/v1alpha1
kind: PromotionTask
metadata:
  name: promote
  namespace: kargo-advanced
spec:
  vars:
  - name: repoURL
    value: https://github.com/satsuki2200/kargo-advanced.git
  - name: branch
    value: main
  - name: image
    value: ghcr.io/satsuki2200/guestbook
  steps:
  # Clone the Git repository that contains the Kustomize configuration
  # to the ./src directory, and the environment configuration to ./out.
  - uses: git-clone
    config:
      repoURL: ${{ vars.repoURL }}
      checkout:
      - commit: ${{ commitFrom(vars.repoURL).ID }}
        path: ./src
      - branch: env/${{ ctx.stage }}
        path: ./out
        # Create the branch if it does not exist.
        create: true
  # Following a "rendered branch" pattern, we delete all files in the
  # ./out directory to ensure that we only have the files that are
  # rendered from the Kustomize configuration in the ./src directory
  # of the repository after being rendered.
  - uses: git-clear
    config:
      path: ./out
  # Update the image in the Kustomize configuration located at ./src/env/<stage>
  # in the repository.
  - uses: kustomize-set-image
    as: update-image
    config:
      path: ./src/env/${{ ctx.stage }}
      images:
      - image: ${{ vars.image }}
        tag: ${{ imageFrom(vars.image).Tag}}
  # Build the Kustomize configuration in the ./src directory using the env/<stage>
  # overlay to the ./out directory.
  - uses: kustomize-build
    config:
      path: ./src/env/${{ ctx.stage }}
      outPath: ./out
  # Commit the changes to the Git repository.
  - uses: git-commit
    as: commit
    config:
      path: ./out
      message: ${{ task.outputs['update-image'].commitMessage }}
  # Push the changes to the Git repository.
  - uses: git-push
    config:
      path: ./out
  # Request a sync of the ArgoCD Application to apply the changes from the
  # commit.
  - uses: argocd-update
    config:
      apps:
      - name: guestbook-${{ ctx.stage }}
        sources:
        - repoURL: ${{ vars.repoURL }}
          desiredRevision: ${{ task.outputs['commit'].commit }}

Promotion Template

Promotion Templateでは、新しいk8sマニフェストやコンテナイメージをStageに導入する際実行するTaskを定義します。

また、呼び出すTaskに変数が必要な場合は、Promotion Templateで定義します。

Kargoを使用することで得られるメリット

ここでは、私がインターン期間にKargoを調査して発見したメリットを説明します。

私が発見したメリットは以下です。

  • デプロイフローをWeb GUIで可視化することができる
  • Podに変更を反映する前に行いたい処理を自動化できる
  • 開発環境から本番環境までのデプロイフローを自由に構成できる

それぞれについて、説明していきます。

今回はkargo-advancedというKargo提供元が公開しているサンプルリポジトリを使用します。このリポジトリでは、大きく分けて4つのStageを含んでおり、dev、staging、ab-test、prodのデプロイフローで構成されています。ab-testは同じテストを値の異なる2種類で検証するためにテストA用とテストB用の計2つ、prodは本番環境に複数のリージョンがあることを想定して作られているため、eastリージョン、westリージョン、centralリージョンが用意されており、それぞれにStageが存在することに注意してください。

デプロイフローの可視化

Gitリポジトリに変更を加えた後、本番環境にデプロイするまで、様々な環境での検証やテストが行われることでしょう。現在のステップは本番環境デプロイまであとどれくらいなのか、そして現在のステップが終わったら次に何のステップを行うのか、Argo CDでApplicationsを眺めているだけでは分かりません。

しかしKargoを使用することで、これらの問題は解消され、一箇所で可視化することができます。

以下はkargo-advancedについてArgo CDのApplicationsを表示した画像です。この画像を見ただけでは、最初にどのApplicationで検証を行うべきかわかりません。

argocd_applications.png

しかしKargoを使用すると、この問題は解決します。以下はkargo-advancedについてKargoのProjectを表示した画像です。この画像を見ると、最初にdev環境で検証を行い、次にstaging、そしてab-testの順に検証すれば良いことがわかるでしょう。

kargo_project.png

また、Kargoでは現在実行しているコンテナのバージョンやGitリポジトリのコミットをハッシュ値で表示することができます。これにより、dev環境ではv0.0.11のコンテナを実行しており、それ以外の環境ではv0.0.10のコンテナを実行していることも一目でわかります。

処理の自動化

Podで動かしているコンテナのバージョンをあげたい、リポジトリの内容に変更があったので反映したい。そのような時、Promotion Taskに行いたい処理を定義しておくことで、自動化することができます。

Gitブランチやコミットの作成、GitリポジトリにPRを作成することやYAMLファイルの更新、Argo CDの更新、HTTPリクエストの送信など、様々なことを行えます。

デプロイフロー構成の自由度

本番環境までに幾つのステップを通過する必要があるか、どんなテストをどれだけ行うのか、それは内容によって異なるかと思います。

Kargoでは、Stage数や各Stageで行うPromotion Taskを自由に設定できます。例えば、dev環境とuat環境、そして5つのテスト環境を用意するといったことも可能です。

また、それぞれの環境で行うPromotion Taskも柔軟に変更することができます。すべての環境で異なるTaskを動作させることも可能です。

Kargoデモ

AkuityはKargoの使用例として複数のリポジトリを公開しています。今回はその1つであるkargo-advancedをforkしてプロモーションの検証を行いました。

手元で実行する際は各自でリポジトリをforkし、KargoがリポジトリにpushできるようGitHub Personal Access Tokenを発行してArgo CDとKargoのそれぞれにSecretとして追加してください。

検証環境は以下のとおりです。

名称 バージョン
macOS v15.5
Docker v27.4.0
kind v0.27.0
Argo CD client:v3.0.0+e98f483
server:v3.0.6+db93798
Argo Rollouts v1.8.3
cert-manager v1.18.1
Kargo v1.5.3.

環境構築は自作したシェルスクリプトを使用しました。

install.sh
#!/bin/bash

# Argo CD
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

# Argo Rollouts
kubectl create namespace argo-rollouts
kubectl apply -n argo-rollouts -f https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml

# cert-manager
helm install cert-manager cert-manager \
  --repo https://charts.jetstack.io \
  --namespace cert-manager \
  --create-namespace \
  --set crds.enabled=true \
  --wait

# Kargo
# Password is 'admin'
helm install kargo \
  oci://ghcr.io/akuity/kargo-charts/kargo \
  --namespace kargo \
  --create-namespace \
  --version 1.5.3 \
  --set api.adminAccount.passwordHash='$2a$10$Zrhhie4vLz5ygtVSaif6o.qN36jgs6vjtMBdM6yrU1FOeiAAMMxOm' \
  --set api.adminAccount.tokenSigningKey=iwishtowashmyirishwristwatch \
  --wait

環境構築とリポジトリforkを行った後、ArgoCDとKargoのWeb GUI操作画面にアクセスするためにポートフォワードを行います。これらはターミナルで別タブを開き、実行したままにしておいてください。

# Argo CDのポートフォワード
kubectl port-forward services/argocd-server -n argocd 8080:443

# Kargoのポートフォワード
kubectl port-forward --namespace kargo svc/kargo-api 3000:443

Webでhttps://localhost:8080https://localhost:3000にアクセスすると、それぞれArgoCDとKargoのログイン画面が表示されます。

Kargoの初期パスワードはadmin です。Argo CDの初期パスワードは以下のコマンドで確認できます。

argocd admin initial-password -n argocd

CLIもログインします。

# Argo CD CLI login
$ argocd login localhost:8080
WARNING: server certificate had error: tls: failed to verify certificate: x509: certificate signed by unknown authority. Proceed insecurely (y/n)? y
Username: admin
Password:
'admin:login' logged in successfully
Context 'localhost:8080' updated
$ 
# Kargo CLI login
$ kargo login https://localhost:3000 --admin --insecure-skip-tls-verify
? Admin user password *****
$ 

次にArgo CDのプロジェクトとApplications、Kargoのプロジェクトなどを作成します。

argocd proj create -f ./argocd/appproj.yaml
argocd appset create ./argocd/appset.yaml
kargo apply -f ./kargo

すべて実行した後にArgo CDの管理画面にアクセスすると、guestbookから始まるApplicationが複数存在し、すべてStatusがUnknownになっています。また、Kargoの管理画面にアクセスすると、kargo-advancedというProjectがあるので、クリックしてみます。すると、以下のようにWarehouseや複数のStageが並んでいます。

kargo-advanced-pre.png

試しに0e74c71v0.0.11の組み合わせのFreightをdevにpromoteしてみます。dev右側のトラックボタン→Promoteを順に押下すると、Freightが選択できるため、0e74c71v0.0.11の組み合わせをSelect、右下緑色のPromoteボタンを押下します。

dev_select.png

するとすぐに様々な処理が実行されました。すべてが完了した後、GitHubリポジトリを確認すると/env/devというブランチ内にKargoによるコミットが確認できました。また、Argo CDのguestbook-devもStatusがSyncになっていることが確認できました。

dev_promote.png

dev_commit.png

promoteしたときに何が起こったのでしょうか?

先ほど述べた”様々な処理”はPromotion Task(複数のPromotion Stepの集合)によるものです。これらはpromotiontasks.yamlpromoteという名前で定義されており、kargo-advancedではすべてのStageにおいてFreightをpromoteする際に実行されます。このPromotion Taskでは、git-clone、git-clear、kustomize-set-image、kustomize-build、git-commit、git-push、argocd-updateが順に行われます。

この時、argocd-updateも行われるため、Argo CDを通じてNamespaceguestbook-dev もSyncされ、Podが動き始めます。

promotiontasks.yaml
apiVersion: kargo.akuity.io/v1alpha1
kind: PromotionTask
metadata:
  name: promote
  namespace: kargo-advanced
spec:
  vars:
  - name: repoURL
    value: https://github.com/satsuki2200/kargo-advanced.git
  - name: branch
    value: main
  - name: image
    value: ghcr.io/satsuki2200/guestbook
  steps:
  # Clone the Git repository that contains the Kustomize configuration
  # to the ./src directory, and the environment configuration to ./out.
  - uses: git-clone
    config:
      repoURL: ${{ vars.repoURL }}
      checkout:
      - commit: ${{ commitFrom(vars.repoURL).ID }}
        path: ./src
      - branch: env/${{ ctx.stage }}
        path: ./out
        # Create the branch if it does not exist.
        create: true
  # Following a "rendered branch" pattern, we delete all files in the
  # ./out directory to ensure that we only have the files that are
  # rendered from the Kustomize configuration in the ./src directory
  # of the repository after being rendered.
  - uses: git-clear
    config:
      path: ./out
  # Update the image in the Kustomize configuration located at ./src/env/<stage>
  # in the repository.
  - uses: kustomize-set-image
    as: update-image
    config:
      path: ./src/env/${{ ctx.stage }}
      images:
      - image: ${{ vars.image }}
        tag: ${{ imageFrom(vars.image).Tag}}
  # Build the Kustomize configuration in the ./src directory using the env/<stage>
  # overlay to the ./out directory.
  - uses: kustomize-build
    config:
      path: ./src/env/${{ ctx.stage }}
      outPath: ./out
  # Commit the changes to the Git repository.
  - uses: git-commit
    as: commit
    config:
      path: ./out
      message: ${{ task.outputs['update-image'].commitMessage }}
  # Push the changes to the Git repository.
  - uses: git-push
    config:
      path: ./out
  # Request a sync of the ArgoCD Application to apply the changes from the
  # commit.
  - uses: argocd-update
    config:
      apps:
      - name: guestbook-${{ ctx.stage }}
        sources:
        - repoURL: ${{ vars.repoURL }}
          desiredRevision: ${{ task.outputs['commit'].commit }}

このように、KargoでpromoteするとGitリポジトリの変更やArgo CDのUpdateなどの処理を一括して自動で行うことができました。

同じ要領でstagingとab-test、prodについても順にpromoteしていきます。

ab-testでは、Argo Rolloutsを使用してテストを行っています。内容は特定のポケモンのbase_experienceをPokeAPIで取得し、その値が一定以下ならテストをパスするというものです。ab-test-aではピカチュウ、ab-test-bではリザードンでテストを行っています。

元リポジトリのままだとab-test-bはテストをクリアすることができません。テストをクリアさせたい場合は、stages.yaml でポケモン名を変更するか、analysis.yamlの閾値を変更することでテストをクリアすることができます。

stages.yaml
apiVersion: kargo.akuity.io/v1alpha1
kind: Stage
metadata:
  name: ab-test-b
  namespace: kargo-advanced
  annotations:
    kargo.akuity.io/color: green
spec:
  requestedFreight:
  - origin:
      kind: Warehouse
      name: guestbook
    sources:
      stages:
      - staging
  promotionTemplate:
    spec:
      steps:
      - task:
          name: promote

  verification:
    analysisTemplates:
    - name: pokemon-xp
    args:
    - name: pokemon
      value: charizard # charizardを変更
analysis.yaml
analysis.yaml
# This is a sample analysis template that uses the PokeAPI to
# check the base experience of a Pokemon is under threshold.
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
  name: pokemon-xp
  namespace: kargo-advanced
spec:
  args:
  - name: pokemon
  metrics:
  - name: pokemon-xp
    interval: 5s
    count: 5
    successCondition: result < 200 # 200を変更
    failureLimit: 3
    provider:
      web:
        url: https://pokeapi.co/api/v2/pokemon/{{args.pokemon}}
        jsonPath: "{$.base_experience}"

prodは3つのStageがありますが、prodという名前のStageでpromoteを行おうとすると、これまで”Promote”と書かれていた箇所が”Promote to downstream”になっています。このPromote to downstreamは、prodに紐づいているprod-central、prod-east、prod-westの3つすべてに同じFreightをpromoteすることができます。1つずつpromoteするのはめんどくさいので、Promote to downstreamで一気にpromoteしてしまいましょう。



すべての環境においてFreightを適用することができました🎉

kargo-advanced-finish.png

このように、Stageによって行いたい処理を決めることができるので、デプロイまでのフローを自由に構築することができます。

また、リポジトリに新たなコミットがされた時やコンテナイメージに新しいイメージタグが発生すると、新しいFreightが作られてパイプラインに登場します。

新たなFreightをデプロイしたい時は、先ほどと同じようにpromoteしていくことでデプロイすることができます。

まとめ

今回はKubernetesのコンテナオーケストレーションツールであるKargoについて調査を行い、また簡単な検証を行いました。

また、拙い文章を読んでいただきありがとうございました。

まだまだKubernetesの知識やCDの知識が足りていないので、さらに研鑽していく所存です。

参考

Kargo HP https://kargo.io/

Kargo Docs https://docs.kargo.io/

Kargo Core Concepts https://docs.kargo.io/user-guide/core-concepts

Warehouse https://docs.kargo.io/user-guide/core-concepts/#warehouses

Freight https://docs.kargo.io/user-guide/core-concepts/#freight

Stage https://docs.kargo.io/user-guide/core-concepts/#stages

Promotion Step https://docs.kargo.io/user-guide/reference-docs/promotion-steps/

Promotion Task https://docs.kargo.io/user-guide/reference-docs/promotion-tasks/

Promotion Template https://docs.kargo.io/user-guide/reference-docs/promotion-templates/

kargo-advanced https://github.com/akuity/kargo-advanced

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?