Kubernetes的client-go库介绍

96
吴德宝AllenWu
0.3 2018.10.19 21:14 字数 1575

[TOC]

Kubernetes的client-go库介绍

client-go的作用

github上client-go官方项目工程

基本介绍

Kubernetes官方从2016年8月份开始,将Kubernetes资源操作相关的核心源码抽取出来,独立出来一个项目Client-go,作为官方提供的Go client。Kubernetes的部分代码也是基于这个client实现的,所以对这个client的质量、性能等方面还是非常有信心的。

client-go是一个调用kubernetes集群资源对象API的客户端,即通过client-go实现对kubernetes集群中资源对象(包括deployment、service、ingress、replicaSet、pod、namespace、node等)的增删改查等操作。大部分对kubernetes进行前置API封装的二次开发都通过client-go这个第三方包来实现。

源码简介

主要package

主要的几个package包的功能说明:

  • kubernetes: 访问 Kubernetes API的一系列的clientset
  • discovery:通过Kubernetes API 进行服务发现
  • dynamic:对任意Kubernetes对象执行通用操作的动态client
  • transport:启动连接和鉴权auth
  • tools/cache:controllers控制器

Client结构

  • RESTClient:RESTClient是最基础的,相当于的底层基础结构,可以直接通过 是RESTClient提供的RESTful方法如Get(),Put(),Post(),Delete()进行交互
    • 同时支持Json 和 protobuf
    • 支持所有原生资源和CRDs
    • 但是,一般而言,为了更为优雅的处理,需要进一步封装,通过Clientset封装RESTClient,然后再对外提供接口和服务
  • Clientset:Clientset是调用Kubernetes资源对象最常用的client,可以操作所有的资源对象,包含RESTClient。需要指定Group、指定Version,然后根据Resource获取

    • 优雅的姿势是利用一个controller对象,再加上Informer
  • DynamicClient:Dynamic client 是一种动态的 client,它能处理 kubernetes 所有的资源。不同于 clientset,dynamic client 返回的对象是一个 map[string]interface{},如果一个 controller 中需要控制所有的 API,可以使用dynamic client,目前它在 garbage collector 和 namespace controller中被使用。

    • 只支持JSON

RESTClient

RESTClient 封装了指定资源URL的通用Kubernetes API的访问姿势

Clientset

/Users/meitu/Documents/work_Meitu/goDev/Applications/src/k8s.io/client-go/kubernetes/clientset.go

Clientset 是一系列的clients的group组合,注意每个group在一个Clientset中只包含一个版本。

Clientset包含了appsV1、coreV1,这中间包含了RESTClient,因此Clientset是基于RESTClient的。

dynamic client

dynamic client针对的是所有资源,但是只支持Json;

主要源码路径在:/Users/meitu/Documents/work_Meitu/goDev/Applications/src/k8s.io/client-go/dynamic

type ResourceInterface interface {
    Create(obj *unstructured.Unstructured, options metav1.CreateOptions, subresources ...string) (*unstructured.Unstructured, error)
    Update(obj *unstructured.Unstructured, options metav1.UpdateOptions, subresources ...string) (*unstructured.Unstructured, error)
    UpdateStatus(obj *unstructured.Unstructured, options metav1.UpdateOptions) (*unstructured.Unstructured, error)
    Delete(name string, options *metav1.DeleteOptions, subresources ...string) error
    DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error
    Get(name string, options metav1.GetOptions, subresources ...string) (*unstructured.Unstructured, error)
    List(opts metav1.ListOptions) (*unstructured.UnstructuredList, error)
    Watch(opts metav1.ListOptions) (watch.Interface, error)
    Patch(name string, pt types.PatchType, data []byte, options metav1.UpdateOptions, subresources ...string) (*unstructured.Unstructured, error)
}

Informer

Client-go包中一个相对较为高端的设计在于Informer的设计,我们知道我们可以直接通过Kubernetes API交互,但是考虑一点就是交互的形式,Informer设计为List/Watch的方式。Informer在初始化的时先通过List去从Kubernetes API中取出资源的全部object对象,并同时缓存,然后后面通过Watch的机制去监控资源,这样的话,通过Informer及其缓存,我们就可以直接和Informer交互而不是每次都和Kubernetes API交互。

