kubernetes clientでpodの状態を確認する

# kubernetes clientでpodの状態を確認する

`kubectl`コマンドでも確認できるのですが、久々にプログラミングをしたくなったので、
kubernetes clientを使って標記の件をやってみました。

## kubernetes client

公式ドキュメントの[client libraries](https://kubernetes.io/docs/reference/using-api/client-libraries/)にクライアントライブラリ一覧が記載されています。

この記事を書いている時点の情報ですが、オフィシャルサポートとなっているクライアントの言語は、GO/python/java/C#/javascriptの5種類。
せっかくの機会なので未経験のpythonでやってみることにします。

## クライアントを使ってやってみること

podの情報を取得し、そこからkafka brokerコンテナの情報を出力する。
`kubectl get <pod-name> -n <namespace> -o json`で取得可能な情報をkubernetes clientで同じようにやってみる感じです。

## podの作成
kubernetesの[helm](https://helm.sh/)を使ってpodを作ります。
helmでのdeployは、特に拘りはないのですが[kafka](https://kafka.apache.org/)をチョイス。
kafka用のhelm chartは[こちら](https://github.com/helm/charts/tree/master/incubator/kafka)を利用しました。
デフォルトの設定から一部変更し、brokerの数を1、jmx-exporterをenableにし、1pod-2containerの構成に変更。

```
$ helm install -n kafka incubator/kafka -f values.yaml --namespace kafka
```

投入コマンドはこんな感じですが、[helm](https://helm.sh/)は本記事の趣旨ではないので説明は割愛します。

## podの状態確認

```
$ kubectl get pod kafka-0 -n kafka
NAME      READY     STATUS    RESTARTS   AGE
kafka-0   2/2       Running   1          5m
```

無事に起動。

## サンプルプログラム

```python
#!/usr/bin/env python                                                     
                                                                          
import os                                                                 
from kubernetes import client, config                                     
from kubernetes.client.rest import ApiException                           
                                                                          
################################################################          
                                                                          
config.load_kube_config(os.path.join(os.environ["HOME"], '.kube/config')) 
v1 = client.CoreV1Api()                                                   
                                                                          
namespace = 'kafka'                                                       
label = 'app=kafka'                                                       
                                                                          
try:                                                                      
  pod_list = v1.list_namespaced_pod(namespace, label_selector=label)      
except ApiException as e:                                                 
  print('Exception when calling CoreV1Api->list_namespaced_pod: %s\n' % e)
                                                                          
for pod in pod_list.items:                                                
  for container in pod.spec.containers:                                   
    if container.name == 'kafka-broker':                                  
      print container
```

以下は簡単な説明。

### kubernetesのconfigファイル読み込み
```python
config.load_kube_config(os.path.join(os.environ["HOME"], '.kube/config')) 
```
引数にはconfigファイルのパスを指定。

### podの取得
```python
namespace = 'kafka'                                                       
label = 'app=kafka'

try:                                                                 
  pod_list = v1.list_namespaced_pod(namespace, label_selector=label)      
```
`kubectl get pod -n kafka -l app=kafka -o json`と同じようなイメージです。
利用したhelm chartでは、kafka podにはラベル`app=kafka`が付与されます。

### コンテナ情報の参照
```python
for pod in pod_list.items:                                                
  for container in pod.spec.containers:                                   
    if container.name == 'kafka-broker':                                  
      print container
```
なんかネストが深いのでちょっと微妙な感じがします...
今回は[list_namespaced_pod](https://github.com/kubernetes-client/python/blob/master/kubernetes/docs/CoreV1Api.md#list_namespaced_pod)関数を使いましたが、左記リンクのresponseに書かれている情報を見れば、どのような構造で値が返ってくるか読み取れます。
`kubectl get pod -n kafka -l app=kafka -o json`に馴染みがある人はそちらの構造をそのまま辿っていただければ見たい情報に辿り着けると思います。
今回はkafka用のポッド内には、brokerのコンテナとprometheusのexporter用のコンテナの2つがありますので、brokerのコンテナのみ出力するためにコンテナ名で判定しています。

## 出力結果
```
{'args': None,
 'command': ['sh',
             '-exc',
             'unset KAFKA_PORT && \\\nexport KAFKA_BROKER_ID=${HOSTNAME##*-} && \\\nexport KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://${POD_IP}:9092 && \\\nexec /etc/confluent/docker/run\n'],
.
.
.
(略)
```
こんな感じで出力されます。