Goとcdk8sを使ってKubernetesのカスタムリソースを管理する方法
Goとcdk8sを使ってKubernetesのカスタムリソースを管理する方法
はじめに
Kubernetesのカスタムリソースを管理するのに、YAMLを書くのは正直面倒ですよね。特に複雑なリソースになると、YAMLファイルはすぐに肥大化します。
そこでcdk8sの出番です。GoやTypeScriptなどのプログラミング言語でリソースを定義できるので、コードの再利用や型チェックの恩恵を受けられます。この記事では、Goとcdk8sを使ったカスタムリソース管理の方法を紹介します。例として、Argo WorkflowsのCronWorkflowカスタムリソースを使用しますが、ここで紹介する手法は他のカスタムリソースにも適用できます。
cdk8sとは
cdk8sは、AWSが開発したCDK(Cloud Development Kit)の考え方をKubernetesに適用したものです。これにより、YAMLの代わりにTypeScript、Python、Goなどのプログラミング言語を使用してKubernetesリソースを定義できます。
cdk8sの主な利点:
- 型安全性: コンパイル時にエラーを検出できる
- 抽象化: 複雑なリソース定義を再利用可能なコンポーネントとして抽象化できる
- テスト容易性: ユニットテストやスナップショットテストが可能
- IDEサポート: コード補完や定義ジャンプなどのIDEの機能を活用できる
環境準備
この記事では、GoとNode.jsがすでにインストールされていることを前提としています。まだインストールしていない場合は、それぞれの公式サイトからインストールしてください。
cdk8s CLIをインストールします:
npm install -g cdk8s-cli
プロジェクトの作成
新しいcdk8sプロジェクトを作成します:
# 新しいディレクトリを作成
mkdir cdk8s-sample
cd cdk8s-sample
# cdk8sプロジェクトを初期化(Go言語を指定)
cdk8s init go-app
これにより、基本的なプロジェクト構造が作成されます。
カスタムリソース定義のインポート
カスタムリソース定義(CRD)をインポートするには、cdk8s import
コマンドを使用します。ここでは例としてArgo WorkflowsのCronWorkflow CRDをインポートします:
cdk8s import https://raw.githubusercontent.com/argoproj/argo-workflows/refs/tags/v3.6.5/manifests/base/crds/full/argoproj.io_cronworkflows.yaml
このコマンドは、指定されたURLからCRDを取得し、Goコードを生成します。
これにより、imports/argoprojio
ディレクトリにカスタムリソースを操作するためのGoコードが生成されます。他のカスタムリソースを使用する場合は、対応するCRDのURLを指定します。
Goコードでのカスタムリソース定義
main.go
ファイルを編集して、カスタムリソースを定義します。以下はCronWorkflowリソースを例とした実装です:
package main
import (
"example.com/cdk8s-sample/imports/argoprojio"
"github.com/aws/constructs-go/constructs/v10"
"github.com/aws/jsii-runtime-go"
"github.com/cdk8s-team/cdk8s-core-go/cdk8s/v2"
)
type MyChartProps struct {
cdk8s.ChartProps
}
func NewMyChart(scope constructs.Construct, id string, props *MyChartProps) cdk8s.Chart {
chart := cdk8s.NewChart(scope, jsii.String(id), &props.ChartProps)
argoprojio.NewCronWorkflow(chart, jsii.String("hoge"), &argoprojio.CronWorkflowProps{
Metadata: &cdk8s.ApiObjectMetadata{
Name: jsii.String("cfw-test"),
},
Spec: &argoprojio.CronWorkflowSpec{
WorkflowSpec: &argoprojio.CronWorkflowSpecWorkflowSpec{
WorkflowTemplateRef: &argoprojio.CronWorkflowSpecWorkflowSpecWorkflowTemplateRef{
Name: jsii.String("wft-test"),
},
},
Schedule: jsii.String("0 0 * * *"),
},
})
return chart
}
func main() {
app := cdk8s.NewApp(&cdk8s.AppProps{})
NewMyChart(app, "sample", &MyChartProps{})
app.Synth()
}
このコードでは、以下のことを行っています:
-
NewMyChart
関数でcdk8sのチャートを作成 - チャート内でカスタムリソース(この例ではCronWorkflow)を定義
- メタデータ:名前を設定
- 各種プロパティ:リソースに必要な設定を指定
-
main
関数でアプリケーションを作成し、チャートを追加して、マニフェストを生成
このパターンは他のカスタムリソースにも適用できます。インポートしたCRDに基づいて生成されたGoの型定義を使用することで、IDEの補完機能を活用しながら、型安全にリソースを定義できます。
マニフェストの生成と適用
以下のコマンドを実行して、Kubernetesマニフェストを生成します:
go run .
または:
cdk8s synth
これにより、dist
ディレクトリにKubernetesマニフェストファイルが生成されます。例えば、上記のCronWorkflowの例では以下のようなYAMLが生成されます:
apiVersion: argoproj.io/v1alpha1
kind: CronWorkflow
metadata:
name: cfw-test
spec:
schedule: 0 0 * * *
workflowSpec:
workflowTemplateRef:
name: wft-test
他のカスタムリソースを使用する場合も、同様のパターンでGoコードからYAMLマニフェストが生成されます。
生成されたマニフェストをKubernetesクラスタに適用するには:
kubectl apply -f dist/sample.k8s.yaml
cdk8sを使ったカスタムリソース管理の利点
1. 型安全性
Goの型システムにより、リソース定義の誤りをコンパイル時に検出できます。例えば、必須フィールドの欠落や型の不一致などは、コードを実行する前に検出されます。
2. コード再利用
共通のリソース定義をGoの関数や構造体として抽象化し、再利用できます。例えば、複数のCronWorkflowで共通の設定を持つ場合、それをヘルパー関数として定義できます:
func CreateBaseCronWorkflow(chart constructs.Construct, id string, name string, schedule string) argoprojio.CronWorkflow {
return argoprojio.NewCronWorkflow(chart, jsii.String(id), &argoprojio.CronWorkflowProps{
Metadata: &cdk8s.ApiObjectMetadata{
Name: jsii.String(name),
},
Spec: &argoprojio.CronWorkflowSpec{
Schedule: jsii.String(schedule),
// 共通の設定...
},
})
}
3. 環境ごとの設定変更
環境変数や設定ファイルから値を読み込み、環境ごとに異なるマニフェストを生成できます:
func NewEnvironmentSpecificChart(scope constructs.Construct, id string, props *MyChartProps, env string) cdk8s.Chart {
chart := cdk8s.NewChart(scope, jsii.String(id), &props.ChartProps)
var schedule string
if env == "production" {
schedule = "0 0 * * *" // 本番環境:毎日午前0時
} else {
schedule = "0 12 * * *" // 開発環境:毎日正午
}
argoprojio.NewCronWorkflow(chart, jsii.String("cron-workflow"), &argoprojio.CronWorkflowProps{
// ...
Spec: &argoprojio.CronWorkflowSpec{
Schedule: jsii.String(schedule),
// ...
},
})
return chart
}
4. テスト容易性
リソース定義をユニットテストできます:
func TestCronWorkflowCreation(t *testing.T) {
app := cdk8s.NewApp(&cdk8s.AppProps{})
chart := NewMyChart(app, "test", &MyChartProps{})
// チャート内のリソースをテスト
// ...
}
まとめ
この記事では、Goとcdk8sを使用してKubernetesのカスタムリソースを管理する方法を紹介しました。cdk8sを使うことで、YAMLファイルを直接編集する代わりに、型安全なGoコードでKubernetesリソースを定義できます。例としてArgo WorkflowsのCronWorkflowを使用しましたが、同じアプローチは他のカスタムリソース(例:Istio、Knative、Prometheus Operator、Cert-Managerなど)にも適用できます。
cdk8sの主な利点は:
- 型安全性によるエラーの早期発見
- コードの再利用と抽象化
- 環境ごとの設定変更の容易さ
- テスト容易性
カスタムリソースが増えてくると、YAMLファイルの管理は複雑になりがちです。cdk8sを使うことで、プログラミング言語の強力な機能を活用しながら、Kubernetesリソースを効率的に管理できます。
Discussion