Kubernetes の Go API クライアントライブラリを使って Kubernetes を直接操作する

Posted on
qiita Go kubernetes

この記事はQiitaの記事をエクスポートしたものです。内容が古くなっている可能性があります。

2016/11/15 10:15 追記

この記事では kubernetes/kubernetes リポジトリに含まれているクライアントライブラリを紹介していますが、今年の8月だか9月になって API クライアントだけが別リポジトリとして切り出されました。

https://github.com/kubernetes/client-go

今後何かツールを作るときは、この client-go を使うのがよいでしょう。

というわけで、以下の内容は__記事初公開時点の、client-go がなかった時代の__ものとなっております。その点ご留意いただいた上でお読みください。

追記終わり


あまり知られてないようですが、Kubernetes には公式の Go 製 API クライアントライブラリがあります。kubectl もこのライブラリを用いて実装されています。

https://github.com/kubernetes/kubernetes/tree/master/pkg/client/

kubectl は確かに万能なんですが、実運用に投入するとなるとその万能さがマイナスに効いてくることもあります。で、自分たちが使いやすいように kubectl をラップした何かを作りたくなるのですが、他の言語から kubectl をサブコマンド呼び出しするのは筋が悪いです。API ライブラリを使ってネイティブレベルで Kubernetes を操作するようにしましょう。

いきなりサンプルコード

というわけで、Pod の名前一覧を表示するだけのサンプルコードです。

package main

import (
	"fmt"
	"os"

	"k8s.io/kubernetes/pkg/api"
	client "k8s.io/kubernetes/pkg/client/unversioned"
	"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
)

func newKubeClient() (*client.Client, error) {
	loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
	loadingRules.ExplicitPath = clientcmd.RecommendedHomeFile

	loader := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, &clientcmd.ConfigOverrides{})

	clientConfig, err := loader.ClientConfig()

	if err != nil {
		return nil, err
	}

	kubeClient, err := client.New(clientConfig)

	if err != nil {
		return nil, err
	}

	return kubeClient, nil
}

func main() {
	kubeClient, err := newKubeClient()

	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	pods, err := kubeClient.Pods(api.NamespaceDefault).List(api.ListOptions{})

	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	for _, pod := range pods.Items {
		fmt.Println(pod.Name)
	}
}

出力は以下のようになります。

$ go run listpods.go
hello-world-e2d3x
wordpress-mysql-488205646-t6v4k

ちなみに kubectl get pods だとこうなります。

$ kubectl get pods
NAME                              READY     STATUS    RESTARTS   AGE
hello-world-e2d3x                 1/1       Running   0          8d
wordpress-mysql-488205646-t6v4k   1/1       Running   0          8d

コード解説

API クライアントインスタンスの作成

最初に、ローカルのコンフィグファイルを読み込みます。

	loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
	loadingRules.ExplicitPath = clientcmd.RecommendedHomeFile

	clientConfig, err := loader.ClientConfig()

	if err != nil {
		return nil, err
	}

	kubeClient, err := client.New(clientConfig)

	if err != nil {
		return nil, err
	}

loadingRules.ExplicitPath にコンフィグファイルのパスを指定します。定数 RecommendedHomeFile~/.kube/config を指していますkubectl がデフォルトで見に行くパスですね。 kubectl --kubeconfig /path/to/kubecfg のようにパスを明示的に指定したい場合は、

	loadingRules.ExplicitPath = /path/to/kubecfg

にそのパスを代入すればよいです。

API を叩く

kubeClient.リソース.操作 の形になっています。

    pods, err := kubeClient.Pods(api.NamespaceDefault).List(api.ListOptions{})

まず PodsSecrets のように操作対象リソースを指定します。引数には Namespace を指定します。自分で指定することもできますが、api.NamespaceDefaultapi.NamespaceSystem のように定数も用意されてます。 続いて操作内容を指定します。名前を指定して Pod を取得するなら Get(name) ですし、全部の Pod を撮りたいなら List() です。

得られた Pod 一覧の中身を出力する

	for _, pod := range pods.Items {
		fmt.Println(pod.Name)
	}

実際の配列は pods ではなく pods.Items に格納されています。

注意

k8s.io/kubernetes は Kubernetes 本体のリポジトリなので、API クライアントを import するには Kubernetes のソースコード (+ 依存リポジトリ、docker/docker とか) を全部落としてくる必要があります。数百 Mbyte あるので、Godeps みたいにリポジトリへ vendor を含める場合は要注意です。glide 使いましょう。

おわりに

Kubernetes の Go API クライアントライブラリを用いて、Go から直接 Kubernetes を操作する手法を紹介しました。最初に書き方さえ覚えてしまえば、あとはどのリソースや操作に対しても比較的簡単に実装できると思います。 自分は最近、このライブラリを使って k8sec というツールを作りました。k8sec は Heroku の config のように、k8sec set key1=val1 key2=val2 の形で Kubernetes の Secret を管理できるコマンドラインツールです。あわせてご覧 & ご利用ください。

REF