Engineer in Tokyo

Kubernetes Python クライアントを使ってみる

この記事は pyspa Advent Calendar 2016 の第2日目の記事。第1目はakisuteさんの「今年の話」だった。

「斧さんの記事凄かった。pyspa の二日目の人まじかわいそう」というかわいそうなイアンです。よろしくです。

私はGoogleに入ってもうすぐ2年が経つのですが、今年はコンテナオーケストレーションシステムのKubernetesをだいぶ触るようになった。と同時にPythonを使うシーンが結構減ってしまったんですけど、今回は両方使うことにした。

Kubernetesはなんっすか

みんなDocker触ったことあるけど、Kubernetesなんで触ったことない人がまだ結構いると思うけど、ちょっと説明してみる。Kubernetesは今までやっていたことを自分なりに自動化したものだと考えるといい。今まで、chefやansibleでウェブアプリをサーバーにダウンロードして起動してsupervisordか何かの方法で監視して、その前にロードバランサを作って外からアクセスすることができるようにしたと思う。sshを使わないし、内部でやっていることがだいぶ違うけど、ハイレベルで考えるとKubernetesはアプリのパッケージフォーマットとしてDockerイメージを使って以前にchefやansibleでやったことをAPIでできるようにしているもの。

簡単な例ですが、nginxをデプロイしてみる。KubernetesのAPIを簡単に使えるためにkubectlというCLIがあります。

$ kubectl run nginx --image=nginx:1.10 --replicas=5
deployment "nginx" created

こうするとnginxのをデプロイするためにDeploymentを作ります。これでKubernetesクラスタの中でnginx:1.10をDocker Hubからダウンロードして、nginxのコンテナを5台起動する。以下のコマンドで確認できる。

$ kubectl get deployments
NAME      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx     5         5         5            5           54s

$ kubectl get pods
nginx-527866857-1o78v   1/1       Running            0          54s
nginx-527866857-l0z3f   1/1       Running            0          54s
nginx-527866857-lub8r   1/1       Running            0          54s
nginx-527866857-rdvgf   1/1       Running            0          54s
nginx-527866857-w12s7   1/1       Running            0          54s

kubectlがKubernetesのREST API経由でDeploymentを作ったことで、アプリをデプロイした。もちろん、APIでアプリコンテナを数を増やしたり、減らしたりすることもできるし、アプリを完全に削除することもできる。

外からアクセスしたい時はServiceを作れば、クラスタの外からアクセスすることができる。GCPやAWSを使っている場合は、クラウドのAPIと連動してロードバランサを作ってくれます。

$ kubectl expose deployment nginx --type=LoadBalancer --port=80
service "nginx" exposed

$ kubectl get svc
NAME         CLUSTER-IP       EXTERNAL-IP       PORT(S)   AGE
kubernetes   10.239.240.1     <none>            443/TCP   57d
nginx        10.239.249.220   104.155.215.220   80/TCP    1m

$ curl -s http://104.155.215.220/ | grep title
<title>Welcome to nginx!</title>

そして、Deploymentだけじゃなくて、設定をもつConfigMapSecretもあるし、永住ストーレッジのPersistentVolumeもあるし、必要なものはたいていあって全部APIから制御できる。

PythonからAPIを触ってみる

KubernetesはREST APIを提供しているので、基本的にどの言語でもKubernetesクラスタを制御できる。私の一番好きな言語の一つがPythonだし、最近新しい正式Pythonクライアントが kubernetes-incubatorに出たので、使ってみようと思う。

インストールはいつもどおりpipを使う

pip install kubernetes

そうしたら、わりと簡単にAPIを使える。以下のアプリはdefault名前空間のポッドの名前、ステータス、IPアドレスを表示する。

import os
from kubernetes import client, config

config.load_kube_config(
    os.path.join(os.environ["HOME"], '.kube/config'))

v1 = client.CoreV1Api()

pod_list = v1.list_namespaced_pod("default")
for pod in pod_list.items:
    print("%s\t%s\t%s" % (pod.metadata.name,
                          pod.status.phase,
                          pod.status.pod_ip))

実行すると

$ python list_pods.py
nginx-2048367498-2000v  Running 10.236.2.16
nginx-2048367498-a4otw  Running 10.236.0.15
nginx-2048367498-eblzn  Running 10.236.1.20
nginx-2048367498-tqy6j  Running 10.236.2.17
nginx-2048367498-zwkfg  Running 10.236.0.16

このクライアントはKubernetesのswaggerスペックから生成しているっぽいので、基本的にAPIの全部のエンドポイントに対応している。

すべてのオブジェクトタイプをウォッチすることもできる。なにかのオブジェクトが変更されたらイベントを拾って何か処理する。

import os
from kubernetes import client, config, watch

config.load_kube_config(
    os.path.join(os.environ["HOME"], '.kube/config'))

v1 = client.CoreV1Api()

stream = watch.Watch().stream(v1.list_namespaced_pod, "default")
for event in stream:
    print("Event: %s %s" % (event['type'], event['object'].metadata.name))
$ python watch_pods.py
Event: ADDED nginx-2048367498-zwkfg
Event: ADDED nginx-2048367498-2000v
Event: ADDED nginx-2048367498-a4otw
Event: ADDED nginx-2048367498-eblzn
Event: ADDED nginx-2048367498-tqy6j
Event: MODIFIED nginx-2048367498-a4otw
Event: MODIFIED nginx-2048367498-zwkfg

まとめ

このところまで読んだら「んじゃ、APIで何ができる?なんのメリットある?」って思っているかもしれない。APIの上に作れるものは幅広いんだけど、便利なUI (例: dashboard)や、CIシステムのパイプライン(例: fabric8)や、監視ツールや、フルフルなPaaS(例: Deis, OpenShift)、やserverless的なFaaS(Function as a Service, 例: fission.io, funktion)が作れるだろう。

client-pythonをインストールして、Pythonでアプリを作ってみよう。もし、興味がある方は Kubernetes Slackチャンネルにジョインすると、他のKubernetes開発者と話せる。Pythonクライアントを担当しているのが #sig-api-machinery というチャンネルですが、英語得意じゃない方はぜひ #jp-users にジョインしていただけると幸い