17
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

NRI OpenStandiaAdvent Calendar 2024

Day 7

Argo Rolloutsのソースコードを読んでみた

Last updated at Posted at 2024-12-06

はじめに

この記事では、Argo Rolloutsのソースコードを通して、ArgoがKubernetesをどのように操作するのか、その仕組みの概要を理解できる内容となってます。

ドキュメントを読んでもいまいち分からなかった方にとって、Argoの動作メカニズムを少しでも理解する手助けになれば幸いです。

前提としてそれぞれの機能を深掘りはせず、あくまでKubernetesをどのように操作するのかをまとめたものになります。
そのため、それぞれの詳しい機能に関しては公式ドキュメント1や他の記事を参考にしていただくようお願いいたします。

Argo Rolloutsとは

image.png

Argo Rollouts(アルゴロールアウト) は、Kubernetes環境にデプロイメントのための機能を提供するGo言語で書かれたオープンソースのツールセットです。2

主な特徴としては、以下のような高度なデプロイメント機能が提供されていることです。

  • ブルー/グリーンデプロイメント
  • カナリアデプロイメント
  • 自動ロールバックとプロモーション

Argo Rolloutsは、KubernetesコントローラーとCRDのセットを利用して、これらの高度なデプロイ機能を提供しています。1

オープンソースであることから、Githubにソースコードが公開されています。

Argo Projectには、Argo Rolloutsの他にも以下のプロジェクトがあります。

Argo Rolloutsが提供する機能

Argo Rolloutsが提供する主な機能は以下の2つです。

  • kubectl-argo-rollouts
  • rollouts-controller

kubectl-argo-rolloutsは、Kubernetesを操作するときに利用するコマンドkubectlの拡張版コマンドのようなものです。

rollouts-controllerについて、公式ドキュメントには以下のような記載がありました。3

Similar to the deployment object, the Argo Rollouts controller will manage the creation, scaling, and deletion of ReplicaSets. These ReplicaSets are defined by the spec.template field inside the Rollout resource, which uses the same pod template as the deployment object.

rollouts-controllerはKubernetesクラスター内で、ReplicaSetsの作成、スケーリング、削除を管理するものです。

Kubernetesリソースの操作について

kubectl-argo-rollouts

まず、前述した機能の内kubectl-argo-rolloutsを確認します。
やっていることは、NewCmdArgoRolloutsを実行なので、次はそのソースコードを確認します。

func main() {
	klog.InitFlags(nil)
	logutil.SetKLogLogger(log.New())
	streams := genericclioptions.IOStreams{In: os.Stdin, Out: os.Stdout, ErrOut: os.Stderr}
	o := options.NewArgoRolloutsOptions(streams)
	root := cmd.NewCmdArgoRollouts(o)
	if err := root.Execute(); err != nil {
		os.Exit(1)
	}
}

NewCmdArgoRollouts

NewCmdArgoRolloutsには、色々なコマンドをセットして実行していることが分かります。

なかには以下のようなArgo CDのダッシュボードで見慣れた機能があります。

スクリーンショット 2024-12-02 214607.png

今回は「Abort」=NewCmdAbortのソースコードを確認します。

// 抜粋
o.AddKubectlFlags(cmd)
cmd.AddCommand(create.NewCmdCreate(o))
cmd.AddCommand(get.NewCmdGet(o))
cmd.AddCommand(lint.NewCmdLint(o))
cmd.AddCommand(list.NewCmdList(o))
cmd.AddCommand(pause.NewCmdPause(o))
cmd.AddCommand(promote.NewCmdPromote(o))
cmd.AddCommand(restart.NewCmdRestart(o))
cmd.AddCommand(version.NewCmdVersion(o))
cmd.AddCommand(abort.NewCmdAbort(o))
cmd.AddCommand(retry.NewCmdRetry(o))

NewCmdAbort

rolloutIf.Patchを実行しています。
Patchとみて、まず思いつくのが、REST APIにおけるPATCHです。(一般的には、リソースへの部分的な変更を適用に利用する)
次はRolloutInterfaceを確認します。

const (
	abortPatch = `{"status":{"abort":true}}`
)
// 省略
func AbortRollout(rolloutIf clientset.RolloutInterface, name string) (*v1alpha1.Rollout, error) {
	ctx := context.TODO()
	ro, err := rolloutIf.Patch(ctx, name, types.MergePatchType, []byte(abortPatch), metav1.PatchOptions{}, "status")
	if err != nil && k8serrors.IsNotFound(err) {
		ro, err = rolloutIf.Patch(ctx, name, types.MergePatchType, []byte(abortPatch), metav1.PatchOptions{})
	}
	return ro, err
}

