CDK8sをGoで試す

2021/10/25に公開

CDK8sとは

CDK8sは、汎用プログラミング言語を使用してKubernetesアプリケーションを定義するためのオープンソフトウェア開発フレームワークのことです。CDK8sプログラムは、任意のクラスターに直接適用できるKubernetesYAMLを出力します。

CDK8sプロジェクトを構成するコンポーネント

  • cdk8s-cli:CDK8sプロジェクトを初期化および合成するためのコマンドラインツール
  • cdk8s:Kubernetesリソースのビルディングブロックを定義するコアライブラリ
  • cdk8s-plus:Kubernetesリソースとやり取りするための簡略化されたイベントベースのAPI

CDK8sの言語サポート

Java
Pyhton
TypeScript

Go ←new(2021年10月12日)

CDK8s使用方法

まず、CDK8sCLIをインストールします。

$ npm install -g cdk8s-cli

次に、任意の新しいディレクトリを作成し、GoテンプレートからCDK8sアプリを初期化します。

$ mkdir hello-cdk8s-go
$ cd hello-cdk8s-go
$ cdk8s init go-app
Initializing a project from the go-app template
Importing resources, this may take a few moments...
========================================================================================================

 Your cdk8s Go project is ready!

   cat help      Prints this message
   cdk8s synth   Synthesize k8s manifests to dist/
   cdk8s import  Imports k8s API objects to "imports/k8s"

  Deploy:
   kubectl apply -f dist/

そうすることで、main.goが作成されます。

main.go
package main

import (
    "github.com/aws/constructs-go/constructs/v3"
    "github.com/aws/jsii-runtime-go"
    "github.com/cdk8s-team/cdk8s-core-go/cdk8s"
)

type MyChartProps struct {
    cdk8s.ChartProps
}

func NewMyChart(scope constructs.Construct, id string, props *MyChartProps) cdk8s.Chart {
    var cprops cdk8s.ChartProps
    if props != nil {
        cprops = props.ChartProps
    }
    chart := cdk8s.NewChart(scope, jsii.String(id), &cprops)

    // define resources here

    return chart
}

func main() {
    app := cdk8s.NewApp(nil)
    NewMyChart(app, "hello-cdk8s-go", nil)
    app.Synth()
}

nginx用のマニフェストを作成する

main.go
package main

import (
	"example.com/hello-cdk8s-go/imports/k8s"
	"github.com/aws/constructs-go/constructs/v3"
	"github.com/aws/jsii-runtime-go"
	"github.com/cdk8s-team/cdk8s-core-go/cdk8s"
)

type MyChartProps struct {
	cdk8s.ChartProps
}

func NewMyChart(scope constructs.Construct, id string, props *MyChartProps) cdk8s.Chart {
	var cprops cdk8s.ChartProps
	if props != nil {
		cprops = props.ChartProps
	}
	chart := cdk8s.NewChart(scope, jsii.String(id), &cprops)

	labels := map[string]*string{"app": jsii.String("nginx")}

	podSpec := &k8s.PodSpec{
		Containers: &[]*k8s.Container{
			{
				Name:  jsii.String("nginx"),
				Image: jsii.String("nginx:latest"),
				Ports: &[]*k8s.ContainerPort{{ContainerPort: jsii.Number(80)}},
			},
		},
	}

	k8s.NewKubeDeployment(chart, jsii.String("nginx-deployment"), &k8s.KubeDeploymentProps{
		Spec: &k8s.DeploymentSpec{
			Selector: &k8s.LabelSelector{
				MatchLabels: &labels,
			},
			Template: &k8s.PodTemplateSpec{
				Metadata: &k8s.ObjectMeta{
					Labels: &labels,
				},
				Spec: podSpec,
			},
		},
	})

	return chart
}

func main() {
	app := cdk8s.NewApp(nil)
	NewMyChart(app, "hello-cdk8s-go", nil)
	app.Synth()
}

CDK8sアプリを実行してKubernetesマニフェストを作成する

$ cdk8s synth
dist/hello-cdk8s-go.k8s.yaml

dist/hello-cdk8s-go.k8s.yamlを開くと、以下のようなYAMLが表示されます。

hello-cdk8s-go.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-cdk8s-go-nginx-deployment-c8413b4d
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - image: nginx:latest
          name: nginx
          ports:
            - containerPort: 80

そして、マニフェストをクラスターに適用してテストします。

$ kubectl apply -f dist/hello-cdk8s-go.k8s.yaml
deployment.apps/hello-cdk8s-go-nginx-deployment-c8413b4d created

POD_NAME=$(kubectl get pods -l app=nginx -o jsonpath='{.items[0].metadata.name}')
kubectl port-forward $POD_NAME 8080:80

ブラウザで http://localhost:8080 を開くと、“Welcome to nginx!” と表示されると成功です。

CDK8s+

CDK8sで実装したものは元々YAMLに記述していたプロパティと1:1の関係のままであり、以下のようなデメリットがあります。

  • 覚えるべきKubernetesのリソースやプロパティが多く、学習コストが高い
  • 冗長な記述が必要
    そこで作成されたものがCDK8s+になり、以下のようなメリットがあります。
  • 各ObjectごとにIntentベースな実装ができるメソッドが用意されている
  • コード量を減らし、より効率的な実装が可能となる

今後は、このCDK8s+を試したいと思います。

Discussion