2021年3月16日火曜日

Python で kubernetes を操作する超入門

概要

kubernetes の API をコールするのに公式の Python クライアントがあります
今回は超入門ということで redis の Pods を k8s 上に構築してみました

環境

  • kubernetes v1.19.3
  • Python 3.8.3
  • pipenv 2020.8.13

インストール

  • pipenv install kubernetes

進め方

リファレンスを読みながら API をコールするための yaml 情報を Python で構築いく感じになります
フィールドがオブジェクトだったり dict だったりするのでそれをリファレンスで確認して何を使用するのか指定するのかを確認しながらコーディングしていくとやりやすいと思います

まずはバージョンを取得する

  • vim show_version.py
from kubernetes import client, config

config.load_kube_config()

v1 = client.VersionApi()
print(v1.get_code())
  • pipenv run python show_version.py

redis の PersistentVolumeClaim を作成する

storageClass は nfs を使って事前に作成しておきます
https://hawksnowlog.blogspot.com/2021/03/how-to-use-nfs-as-storageclass-server-on-kubernetes.html

  • vim apply_pvc.py
from kubernetes import client, config

config.load_kube_config()

api_instance = client.CoreV1Api()
body = client.V1PersistentVolumeClaim()
namespace = "default"
body.metadata = client.V1ObjectMeta(
  name="pvc1"
)
body.spec = client.V1PersistentVolumeClaimSpec(
  access_modes = [
    "ReadWriteOnce"
  ],
  resources = client.V1ResourceRequirements(
    requests = {
      "storage": "100Mi"
    }
  ),
  storage_class_name = "nfs",
)

api_response = api_instance.create_namespaced_persistent_volume_claim(namespace, body)
print(api_response)
  • pipenv run python apply_pvc.py
  • kubectl get pvc pvc1
NAME   STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS       AGE
pvc1   Bound    pvc-b0386fce-8745-4e24-9cbe-e79b6602e671   100Mi      RWO            nfs                15s

redis の Deployment を作成する

長いですが Pod spec なども同じ用に作成するだけです

  • vim apply_deploy.py
from kubernetes import client, config

config.load_kube_config()

api_instance = client.AppsV1Api()
body = client.V1Deployment()
namespace = "default"
body.metadata = client.V1ObjectMeta(
  name="redis"
)
body.spec = client.ExtensionsV1beta1DeploymentSpec(
  replicas = 1,
  selector = client.V1LabelSelector(
    match_labels = {
      "name": "redis"
    }
  ),
  template = client.V1PodTemplateSpec(
    metadata = client.V1ObjectMeta(
      labels = {
        "name": "redis"
      }
    ),
    spec = client.V1PodSpec(
      containers = [
        client.V1Container(
          image = "redis:6",
          name = "redis",
          volume_mounts = [
            client.V1VolumeMount(
              mount_path = "/data",
              name = "pvc1"
            )
          ]
        )
      ],
      restart_policy = "Always",
      volumes = [
        client.V1Volume(
          name = "pvc1",
          persistent_volume_claim = client.V1PersistentVolumeClaimVolumeSource(
            claim_name = "pvc1"
          )
        )
      ]
    )
  )
)

api_response = api_instance.create_namespaced_deployment(namespace, body)
print(api_response)
  • pipenv run python apply_deploy.py
  • kubectl get pod redis-6965c4dcd7-7mptl
NAME                     READY   STATUS    RESTARTS   AGE
redis-6965c4dcd7-7mptl   1/1     Running   0          9m31s

redis の Service を作成する

NodePort を使ってアクセスします

  • vim apply_svc.py
from kubernetes import client, config

config.load_kube_config()

api_instance = client.CoreV1Api()
body = client.V1Service()
namespace = "default"
body.metadata = client.V1ObjectMeta(
  name="redis-svc"
)
body.spec = client.V1ServiceSpec(
  type = "NodePort",
  selector = {
    "name": "redis"
  },
  ports = [
    client.V1ServicePort(
      name = "6379",
      port = 6379,
      target_port = 6379,
      protocol = "TCP"
    )
  ]
)

api_response = api_instance.create_namespaced_service(namespace, body)
print(api_response)
  • pipenv run python apply_svc.py
  • kubectl get svc redis-svc
NAME        TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
redis-svc   NodePort   10.105.106.45   <none>        6379:31806/TCP   5s

動作確認

  • redis-cli -h 192.168.100.10 -p 31806

おまけ: yaml からリソースを作成する

  • vim from_file.py
from kubernetes import client, config, utils

config.load_kube_config()
k8s_client = client.ApiClient()
ret = utils.create_from_yaml(k8s_client, "./pvc.yml")
print(ret)

最後に

慣れればリファレンス片手に簡単にコーディングできるようになると思います
動的に変わるようなマニフェストを作成したい場合やテンプレート化して管理したい場合に使えます

0 件のコメント:

コメントを投稿