Upgrade to Pro — share decks privately, control downloads, hide ads and more …

#CNDT2021 Kubernetes コントローラーを手軽に自動テストする / Runni...

riita10069
November 05, 2021

#CNDT2021 Kubernetes コントローラーを手軽に自動テストする / Running e2e tests for Kubernetes controllers in CI with #CNDT2021

Kubernetesのカスタムコントローラーに対する自動テストを記述し、CI上で実行するというテーマでの発表です。
Kubernetesは非常に複雑なコンポーネントで成り立っていて、テストのための環境のポータビリティが低く、CIでも手元のMacでも、複数の開発者のPCでも実行したいという要望に答えるのが難しいです。
それに対する回答として、3つの手段を提案しています。
それが、fake-client, envtest, ket の3つです。
それらの使い方や特徴の違いなどについて説明しています。

Keyword:
client-go, fake, fake-client, envtest, setup-envtest, kind, skaffold, kubectl, e2e, test, ket, Kubernetes, Custom Controller, Operator

登壇内容:
https://event.cloudnativedays.jp/cndt2021/talks/1244

参考:
https://engineering.mercari.com/blog/entry/20210831-f666b94b24/
https://pkg.go.dev/k8s.io/client-go/kubernetes/fake
https://github.com/kubernetes-sigs/controller-runtime/tree/master/pkg/envtest
https://github.com/riita10069/ket
https://mercari.connpass.com/event/227024/

riita10069

November 05, 2021
Tweet

More Decks by riita10069

Other Decks in Technology

Transcript

  1. Kubernetesの拡張性がすごい ,VCFSOFUFT%BUB1MBOF LVCFMFU DPOUBJOFSE $POUBJOFS3VOUJNF*OUFSGBDF $3* SVOD SVOD SVOD 0QFO$POUBJOFS*OJUJBUJWF

    0$* IUUQTPQFODPOUBJOFSTPSH IUUQTLVCFSOFUFTJPCMPHDPOUBJOFSSVOUJNFJOUFSGBDFDSJJOLVCFSOFUFT IUUQTRJJUBDPNNBNPNBNPJUFNTFEECBCGB
  2. Kubernetes API の拡張 Aggregation 
 Layer Custom Resources APIリソースを追加 Kubernetesリソースを追加

    ⾼い⾃由度を誇る 組み込みリソースと同様に IUUQTLVCFSOFUFTJPKBEPDTDPODFQUTFYUFOELVCFSOFUFTBQJFYUFOTJPOBQJTFSWFSBHHSFHBUJPO IUUQTLVCFSOFUFTJPKBEPDTDPODFQUTFYUFOELVCFSOFUFTBQJFYUFOTJPODVTUPNSFTPVSDFT
  3. setup-envtest IUUQTQLHHPEFWTJHTLTJPDPOUSPMMFSSVOUJNFUPPMTTFUVQFOWUFTU • envtest binaries manager • kubeapi-server, etcd, kubectl

    のバイナリを管理 • curl, tarを使うとk8sやこれらのバージョン管理が煩雑 • ポータビリティの向上
  4. envtestの使⽤例 func TestMain(m *testing.M) { os.Exit(func() int { cli, done,

    err := testutil.TestK8SClient( ) if err != nil { fmt.Fprintf(os.Stdout, "failed to create k8s client: %s\n", err ) return 1 } defer done( ) k8sClient = cl i return m.Run( ) }() ) }
  5. envtestの使⽤例 _, file, _, _ := runtime.Caller(0 ) testEnv :=

    envtest.Environment { BinaryAssetsDirectory: filepath.Join(path.Dir(file), "..", "..", "..", "_dev", "bin") , CRDDirectoryPaths: []string{filepath.Join(path.Dir(file), "..", "..", "..", "_kubernetes", “kube-github-operator-api", "apis", "v1alpha1", "crd")} , ControlPlaneStartTimeout: 20 * time.Second , ErrorIfCRDPathMissing: true , AttachControlPlaneOutput: false , KubeAPIServerFlags: []string { "--advertise-address=127.0.0.1" , "--etcd-servers={{ if .EtcdURL }}{{ .EtcdURL.String }}{{ end }}" , "--cert-dir={{ .CertDir }}" , "--insecure-port={{ if .URL }}{{ .URL.Port }}{{else}}0{{ end }}" , "{{ if .URL }}--insecure-bind-address={{ .URL.Hostname }}{{ end }}" , "--secure-port={{ if .SecurePort }}{{ .SecurePort }}{{ end }}", "--disable-admission-plugins=ServiceAccount" , "--service-cluster-ip-range=10.0.0.0/24" , "--allow-privileged=true" , } , } cfg, err := testEnv.Start( ) if err != nil { return nil, nil, fmt.Errorf("failed to start test env: %w", err ) } cli, err := client.New(cfg, client.Options { Scheme: s , })
  6. envtest • Controller-runtimeが提供するテスト⽤のパッケージ • kube-apiserverとetcdのバイナリを実際に⽴てる • kube-apiserverリソース操作のみしか再現できない • Podとしてコントローラーを動作することができない Pros.

    IUUQTCPPLLVCFCVJMEFSJPSFGFSFODFFOWUFTUIUNM IUUQTQLHHPEFWHJUIVCDPNLVCFSOFUFTTJHTDPOUSPMMFSSVOUJNFQLHFOWUFTU IUUQTHJUIVCDPNLVCFSOFUFTTJHTDPOUSPMMFSSVOUJNFUSFFNBTUFSQLHFOWUFTU Cons.
  7. for _, tt := range tests { tt := t

    t t.Run(tt.name, func(t *testing.T) { ctx := context.Background( ) err := kubectl.ApplyAllManifest(ctx, tt.fixture.manifestPaths, false ) for _, expect := range tt.res.A.Items { // check expec t } err = kubectl.DeleteAllManifest(ctx, tt.fixture.manifestPaths, true ) } ) } 1st, Create resources “declaratively” Maybe notify informer of the change. 2nd, Make sure the behavior of the Controller. 3rd, Restore the state of the resource. テストシナリオの実⾏
  8. func (k *Kubectl) ApplyFile(ctx context.Context, filePath string) error { args

    := []string { "apply" , "-f" , filePath , } err := k.Execute(ctx, args ) if err != nil { return err } return ni l } サポートされていないコマンドの作成