Amazon Web Services ブログ

cdk8s が一般利用開始並びに Go 言語 をサポート

私たちは、CDK8s プロジェクトの一般利用開始並びに Go 言語のサポートを皆様に発表できることを嬉しく思います。CNCF Sandbox プロジェクトである CDK8s は、汎用的なプログラミング言語を使用して Kubernetes アプリケーションを定義するためのオープンソースのソフトウェア開発フレームワークです。CDK8s は、Kubernetes のマニフェスト YAML ファイルを出力し、そのマニフェストは任意のクラスタにそのまま適用することができます 。CDK8s が開発された背景について詳細は、ローンチ時のブログまたは CNCF ウェビナーをご覧ください。

一般利用開始 (つまり v1.0)

詳しく説明する前に、CDK8s プロジェクトを構成する主要なコンポーネントの簡単な要約を以下に示します。

  • cdk8s-cli: CDK8s プロジェクトの雛形生成や、CDK8s を利用して書かれたコードから YAML の生成を行えるコマンドラインツール
  • cdk8s: Kubernetes リソースのビルディングブロックを定義するコアライブラリ
  • cdk8s+ (cdk8s-plus): Kubernetes リソースを Intent ベースな実装でマニフェストYAML を効率的に生成できるライブラリ

このリリースでは、cdk8s-clicdk8s を v1.0 としてマークしています。これは、今後のリリースがセマンティックバージョニングに準拠し、マイナーバージョンでの破壊的変更の導入回避が期待できることを意味します。

より多くのコミュニティフィードバックを収集するため、cdk8s-plus はまだベータ版のままであることに注意してください。

安定性と互換性のサポートに加えて、このリリースにはさらにいくつかの機能強化があります。

Go 言語のサポート (デベロッパープレビュー)

CDK8s のローンチ以来、Go はサポートリクエストが圧倒的に最も多く寄せられていた言語でした。一般利用開始と合わせて、Go が公式にサポートされている言語に加わったことを発表でき嬉しく思います。これにより、CDK8s は Java、Python、TypeScript、Go を公式にサポートしていることになります。 Go を利用する開発者は CDK8s を使用して Kubernetes リソースをプログラムで定義し、Kubernetes OpenAPI スキーマから生成された低レベルのビルディングブロックで簡単に構成できるようになりました

開始するには GoNode.js が必要です。これらは、パッケージマネージャーから取得できるでしょう。また、デプロイ先の Kubernetes クラスターも必要です。現在 Kubernetes クラスターがない場合は、kindeksctl、またはその他のプロバイダーを使用して作成できます。次のコマンドを実行して CDK8s CLI をインストールします。

$ npm install -g cdk8s-cli

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 を開きます。

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()
}

CDK8s にはいくつかの異なる概念があり、それらを扱います。Construct は、CDK8s で Kubernetes マニフェストを記述する際のビルディングブロックをあらわす概念です。これらを組み合わせることで、さらに高レベルの抽象度を持つ Construct を構築できます。ApiObject は Kubernetes リソースを表す Construct 群であり、Chart (Helm Chart と混同しないでください) は 1つの Kubernetes マニフェスト YAML を出力する Construct 群の入れ物となる概念です。

CDK8s CLI は、Kubernetes OpenAPI 仕様から生成された APIObject 群を自動的にインポートしたものを imports/k8s/k8s.go に保持しています。このファイルを見て、そのサイズに恐れることはありません。これは Kubernetes API 全体を表しています。

main.go ファイル先頭の import セクションに example.com/hello-cdk8s-go/imports/k8s を追加して、ApiObject 群を インポートします。注:モジュール名は、example.com から go.mod ファイルの先頭にある任意の名前に変更できます。

これで最初の Chart が完成します!// define resources here と書かれている行を、以下のようなコードで書き換えて、Nginx ウェブサーバーイメージを使った Kubernetes Deployment オブジェクトを定義します。

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,
        },
    },
})

APIObject 群が配置されたら、cdk8s synth コマンドを実行します。CDK8s アプリを実行され、Kubernetes マニフェストYAML が生成されます。

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

dist/hello-cdk8s-go.k8s.yaml を開くと、元のプレーンな 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+

低レベル (L1) の Construct である CDK8s のリソースは強力です。しかし、その実装はあくまで YAML に記述していたプロパティと 1:1 の関係のままです。覚えないといけない Kubernetes のリソースやプロパティは非常に多く、依然として学習コストは高く、また冗長な記述が必要です。これに対処するために、高レベル (L2) の Construct である CDK8s+ を作成しました。先ほど使用した低レベルの Construct を抽象化する形で、各 Object ごとに Intent ベースな実装ができるメソッドが用意されています。これによりコード量を減らしたり、より効率的な実装が可能となります。

たとえば、先ほどと同じ結果を得るために今度は CDK8s+ を使うと以下のような実装になります。先ほどよりもコード量を減っていることがわかると思います。

import (
      "github.com/cdk8s-team/cdk8s-plus-go/cdk8splus22"
    )

cdk8splus22.NewDeployment(app, jsii.String("nginx"), &cdk8splus22.DeploymentProps{
    Containers: &[]*cdk8splus22.ContainerProps{
        {
            Image: jsii.String("nginx:latest"),
        },
    },
})

CDK8s+ についての詳細は、ローンチブログをご覧ください。

CDK8s+ の主な目標の 1 つは、Kubernetes のマニフェストを書く上で覚えるべきことを減らし、マニフェストの記述ミスをする余地をほとんど残さないことです。これを実現するために、CDK8s+ は特定のバージョンの Kubernetes をターゲットにしています。結果、運用している Kubernetes クラスターで利用できない可能性がある機能がマニフェストに入り込むことはありません。

今回のローンチ以前は、CDK8s+ は Kubernetes v1.17 のみをサポートしていました。つまり、上位バージョンで追加された機能を CDK8s+ で利用できませんでした。今回のリリースでは、Kubernetes の 最新 3 バージョン (1.20, 1.21, 1.22) に対応する複数の CDK8s+ ライブラリが導入されました。

CDK8s+ のバージョニングと販売戦略の詳細については、CDK8s+ FAQ を参照してください。

より多くのコミュニティフィードバックを収集するため、CDK8s+ はまだベータ版のままです。ぜひフィードバックをよろしくお願いします

次のステップ

CDK8s をぜひお試しください。始めるにあたって、入門ガイドやリポジトリ内のが最適です。コントリビュートやフィードバックに興味がある場合は、メーリングリストに参加して、毎月のコミュニティミーティングに参加してください。

翻訳はソリューションアーキテクト濱が担当しました。原文はこちらです。