Go言語からkubernetes APIを呼び出すクライアント「client-go」の紹介
これはKubernetes2 Advent Calendar 2017 25日目の記事です。この記事ではclient-goというライブラリを使ってgo言語からkubernetesのAPIを呼び出す方法を紹介します。
とりあえず使ってみるところから、任意のkubernetesクラスタにつなぐ方法、service accountを利用した認証方法、テストの書き方まで紹介します。
Client-goとは
Kubernetes APIを叩くためのGo製ライブラリです。おなじみのkubectlコマンドでも使われています。僕の関わっているサービスでは、kubernetes外のサーバーやkubernetes内部のコンテナからkubernetesを操作したいときに使っています。
インストールは、以下のコマンドでできます。
$ go get k8s.io/client-go/...
インストールに関する詳細はドキュメントを参照して下さい。ちゃんと使うならバージョン管理してね、といったことが書かれています。
まずは叩いてみる
以下の例ではPod一覧を取得しています。なお、実行にはkubectlが必要です(後述しますが、client-go利用の際にkubectlが常に必要になるわけではありません)。
まずはnewClient()
でクライアントを生成しています。その際の認証情報は、~/.kube/config
ファイルから取得しています。これはkubectlが作成するファイルで、接続先サーバーや認証情報が格納されています。
その後、client.CoreV1().Pods("").List()
でPod一覧を取得しています。Pods("")
の引数ではnamespaceを指定することができ、空文字列にすると、全namespace指定と同等になります。
実行すると、Pod一覧が出力されます。
$ go run get_started.go kube-addon-manager-minikube kube-dns-6fc954457d-f58rp kubernetes-dashboard-jcjjn
接続先kubernetesクラスタを指定する
先程の例では、kubectlの作成したクラスタ/認証情報を使用しました。kubectlは複数のクラスタが存在する場合でもcontextを切り替えて対応できますが、先程はkubectl config current-context
で得られるcontextを自動的に使うようになっていました。
そこで今度は、contextを指定して任意のクラスタに接続できるようにしてみます。こちらも、実行にはkubectlが必要です。
主に変更したのはnewClient()
です。clientcmd.ConfigOverrides{}
を使用してcontextを指定しています。試したことはないですが接続先サーバーや認証情報の上書きもできるようです。clientcmd.NewDefaultClientConfigLoadingRules()
では、クラスタ/認証情報のロード方法を指定しています。デフォルトでは、~/.kube/config
の情報がロードされます。これらの情報を元にconfigとclientを作成しています。
実行の際は、引数でcontextを指定します。kubectl config get-contexts
で得られるcontext名が指定できます。
$ go run choose_k8s_cluster.go minikube kube-addon-manager-minikube kube-dns-6fc954457d-f58rp kubernetes-dashboard-jcjjn
Kubernetes内部のPodからAPIを叩く
ここまでの例では、kubectlの作成したクラスタ/認証情報を使用してクライアントを作成していました。kubectlが利用できる環境ではここまでの方法でも良いですが、kubernetes内部のPodからAPIを叩くような場合には、kubectlがインストールされていないことがあります。
そのような場合、kubernetesがPodに対して付与するservice accountを使うと便利です。Service accountについてはこのドキュメントが詳しいです。
主に変更したのはnewClient()
です。rest.InClusterConfig()
でservice accountを利用するための設定をしています。/var/run/secrets/kubernetes.io/serviceaccount/
以下のトークンや証明書が使われます。
Pod内のコンテナにログインして実行すると、~/.kube/config
のない環境でもPod一覧を取得できることがわかります。
(もしパッケージがない旨のエラーが出たら、client-goをインストールして下さい)
root@golang:/go# ls ~/.kube ls: cannot access '/root/.kube': No such file or directory root@golang:/go# go run in_cluster_client.go golang kube-addon-manager-minikube kube-dns-6fc954457d-f58rp kubernetes-dashboard-jcjjn
テストを書く
最後にテストを書いてみます。client-goに含まれるfakeパッケージを使用すると、テスト用のデータを予め仕込んだ上で各種APIを叩くことができます。
newClient()
でのクライアント作成はfake.NewSimpleClientset()
を呼ぶだけになりました。addTestData()
でテスト用のPodを作成していますが、方法は非テストコードでPodを作成する場合と同じです。今回は省略しましたが、ここでPodの状態や各種ポリシーを設定することもできます。
実行すると、作成したテスト用Podが出力されることがわかります。
$ go run normal_case_test.go test
今度は、kubernetes APIがエラーを返す場合のテストを書いてみます。
setServerError()
でAPI呼び出し時にエラーを返すようにしています。テスト用クライアントは内部にReactionChain
と呼ばれるハンドラリストをもっていて、先頭のハンドラから順番にリクエストを処理していきます。上記のコードでは常にエラーを返すハンドラを先頭に挿入しているので、API呼び出しがエラーを返すようになります。ちなみに、PrependReactor()
の第一引数でverb、第二引数でresourceを指定できるので、第一引数をlist
、第二引数をpods
とすれば、Pod一覧取得のときだけエラーを返すようになります。
実行すると、Pod一覧を取得するAPIがエラーを返して終了します。
$ go run error_case_test.go 2017/12/22 13:03:08 server error exit status 1
まとめ
この記事ではclient-goの使い方について簡単に紹介しました。ドキュメントはそれほど充実していないですが、kubectlで使われているだけあって、やりたいことは大体できる印象です。Kubernetes APIを使うときはぜひ利用を検討してみて下さい。