之前建立和管理CRD的client库位于:github.com/kubernetes/…git
好比定义一个目录api/types/v1alpha1,里面是关于types的一些定义文件;github
metav1.ObjectMeta 类型会包含典型的任意的Kubernetes资源的metadata属性,如name, namespace, labels, annotations。json
被Kubernetes API定义的全部资源对象、类型都须要实现k8s.io/apimachinery/pkg/runtime.Object这个接口定义,这个接口包含两个方法GetObjectKind() 和 DeepCopyObject():后端
Scheme定义了序列化和反序列化API对象的方法,用于将group、版本和类型信息转换为Go模式和从Go模式转换为Go模式的类型注册表,以及不一样版本的Go模式之间的映射。api
当和API Server通讯的时候可以处理新的types类型的话就须要先让client可以知道有这个新的types类型存在。缓存
AddToScheme 会利用到反射,所以新定义的types类型的结构体的命名必需要和自定义的Kind的命名(如VirtualService
)保持一致,不然会找不到对应的kind,安全
var ( SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) AddToScheme = SchemeBuilder.AddToScheme ) 复制代码
当咱们定义好一个新的types类型而且添加了一个register注册方法到全局的scheme编译器后,咱们就能够建立一个http client去加载咱们的自定义资源了。如今就要用到client-go/rest
这个RESTClient去实现了。通常而言,为了更为安全的方式使用API,优雅的姿式是打包这些操做到clientset中,经过rest包中的RESTClientFor
方法进行相关的封装,而后再实现一些普适的interface接口,包含Get、Create、 Delete, Update 、List、Watch等通用接口方法,这个能够参考Pod client set的实现ide
通常优雅的姿式去操做Kubernetes的资源并实时作出响应的方案是采用client-go的informer,它的工做模式是:初始时使用List()去加载资源的全部相关实例,而后使用Watch()进行订阅更新;使用初始对象List列表和从watch订阅更新到的数据会构建一个本地缓存,该缓存能够快速访问任何自定义资源而无需每次都访问API Server。像Pod、Deployment等资源对象都是采用这种方式。ui
在k8s.io/client-go/tools/cache
包中提供了一个Informer方法cache.NewInformer
,这个cache.NewInformer
返回两个参数Store 和Controller:
代码生成相比于前面的手动生成的优点在于不用手动去写一些基础的deepcopy,client,informer,lister
这些方法
code-generation 也是基于client-go,由于client-go 须要实现runtime.Object interface的CustomResources类型 ,这样就要实现诸如DeepCopy深拷贝的一系列方法,code-generation 就是实现了好比深拷贝的代码生成器,关于k8s.io/code-genera…,以下:
func (t* T) DeepCopy() *T
informer和lister至关因而controllers,抽象一层controllers去进行操做资源.
实际项目中,须要引入k8s.io/code-genera…这个工程,而后经过一些脚本生成。一个简单的示例是github上的crd-code-generation项目,这个同时也是这篇博文 code-generation-customresources中的示例
官方的sample-controller项目也是代码生成的,而且有关于自定义资源CRD的一些操做。
建立好工程目录
pkg/apis/{Groupame}/{Version}
,如pkg/apis/networking.istio.io/v1
在version目录下建立文件
文件里面的注释,格式,都有要求
建立自动生成脚本
vendor/k8s.io/code-generator/generate-groups.sh
生成注意点:types不能有interface{} ,不然自动生成的时候会生成出错,所以其实也不建议经过代码自动生成,仍是手动去编写会更好。
type VirtualServiceSpec struct { Hosts []string `json:"hosts"` Gateways []string `json:"gateways"` Http interface{} `json:"http"` } 报错以下: /v1/zz_generated.deepcopy.go" (107:37: expected ';', found '{' (and 5 more errors)). 复制代码
而后经过以下命令
generate-groups.sh <generators> <output-package> <apis-package> <groups-versions> ... vendor/k8s.io/code-generator/generate-groups.sh all github.com/openshift-evangelists/crd-code-generation/pkg/client github.com/openshift-evangelists/crd-code-generation/pkg/apis example.com:v1 ... 能够同时指定多个输出目录 vendor/k8s.io/code-generator/generate-groups.sh all \ base-code-example/istio/crd-code-generation-service/pkg/client base-code-example/istio/crd-code-generation-service/pkg/apis \ "example.com:v1 networking.istio.io:v1" \ --go-header-file ${SCRIPT_ROOT}/hack/custom-boilerplate.go.txt 复制代码
能够生成client的全部方法
优点:
减小很大一部分的通用实现,如deepcopy,client,informer,lister
这些方法,这个相对来讲是通用的,各个CRD都要实现一套
避免本身编写出一些不完善或者错误的实现
劣势:
试想一下,istio中的资源、对象都是Kubernetes的CRDs,那么必然,istio中确定有处理好Kubernetes CRD的方式,咱们知道目前都是采用client-go,那么istio中必然会有大量的client-go的引用和使用,经过源码能够发现确实如此而且都是采用RESTClient,clientset是包含RESTClient的。
在源码路径/Users/meitu/Documents/work_Meitu/goDev/Applications/src/istio.io/istio/pilot/pkg/config/kube/crd
中就是相关CRD的处理,而后/Users/meitu/Documents/work_Meitu/goDev/Applications/src/istio.io/istio/pilot/pkg/config/kube/crd/types.go
是istio中全部一些经常使用资源的定义如DestinationRule、Gateway、VirtualService等。这样的话,咱们本身要经过client-go去实现后端服务,去开发的话,就能够参考istio源码中的一些定义和基本方法,而后结合client-go的通常性处理去实现后端服务程序。
Accessing Kubernetes CRDs from the client-go package