前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Kubernetes client-go实战应用

Kubernetes client-go实战应用

作者头像
Allen.Wu
发布2019-12-12 16:30:15
1.7K0
发布2019-12-12 16:30:15
举报
文章被收录于专栏:后端系统和架构

Kubernetes client-go实战应用

github上client-go官方项目工程

实战应用

  • 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库位于:https://github.com/kubernetes/apiextensions-apiserver,但是现在client-go已经支持CRD

1,定义types类型

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

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

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 Server通信的时候能够处理新的types类型的话就需要先让client能够知道有这个新的types类型存在。

AddToScheme 会利用到反射,因此新定义的types类型的结构体的命名必须要和自定义的Kind的命名(如VirtualService)保持一致,否则会找不到对应的kind,

代码语言:javascript
复制
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的实现

5,构建Informer

一般优雅的姿势去操作Kubernetes的资源并实时做出响应的方案是采用client-go的informer,它的工作模式是:初始时使用List()去加载资源的所有相关实例,然后使用Watch()进行订阅更新;使用初始对象List列表和从watch订阅更新到的数据会构建一个本地缓存,该缓存可以快速访问任何自定义资源而无需每次都访问API Server。像Pod、Deployment等资源对象都是采用这种方式。

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-generator,如下:

  • 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-generator这个工程,然后通过一些脚本生成。一个简单的示例是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{} ,否则自动生成的时候会生成出错,因此其实也不建议通过代码自动生成,还是手动去编写会更好。

代码语言:javascript
复制
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,生成代码

然后通过如下命令

代码语言:javascript
复制
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-generator

官方的sample-controller项目

github上的crd-code-generation项目

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-10-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 后端系统和架构 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Kubernetes client-go实战应用
    • 实战应用
      • client-go手动操作CRD
      • code-generator自动代码生成操作CRD
      • istio中client-go的处理
    • 参考
    相关产品与服务
    容器服务
    腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档