TOP

K8s python 实现 CRD 相关操作

概述

CRD 概述

K8s 中内置了很多的资源类型, 包括 pod,svc,deploy 等等

crd 是 K8s 允许用户自定义的一种资源格式.  定义好之后的使用体验如同 其他内置资源

crd 本质上也是操作通过apiserver 去操作 etcd, 带有基本的增删改查概念, 如果需要更丰富的功能则需要自己手动实现 operator

operator 目前官方未提供 python 相关的 sdk, 但是基础的 增删改查在官方的 sdk 中已实现

CR 概述

CRD 可以理解为 class 而 CR 则是 CRD 的实例化

CRD 定义了 CR 的格式和属性, 而 CR 则可以对各属性进行定制和重载

实现

官方示例

点击这里

完整示例

在 init 阶段链接集群(通过代码的字符串创建临时文件写入配置), 集群的配置文件在  ~/.kube/config  内, 将这个内容完全拿出来即可

在 init 阶段创建CRD(CRD 只需要创建一次即可)

通过API 调用 CR 的增删改查, 并启用 watch 监控 CR 的状态信息

# -*- coding:utf-8 -*-
import tempfile
import time

from kubernetes.client import api_client
from kubernetes import config, dynamic, watch
from kubernetes.dynamic.exceptions import ResourceNotFoundError


class CRD(object):
    def __init__(self, name=None, res_id=None, phase=None, state=None):
        self.client = None
        self.crd_api = None
        self.flows_api = None
        self.ns = "default"
        self.cr_body = {
            "apiVersion": "flow.yangtuo.com/v1",
            "kind": "FlowPost",
            "metadata": {
                "name": name,
            },
            "spec": {
                "resourceid": res_id,
            },
            "status": {
                "phase": phase,
                "state": state
            }
        }
        self.init()

    def init(self):
        conf = self.get_conf()
        self.client = dynamic.DynamicClient(
            api_client.ApiClient(configuration=config.load_kube_config(config_file=conf)))
        self.crd_api = \
            self.client.resources.get(api_version="apiextensions.k8s.io/v1", kind="CustomResourceDefinition")
        try:
            self.flows_api = self.client.resources.get(api_version="flow.yangtuo.com/v1", kind="FlowPost")
        except ResourceNotFoundError as e:
            print(e)
            self.create_crd()
            time.sleep(2)
        finally:
            self.flows_api = self.client.resources.get(api_version="flow.yangtuo.com/v1", kind="FlowPost")

    @staticmethod
    def get_conf():
        conf = tempfile.mktemp()
        with open(conf, 'w') as f:
            f.write("""apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: ...
    server: https://....:6443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    user: kubernetes-admin
  name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
  user:
    client-certificate-data: ....
    client-key-data:....""")
        f.close()
        return conf

    # 创建 crd
    def create_crd(self):
        try:
            crd_res = self.crd_api.create({
                "apiVersion": "apiextensions.k8s.io/v1",
                "kind": "CustomResourceDefinition",
                "metadata": {
                    "name": "flowposts.flow.yangtuo.com",
                },
                "spec": {
                    "group": "flow.yangtuo.com",
                    "scope": "Namespaced",
                    "names": {
                        "kind": "FlowPost",
                        "singular": "flowpost",
                        "plural": "flowposts",
                        "listKind": "FlowPostList",
                        "shortNames": ["fp"],
                    },
                    "versions": [
                        {
                            "name": "v1",
                            "served": True,
                            "storage": True,
                            "schema": {
                                "openAPIV3Schema": {
                                    "type": "object",
                                    "properties": {
                                        "spec": {
                                            "type": "object",
                                            "properties": {
                                                "resourceid": {"type": "string"},
                                            }
                                        },
                                        "status": {
                                            "type": "object",
                                            "properties": {
                                                "phase": {"type": "string"},
                                                "state": {"type": "string"},
                                            }
                                        },
                                    }
                                },
                            }
                        }
                    ],
                },
            })
            print(f"{crd_res.spec.scope} - {crd_res.metadata.name}")
            print("create_flows_crd success")
        except Exception as e:
            # print(e)
            return "create_crd  end ~~~~!"

    def get(self):
        res = self.flows_api.get()
        for item in res.items:
            print(f"name:{item.metadata.name}  "
                  f"res_id: {item.spec.resourceid}  "
                  f"state: {item.status.state}")
        return res

    def patch_cr(self, state):
        self.cr_body["status"]["state"] = state
        self.flows_api.patch(body=self.cr_body, content_type="application/merge-patch+json", namespace=self.ns)

    def create_cr(self):
        return self.flows_api.create(body=self.cr_body, namespace=self.ns)

    def delete_cr(self, name=None):
        self.flows_api.delete(name, namespace=self.ns)

    def watch(self):
        watcher = watch.Watch()
        for e in self.flows_api.watch(resource_version=0, namespace=self.ns, watcher=watcher):
            print("get new event !!! ", e['object'].metadata.name, e['type'], e['object'].status.phase)
            if e['object'].status.phase == "finished":
                print(f"cr: {e['object'].metadata.name} is finished, over")
                print("let start job (create cvm)....")
                print("creating ... ")
                print("job is done")
                # watcher.stop()


if __name__ == '__main__':
    c = CRD("No.xxxxxxx1234", "instance-dsdax20", "phase_1", "pending")
    c.create_cr() 
    c.patch_cr("finished")
    c.delete_cr()
    c.get()

crd 的创建也可以通过 yaml 的形式 创建, 因为 CRD 是只需要创建一次的, 如果确认可部署集群的话可以提前在集群内导入

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: flowposts.flow.yangtuo.com
spec:
  group: flow.linklogis.com
  scope: Namespaced
  names:
    kind: FlowPost
    singular: flowpost
    plural: flowposts
    listKind: FlowPostList
  versions:
  - name: v1
    served: true
    storage: true
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec:
            type: object
            properties:
              resourceid:
                type: string
          status:
            type: object
            properties:
              phase:
                type: string

 

posted @ 2022-02-10 11:05  羊驼之歌  阅读(1554)  评论(0编辑  收藏  举报