Informer另外一块内容在于提供了事件handler机制,并会触发回调,这样上层应用如Controller就可以基于回调处理具体业务逻辑。因为Informer通过List、Watch机制可以监控到所有资源的所有事件,因此只要给Informer添加ResourceEventHandler 实例的回调函数实例取实现OnAdd(obj interface{}) OnUpdate(oldObj, newObj interface{}) 和 OnDelete(obj interface{})这三个方法,就可以处理好资源的创建、更新和删除操作

Kubernetes中都是各种controller的实现,各种controller都会用到Informer。

对象资源的操作接口

默认的每一种资源对象都有一个interface,封装了对象的CURD方法和list/watch方法

如 Deployment(/文件路径Users/meitu/Documents/work_Meitu/goDev/Applications/src/k8s.io/client-go/kubernetes/typed/apps/v1/deployment.go):

type DeploymentInterface interface {
    Create(*v1.Deployment) (*v1.Deployment, error)
    Update(*v1.Deployment) (*v1.Deployment, error)
    UpdateStatus(*v1.Deployment) (*v1.Deployment, error)
    Delete(name string, options *metav1.DeleteOptions) error
    DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error
    Get(name string, options metav1.GetOptions) (*v1.Deployment, error)
    List(opts metav1.ListOptions) (*v1.DeploymentList, error)
    Watch(opts metav1.ListOptions) (watch.Interface, error)
    Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Deployment, err error)
    DeploymentExpansion
}

如Service(文件路径/Users/meitu/Documents/work_Meitu/goDev/Applications/src/k8s.io/client-go/kubernetes/typed/core/v1/service.go)


// ServiceInterface has methods to work with Service resources.
type ServiceInterface interface {
    Create(*v1.Service) (*v1.Service, error)
    Update(*v1.Service) (*v1.Service, error)
    UpdateStatus(*v1.Service) (*v1.Service, error)
    Delete(name string, options *metav1.DeleteOptions) error
    Get(name string, options metav1.GetOptions) (*v1.Service, error)
    List(opts metav1.ListOptions) (*v1.ServiceList, error)
    Watch(opts metav1.ListOptions) (watch.Interface, error)
    Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Service, err error)
    ServiceExpansion
}

这也就是说明,在Kubernetes中,所有对象资源的操作方式都是统一的,有个interface当做虚基类,包含资源的所有操作方法,然后各个子类继承然后实现它们,子类中的实现定义会针对不同的资源有不同诠释

client-go中的设计思想

client-go 和 controller的架构设计

github上关于client-go的设计有一副概览图如下:

image.png

主要是两大块:

  • client-go组件本身
  • controller上层控制器

上图相对较为复杂,有很多细节,我自己结合源码的理解如下:


image.png

client-go组件

  • Reflector:通过Kubernetes API监控Kubernetes的资源类型

    • 采用List、Watch机制
    • 可以Watch任何资源包括CRD
    • 添加object对象到FIFO队列,然后Informer会从队列里面取数据
  • Informer:controller机制的基础

    • 循环处理object对象
      • 从Reflector取出数据,然后将数据给到Indexer去缓存
    • 提供对象事件的handler接口
  • Indexer:提供object对象的索引,是线程安全的,缓存对象信息

controller组件

  • Informer reference: controller需要创建合适的Informer才能通过Informer reference操作资源对象

  • Indexer reference: controller创建Indexer reference然后去利用索引做相关处理

  • Resource Event Handlers:Informer会回调这些handlers

  • Work queue: Resource Event Handlers被回调后将key写到工作队列

    • 这里的key相当于事件通知,后面根据取出事件后,做后续的处理
  • Process Item:从工作队列中取出key后进行后续处理,具体处理可以通过Indexer reference

  • controller可以直接创建上述两个引用对象去处理,也可以采用工厂模式,官方都有相关示例

参考

Accessing Kubernetes CRDs from the client-go package

client-go under the hood

Kubernetes Deep Dive: Code Generation for CustomResources

kubernetes client-go

Kubernetes Informer 详解

如何用 client-go 拓展 Kubernetes 的 API

Using Kubernetes API from Go

容器化、Kubernetes
Web note ad 1