概述
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