RolloutInterface

c.client.Patchは一般的なREST APIを叩くときのソースコードに見えます。
clientの正体はk8s.io/client-goです。

// 抜粋
import (
	rest "k8s.io/client-go/rest"
)
type RolloutInterface interface {
	Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.Rollout, err error)
}
// rollouts implements RolloutInterface
type rollouts struct {
	client rest.Interface
	ns     string
}
// Patch applies the patch and returns the patched rollout.
func (c *rollouts) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.Rollout, err error) {
	result = &v1alpha1.Rollout{}
	err = c.client.Patch(pt).
		Namespace(c.ns).
		Resource("rollouts").
		Name(name).
		SubResource(subresources...).
		VersionedParams(&opts, scheme.ParameterCodec).
		Body(data).
		Do(ctx).
		Into(result)
	return
}

k8s.io/client-go

client-goとは、Kubernetesクラスターをgoアプリから操作するためのライブラリです。

READMEには、以下の記載があります。

The kubernetes package contains the clientset to access Kubernetes API.

client-goを使うことで、Kubernetes APIにアクセスできます。

以下のKubernetesクラスターを構成するコンポーネントから分かる通り、Kubernetes APIは他コンポーネントからリクエストを処理し、同じクラスター内のリソースを操作できます。4 5

image.png

Argo Rolloutsは内部でKubernetes APIを叩くことで、Kubernetesのリソースを操作していたことが分かりました。

なお、前述の「Abort」については、Kubernetes APIに対してPATCHでリクエストを送信し、クラスター内で以下のコマンドを実行しているイメージになります。

kubectl patch rollout --type merge -p {"status":{"abort":true}}

(おまけ)自動生成ツール

Argo Rolloutsのソースコードを読む中でマークコメントが多かったです。
そのため、ここからはおまけとして、筆者が気になった自動生成ツールを記載します。

前提として、ArgoはCustom Resource Definitions(CRD)という、Kubernetes APIを拡張した独自のリソース(Custom Resource=CR)を定義しています。

CRDは2つの構成要素があり、概要は以下になります。6

  • カスタムリソース:特定のクラスター環境に応じたリソースをカスタムリソースを定義する
  • カスタムコントローラー:指定したリソースの状態を監視しそれを維持するように動作する

CRについては以下のディレクトリにあります。

CRDの一例は以下にあります。

CRDには以下のマーカーコメントがあります。

// 抜粋
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +kubebuilder:resource:path=rollouts,shortName=ro
//+kubebuilder:subresource:scale:specpath=.spec.replicas,statuspath=.status.HPAReplicas,selectorpath=.status.selector
// +kubebuilder:subresource:status

  • +genclient
    • client-genというCRDに対するクライアントコードを自動生成するツールに関するマーカーコメント
    • 前述のRolloutInterfaceを定義しているファイルには、client-genによって生成されたコードであることを示す記載がありました
// Code generated by client-gen. DO NOT EDIT.
  • +k8s:deepcopy-gen
    • deepcopy-genというdeepcopyを自動生成するツールに関するマーカーコメント
    • zz_generated.deepcopy.goには、deepcopy-genによって生成されたコードであることを示す記載がありました
// Code generated by deepcopy-gen. DO NOT EDIT.
  • +kubebuilder
    • KubebuilderというKubernetesを拡張するためのカスタムコントローラー/オペレーターを開発するためのフレームワーク

前述の自動生成ツールを利用することで、Kubernetesを操作する実装を簡易化していることが分かります。

さいごに

Argo Rolloutsは、Kubernetes APIにリクエストを投げることで、リソースを操作していることが分かりました。
しかし、詳細までは確認できていないため、今後調べていこうと思います!

おまけでKubernetesに関する自動生成ツールについても簡単に調べましたがすごく充実している印象を受けました。
やはりKubernetesとgoの親和性が高いですね。

  1. https://argoproj.github.io/argo-rollouts/ 2

  2. https://openstandia.jp/oss_info/argorollouts/

  3. https://argo-rollouts.readthedocs.io/en/stable/#how-does-it-work

  4. https://kubernetes.io/ja/docs/concepts/overview/kubernetes-api/

  5. https://kubernetes.io/ja/docs/concepts/overview/components/

  6. https://kubernetes.io/ja/docs/concepts/extend-kubernetes/api-extension/custom-resources/

17
2
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
17
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?