client-goを使ってKubernetesのAPIに触れた
client-goとは
KubernetesのAPIを実行するためのgoのモジュールです。
Kubernetesの拡張にも使われてます。
ゼロから始めるKubernetes Controller / Under the Kubernetes Controller - Speaker Deck
これ以降は実際に使ってみた内容です。
筆者はgo初心者であるため初歩的なセットアップからつまずきながら進めました。
client-goを使ってみる
client-go/examples/out-of-cluster-client-configuration at master · kubernetes/client-go · GitHub
client-goのリポジトリに使用例があります。
Authenticating outside the clusterを動かしてみます。
client-goをインストールする
環境の前提としてmacOSを利用しています。
goをインストールします。
Downloads - The Go Programming Language
$GOPATHの配下に作業ディレクトリを配置する必要があるので以下のようにしました。
$ export GOPATH=$HOME/go $ pwd [Home Directory]/go/src/github.com/hi1280/out-of-cluster-client-configuration
client-goのインストールについてはこちらに書いてあります。
client-go/INSTALL.md at master · kubernetes/client-go · GitHub
goのversionが1.11以降からはgo modulesというモジュール管理の仕組みを使うことになったようなので、それに基づいてセットアップします。
Enabling go modulesの項にある通りに以下のコマンドを実行します。
$ export GO111MODULE=on $ go mod init
go.modというファイルが作成されます。
client-goをインストールします
$ go get k8s.io/client-go@master
コードを書く
使用例をほぼコピーしました。
podの数と該当のpodがあるかどうかを出力するプログラムです。
pod名は適宜自身の環境に合わせて変更する必要があります。
// Note: the example only works with the code within the same release/branch. package main import ( "flag" "fmt" "os" "path/filepath" "time" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/clientcmd" // // Uncomment to load all auth plugins _ "k8s.io/client-go/plugin/pkg/client/auth" // // Or uncomment to load specific auth plugins // _ "k8s.io/client-go/plugin/pkg/client/auth/azure" // _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" // _ "k8s.io/client-go/plugin/pkg/client/auth/oidc" // _ "k8s.io/client-go/plugin/pkg/client/auth/openstack" ) func main() { var kubeconfig *string if home := homeDir(); home != "" { kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file") } else { kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file") } flag.Parse() // use the current context in kubeconfig config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig) if err != nil { panic(err.Error()) } // create the clientset clientset, err := kubernetes.NewForConfig(config) if err != nil { panic(err.Error()) } for { pods, err := clientset.CoreV1().Pods("").List(metav1.ListOptions{}) if err != nil { panic(err.Error()) } fmt.Printf("There are %d pods in the cluster\n", len(pods.Items)) // Examples for error handling: // - Use helper functions like e.g. errors.IsNotFound() // - And/or cast to StatusError and use its properties like e.g. ErrStatus.Message namespace := "default" pod := "nginx-deployment-54f57cf6bf-j6sxf" _, err = clientset.CoreV1().Pods(namespace).Get(pod, metav1.GetOptions{}) if errors.IsNotFound(err) { fmt.Printf("Pod %s in namespace %s not found\n", pod, namespace) } else if statusError, isStatus := err.(*errors.StatusError); isStatus { fmt.Printf("Error getting pod %s in namespace %s: %v\n", pod, namespace, statusError.ErrStatus.Message) } else if err != nil { panic(err.Error()) } else { fmt.Printf("Found pod %s in namespace %s\n", pod, namespace) } time.Sleep(10 * time.Second) } } func homeDir() string { if h := os.Getenv("HOME"); h != "" { return h } return os.Getenv("USERPROFILE") // windows }
clientsetオブジェクトを生成することで、KubernetesのAPIを実行できることが分かります。
実行する
go buildして実行します。
$ go build -o app . $ ./app There are 9 pods in the cluster Pod nginx-deployment-54f57cf6bf-j6sxf in namespace default not found
応用して作ったもの
client-goを使ってkubernetes向けのCLIツールを作りました。
擬似的なpatchを適用することでdeploymentの更新を実行します。
image tagは変えたくないけど、imageを更新したいという場合の使用を想定しています。
と、作ってみたものの同様のものが公式のkubectlで既に実装済みでした。
やり方もほぼ一緒なので、kubectlのバージョンさえ上げれば、kubernetesクラスタのバージョンはあまり気にしなくて良さそうです。
まとめ
client-goを使うことで、KubernetesのAPIをプログラムから扱うことができました。
ただclient-goのドキュメントはあまりないので、APIのリファレンスを見ながら、それっぽいAPIを呼び出すというコーディングが必要になるかと思います。
https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/
Kubernetes向けのツールはOSSになっているものが多いので、それらを参考にすると良いかもしれません。