先日KubernetesのPodcastを聞いていたところ、kptなるツールがリリースされたと知り、早速試してみました。
kptとは
GoogleがOSSとして開発・公開している、Kubernetes用の設定管理ツールです。ちなみに**「けぷと」**と発音します。アジャイルのふりかえりの手法の1つと同じですね。
Kubernetesで、設定すべき箇所が似通っているサービスを複数起動したいような場合に威力を発揮するツールです。具体的には、以下のように使用します。
- 各サービスで共用できるKubernetesのリソースファイル(.yaml)群を用意する
- リソースファイル内で、サービス毎に設定を変更する箇所をテンプレート化しておく
- 上記ファイル群をまとめて、GitHubリポジトリに格納しておく
- サービス毎に上記ファイル群(「パッケージ」と呼称)をGitHubリポジトリから取得し、
 テンプレート部分を変更して起動する
挙動的には、aptやnpmのイメージに近いです。
実際に動かしてみよう
kptを使ってnginxを動かせる簡単なサンプルを用意してみましたので、これをベースにkptの使い方を説明します。
ちなみに、同サンプルの構成は以下の通りです。
.
├── README.md
└── nginx
    ├── deployment.yml
    └── service.yml
1. 準備編
1) kptのインストール
こちらからダウンロード・インストールできます。
2) Kptfileの作成
GitHubリポジトリのディレクトリをkptの「パッケージ」として扱えるよう、kpt pkg initコマンドを使用してKptfileを作成します。
kpt pkg init nginx/
コマンド実行後、KptfileとREADME.mdが新たに作成されたことが分かります。
./nginx/
├── Kptfile
├── README.md
├── deployment.yml
└── service.yml
Kptfileの内容は、以下の通りです。
apiVersion: kpt.dev/v1alpha1
kind: Kptfile
metadata:
  name: nginx
packageMetadata:
  shortDescription: sample description
3) Setterの作成
後述するテンプレートに適用するための、サービス毎に設定を変更するデータ項目を、キーバリューペアsetterとして作成します。
具体的には、kpt cfg create-setterコマンドを使用して作成します。
kpt cfg create-setter nginx/ name xxx
(書式)
kpt cfg create-setter ${Kptfileのあるディレクトリ名} ${キー} ${バリュー}
ちなみに、後で度々変更することになるため、この時点でのバリュー部分は、適当な値で大丈夫です。
コマンド実行後、setterがKptfileに追加されたことが分かります。ちなみにsetterには、OpenAPIを採用しています。
apiVersion: kpt.dev/v1alpha1
kind: Kptfile
metadata:
  name: nginx
packageMetadata:
  shortDescription: sample description
openAPI:
  definitions:
    io.k8s.cli.setters.name:
      x-k8s-cli:
        setter:
          name: name
          value: xxx
4) テンプレートの用意
上記setterを適用できるよう、リソースファイル内のサービス毎に設定を変更する箇所を、下記のように書き換えます。
name: xxx # {"$ref":"#/definitions/io.k8s.cli.setters.name"}
ちなみに今回のサンプルでは、以下の項目をsetterとして用意・設定できるようにしてあります。
- name
- image(Dockerイメージ)
5) パッケージの準備完了
上記内容を、GitHubリポジトリにcommit・pushします。これで、上記内容をkptの「パッケージ」として使用できるようになります。
2. 動作確認編
1) パッケージの取得
kpt pkg getコマンドを使用して、上記で先に作成した「パッケージ」をGitHubリポジトリから取得します。
kpt pkg get https://github.com/hageyahhoo/kpt-sandbox.git/nginx@master test
(書式)
kpt pkg get ${GitHubリポジトリ(.gitで終わるもの)}/${使いたいパッケージのあるディレクトリ名}@${使いたいパッケージのあるブランチ名} ${パッケージのダウンロード先ディレクトリ名}
コマンド実行後、指定したディレクトリに、上記で先に作成した「パッケージ」一式がダウンロードされたことが分かります。
./test/
├── Kptfile
├── README.md
├── deployment.yml
└── service.yml
2) テンプレートへの値のセット
kpt cfg setコマンドを使用して、リソースファイル内のテンプレート部分を、当該サービスに適した値に書き換えます。
kpt cfg set test/ name kpt-test
(書式)
kpt cfg set ${パッケージのダウンロード先ディレクトリ名} ${キー} ${バリュー}
"set 7 fields" のように表示されればOKです。
実際にリソースファイルを見ると、下記のように指定した値が設定できていることを確認できます。
name: kpt-test # {"$ref":"#/definitions/io.k8s.cli.setters.name"}
ちなみに今回のサンプルでは、以下の項目を設定して動かすことができます。
- name: 適当
- image: nginx:1.14
3) サービスの起動と動作確認
テンプレートへ値を一通り設定し終えたら、パッケージまるごとkubectl applyコマンドで動かせます。
kubectl apply -R -f test/
今回のサンプルでは、Webブラウザで http://localhost:8080/ にアクセスすると、以下の画面が見られます。
4) サービスの停止
起動時と同様、kubectl deleteコマンドでパッケージまるごとサービスを停止できます。
kubectl delete -R -f test/
5) 補足
実際の運用では、namespaceやサービスの単位で「パッケージ」をダウンロードし、テンプレートへ値を設定し、各パッケージを起動する形となります。
今後解決が必要な課題
本稿執筆時点(2020年4月25日)での、実際に試してみて見つけた課題を列挙します。
1) 1行に複数のテンプレートを定義できない
テンプレートがyamlファイルのコメントであるがゆえの課題です。
helmの{{ namespace }}/{{ サービス名 }} みたいな設定は、現時点では無理です。
2) パッケージの取得・テンプレートへの値のセットの一連の操作が面倒
サービスを複数設定・起動したい場合は、設定ミスの防止と時間短縮の観点から、一連の作業をまとめて実行できるスクリプトを作成することをお勧めします。
まとめ
まだ公開されたてのツールなので、kptだけでできることは少なめです。現時点では、helmやkustomizeと必要に応じて使い分けるのが現実的でしょう。
一方で、基本的な操作がシンプルなこと、この短期間でも機能追加・拡張が行われ続けていること、また公開されたてのツールを早期に試す面白みが味わえるという意味では、追う価値はあるのかなと個人的には思います。
