概要

k8sのリソースをCRUDする代表的な手順と言えば公式のライブラリであるclient-goですね。 これは deployment なんかのk8sのデフォルトであるリソースや、client-go で生成されたコードを使うCRDの場合には簡単に使えて便利なんですが、カスタムコントローラーを作るのに一般的に使われるkubebuilderは内部的にcontroller-runtimeってツールを使ってます。これが生成するpkgは client-go と互換性が無い1ので自作したカスタムリソースの操作を client-go からじゃできないです。

解決策は kubebuilder で作られたCRDのリソースの操作には client-go じゃなくて直接 controller-runtime を使うことらしいです。
なので controller-runtime をkubebuilderで生成したカスタムコントローラー外から使う方法を記します。

なお、良い例を見つけることができなかったので以下では基本的に私のコードを使って解説します。

具体的に

では実際にコードを書きましょう。

ライブラリ

まず必要になるライブラリをimportします。

 4import (
 5	"context"
 6	"fmt"
 7	"log"
 8	"net/http"
 9	"net/http/httputil"
10	"os"
11
12	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
13	"k8s.io/apimachinery/pkg/runtime"
14
15	"sigs.k8s.io/controller-runtime/pkg/client"
16	"sigs.k8s.io/controller-runtime/pkg/client/config"
17
18	escv1alpha1 "github.com/koba1t/ESC/api/v1alpha1"
19)

controller-runtime のクライアントライブラリだけでなく、k8s公式のクライアントライブラリもschemeObjectの定義を利用するために必要です。

Schemeの設定

次にSchemeの設定をしましょう。
このSchemeはk8sのAPIオブジェクトをgolangの構造体にマッピングしたりするために使われます。

22var (
23	scheme = runtime.NewScheme()
24)
25
26func init() {
27	// init scheme
28	_ = escv1alpha1.AddToScheme(scheme)
29}

k8sのライブラリを使ってschemeを新しく生成します。
ここで生成したschemeにはCRDのリソースを扱う機能がまだ入っていないので、CRD側のライブラリで追加します。

clientの作成

次に k8sのリソースを操作するためのクライアントをcontroller-runtime のライブラリ から作成しましょう。

54cl, err := client.New(config.GetConfigOrDie(), client.Options{Scheme: scheme})

k8s内で動かす場合は GetConfigOrDie() を使うことで kube-apiserver にアクセスするための kubeconfig を自動で設定してくれます。
ここで、client.New の際に client.Options{Scheme: scheme} を指定して、今回使用するCRDを追加したschemeを設定するのを忘れないようにしてください。これを指定しないとCRDのリソースが操作できません。2

k8sリソースの作成

後は作りたいリソースのObjectの形式の構造体を組み立てて、先程作成したクライアントでCreateするだけです。

86		escuser := &escv1alpha1.Userland{
87			ObjectMeta: metav1.ObjectMeta{
88				Namespace: namespaceName,
89				Name:      username,
90			},
91			Spec: escv1alpha1.UserlandSpec{
92				TemplateName: escTemplateName,
93			},
94		}
95
96		e := cl.Create(context.Background(), escuser)
97		if e != nil {
98			fmt.Printf("Userland create error: %v\n", e)
99		}

これで実際にkubernetesのリソースが作成されます。

k8sで動かすには

ちなみにCRDに限らずk8sのオブジェクトを操作するためには権限が必要になるので、Roleを作ってRoleBindingしたServiceAccountをコードを動かすコンテナから使えるようにする必要があります。

まとめ

kubebuilderで生成したCRDをcrudしようとした時、参考になる文献が無くてこまったので書きました。3
誰かの助けになれば幸いです。

参考


  1. これはcontroller-runtimeclient-go互換のinterfaceを作成しないのが原因なんですが、kubebuilderのissueにこう書かれているので今後もサポートしそうにないですね。 ↩︎

  2. 私はこれを忘れて半日溶かしました ↩︎

  3. コントローラの外から使うという需要がそもそも無いのかもしれない。 ↩︎