Kubernetes client-go实战应用


Kubernetes client-go实战应用

github上client-go官方项目工程html

实战应用

  • sample-controller示例
    • 官方的一个简单的Controller示例,能够处理任何CRD资源
    • The main.go and controller.go contains the sample code to watch for the CRD and do some task accordingly.
    • 采用code-generator 的方式
  • kubernetes-crd-example
    • 一个简单的处理任何CRD资源的示例

client-go手动操做CRD

之前建立和管理CRD的client库位于:github.com/kubernetes/…git

1,定义types类型

好比定义一个目录api/types/v1alpha1,里面是关于types的一些定义文件;github

metav1.ObjectMeta 类型会包含典型的任意的Kubernetes资源的metadata属性,如name, namespace, labels, annotations。json

2,定义DeepCopy深拷贝方法

被Kubernetes API定义的全部资源对象、类型都须要实现k8s.io/apimachinery/pkg/runtime.Object这个接口定义,这个接口包含两个方法GetObjectKind() 和 DeepCopyObject():后端

  • GetObjectKind():
    • 内置的metav1.TypeMeta结构已经实现
  • DeepCopyObject():
    • 须要咱们本身去实现这个方法
    • 目的是生成deep copy 对象,C++中有这样的用法,名为:深拷贝,深拷贝意味着会从新生成对象并拷贝对象中的全部字段、地址等数据;浅拷贝仅仅是对象的引用,并无生成新的对象。
    • 须要手动去写各类字段域的赋值

3,经过scheme注册types类型

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 ) 复制代码
  • AddToScheme: runtime.SchemeBuilder的一个外部方法,当Kubernetes注册新定义的types类型后,就能够在任何地方调用这个方法

4,启动一个HTTP client

当咱们定义好一个新的types类型而且添加了一个register注册方法到全局的scheme编译器后,咱们就能够建立一个http client去加载咱们的自定义资源了。如今就要用到client-go/rest这个RESTClient去实现了。通常而言,为了更为安全的方式使用API,优雅的姿式是打包这些操做到clientset中,经过rest包中的RESTClientFor方法进行相关的封装,而后再实现一些普适的interface接口,包含Get、Create、 Delete, Update 、List、Watch等通用接口方法,这个能够参考Pod client set的实现ide

5,构建Informer

通常优雅的姿式去操做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:

  • Controller: 控制 List() 和 Watch() 的调用并填充Store
  • Store: 返回从API Server获取的资源的最新状态
    • 能够经过这个Store去访问咱们的自定义资源CRDs

code-generator自动代码生成操做CRD

代码生成相比于前面的手动生成的优点在于不用手动去写一些基础的deepcopy,client,informer,lister这些方法

code-generation 也是基于client-go,由于client-go 须要实现runtime.Object  interface的CustomResources类型 ,这样就要实现诸如DeepCopy深拷贝的一系列方法,code-generation  就是实现了好比深拷贝的代码生成器,关于k8s.io/code-genera…,以下:

  • deepcopy-gen: 给自定义type类型T建立一个DeepCopy方法func (t* T) DeepCopy() *T
  • client-gen: 给自定义资源的APIGroups建立clientsets
  • informer-gen:经过informers给自定义资源建立一个基础接口方法去操做自定义资源
  • lister-gen: 为GET和LIST请求建立一个listers监听器

informer和lister至关因而controllers,抽象一层controllers去进行操做资源.

实际项目中,须要引入k8s.io/code-genera…这个工程,而后经过一些脚本生成。一个简单的示例是github上的crd-code-generation项目,这个同时也是这篇博文 code-generation-customresources中的示例

官方的sample-controller项目也是代码生成的,而且有关于自定义资源CRD的一些操做。

1,定义好相关目录和文件

  • 建立好工程目录

    • pkg/apis/{Groupame}/{Version},如pkg/apis/networking.istio.io/v1
  • 在version目录下建立文件

    • doc.go
    • types.go : 资源对象的定义
    • regsiter.go:Scheme和register type
  • 文件里面的注释,格式,都有要求

  • vendor

    • 将code-generator项目引入的vendor下
  • 建立自动生成脚本

    • 调用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)). 复制代码

2,生成代码

而后经过以下命令

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的全部方法

3,自动生成的优劣

优点:

  • 减小很大一部分的通用实现,如deepcopy,client,informer,lister这些方法,这个相对来讲是通用的,各个CRD都要实现一套

  • 避免本身编写出一些不完善或者错误的实现

劣势:

  • 很是严格的定义,包括注释,都要按照要求去实现
  • type定义的struct,暂时不支持interface类型的转换,相对来讲不方便,须要严格知道spec的全部域和字段的准确类型

istio中client-go的处理

试想一下,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

Kubernetes Deep Dive: Code Generation for CustomResources

k8s.io/code-genera…

官方的sample-controller项目

github上的crd-code-generation项目

相关文章
相关标签/搜索