3.3.4 Client
1. Client的初始化
在介绍Client之前,需要引入restClient 结构,它是最底层的基础结构,可以直接通过restClient提供的 RESTful方法 , 如 Get()、Put()、Post()、Delete() 进行交互, 支持 JSON和 protobuf传输数据,以及所有原生资源和 CRD。一般情况下,要先通过 Clientset封装restClient,然后对外提供接口和服务。
那么本节介绍的Client和restClient是什么关系呢?首先我们通过代码清单3-41来分析。当我们启动自定义的CRDController时,一般可以通过如下方式来定义它的结构体。
typeDemoReconcilerstruct{client.Client
Log
}
这里 Client的作用比较清晰,就是在 CRDController 执行协调的过程中,需要通过ClientCRUD(Create、Retrieve、Update、Delete)CRD,即Get、Create等方法。所以 DemoReconciler的结构体第一个元素的对象,指向的是 Controller-runtime包中的 Client接口对象,它设计了必要的方法,如 Get、List、Update 等,见代码清单 3-42。
typeClientinterface{
ReaderWriterStatusClient
}
typeReaderinterface{
Get(ctxcontext.Context,keyObjectKey,objObject)error
List(ctxcontext.Context,listObjectList,opts...ListOption)error
}
//Writer接⼝定义如何创建、删除、更新Kubernetes对象
typeWriterinterface{
Create(ctx context.Context, obj Object, opts ...CreateOption) errorDelete(ctx context.Context, obj Object, opts ...DeleteOption) errorUpdate(ctxcontext.Context,objObject,opts...UpdateOption)error
}
2. Client的结构分析
有了 Client结构之后,结合我们介绍的restClient,读者能够联想到 Client本质上就是 restClient,只是 Client做了很多上层的封装,便于用户使用。下面我们进一步分析 Client是如何赋值的,即它的实例化对象。首先,我们简单回顾一下前面章节介绍的Manager的作用,它初始化了 Client、注册了 CRDScheme及 Reconciler 的对象。因此,这里的 Client可以通过 Manager初始化产生,可通过 manager.GetClient方法获得,具体方法的实现不作为本节重点,读者可参考 Github。这个方法的实质过程是通过 k8s的kubeconfig文件生成可访问的restClient对象,因此,它具备了对k8s 所有资源的操作方法,即 CRUD的过程。
至此,我们通过分析上述案例,明确了Client和restClient的关系,那么在Controller-runtime 的包中,Client 实例化后的结构体如何理解各元素呢?见代码清单 3-43。
typeclientstruct{
typedClient typedClientunstructuredClientunstructuredClientmetadataClient metadataClientscheme *runtime.Scheme
mapper meta.RESTMapper
}
typedClient表明是 k8s内部资源已经封装好的 Client,比如 CoreGroup下的所有资源,包括 Pod、Deploy等,换句话说,如果是自定义的 CRD,则 Client无法处理它。因此,必须设计一个新的 Client,能够处理 CRD的资源对象,UnstructuredClient实现了这一点,它的功能就是通过 restClient,借助 APIServer访问所有的 k8s资源,MetadataClient的作用是操作元数据资源,Scheme对定义的资源对象 GVK等关系进行访问,Mapper用于反射 Meta资源的处理逻辑。