| 
 | 1 | +# Kubernetes Clientset  | 
 | 2 | + | 
 | 3 | +<!-- TOC -->  | 
 | 4 | + | 
 | 5 | +- [Kubernetes Clientset](#kubernetes-clientset)  | 
 | 6 | + - [资源类型 Scheme](#资源类型-scheme)  | 
 | 7 | + - [types.go 文件](#typesgo-文件)  | 
 | 8 | + - [zz_generated.deepcopy.go 文件](#zz_generateddeepcopygo-文件)  | 
 | 9 | + - [register.go 文件](#registergo-文件)  | 
 | 10 | + - [注册所有内置资源类型到 Scheme 对象](#注册所有内置资源类型到-scheme-对象)  | 
 | 11 | + - [创建和使用 Kubernetes Clientset](#创建和使用-kubernetes-clientset)  | 
 | 12 | + - [创建支持所有资源类型的全局 Clientset](#创建支持所有资源类型的全局-clientset)  | 
 | 13 | + - [各资源类型的 Clientset](#各资源类型的-clientset)  | 
 | 14 | + - [各资源类型的 RestFul 方法](#各资源类型的-restful-方法)  | 
 | 15 | + - [使用资源类型的 Clientset 创建 Informer 和 Lister](#使用资源类型的-clientset-创建-informer-和-lister)  | 
 | 16 | + - [使用 client-gen 工具生成资源类型的 Clientset](#使用-client-gen-工具生成资源类型的-clientset)  | 
 | 17 | + - [使用 informer-gen 工具生成资源类型的 Informer](#使用-informer-gen-工具生成资源类型的-informer)  | 
 | 18 | + - [使用 lister-gen 工具生成资源类型的 Lister](#使用-lister-gen-工具生成资源类型的-lister)  | 
 | 19 | + | 
 | 20 | +<!-- /TOC -->  | 
 | 21 | + | 
 | 22 | +## 资源类型 Scheme  | 
 | 23 | + | 
 | 24 | +Clienset 和 apiserver 通信时,需要根据资源对象的类型生成 Resource URL、对 Wire-data 进行**编解码(序列化/反序列化)**。  | 
 | 25 | + | 
 | 26 | +资源类型的 Group、Version、Kind、go struct 定义、编解码(序列化/反序列化) 等内容构成了它的 `Scheme`。  | 
 | 27 | + | 
 | 28 | +K8S 内置资源类型的 Scheme 位于 `k8s.io/api/<group>/<version>` 目录下,以 `Deployment` 为例:  | 
 | 29 | + | 
 | 30 | +``` bash  | 
 | 31 | +$ pwd  | 
 | 32 | +/Users/zhangjun/go/src/gitlab.4pd.io/pht3/aol/vendor/k8s.io/api/extensions/v1beta1  | 
 | 33 | + | 
 | 34 | +$ ls -l  | 
 | 35 | +total 1048  | 
 | 36 | +-rw-r--r-- 1 zhangjun staff 642 Jan 22 15:16 doc.go  | 
 | 37 | +-rw-r--r-- 1 zhangjun staff 308747 Jan 22 15:16 generated.pb.go  | 
 | 38 | +-rw-r--r-- 1 zhangjun staff 49734 Jan 22 15:16 generated.proto  | 
 | 39 | +-rw-r--r-- 1 zhangjun staff 2042 Jan 22 15:16 register.go  | 
 | 40 | +-rw-r--r-- 1 zhangjun staff 69022 Jan 23 22:30 types.go  | 
 | 41 | +-rw-r--r-- 1 zhangjun staff 47996 Jan 22 15:16 types_swagger_doc_generated.go  | 
 | 42 | +-rw-r--r-- 1 zhangjun staff 41555 Jan 22 15:16 zz_generated.deepcopy.go  | 
 | 43 | +```  | 
 | 44 | + | 
 | 45 | +可以暂时忽略无关的文件,我们主要分析 `types.go`、`zz_generated.deepcopy.go` 和 `register.go` 三个文件。  | 
 | 46 | + | 
 | 47 | +1. types.go:定义本 `<group>/<version>` 下所有的资源类型,即 codegen 注释;  | 
 | 48 | +2. zz_generated.deepcopy.go:`deepcopy-gen` 工具自动创建的、包含各资源类型的 `DeepCopyObject()` 方法的文件;  | 
 | 49 | +3. register.go:定义了 `AddToScheme()` 函数,用于将本 `<group>/<version>` 下的各资源类型注册到 Clientset 使用的 Scheme 对象中(k8s.io/client-go/kubernetes/scheme/);  | 
 | 50 | + | 
 | 51 | +### types.go 文件  | 
 | 52 | + | 
 | 53 | +该文件定义了资源类型相关的 go struct 及 codegen 命令行工具使用的注释:  | 
 | 54 | + | 
 | 55 | +``` go  | 
 | 56 | +// 来源于:k8s.io/api/extensions/v1beta1/types.go  | 
 | 57 | + | 
 | 58 | +// +genclient  | 
 | 59 | +// +genclient:method=GetScale,verb=get,subresource=scale,result=Scale  | 
 | 60 | +// +genclient:method=UpdateScale,verb=update,subresource=scale,input=Scale,result=Scale  | 
 | 61 | +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object  | 
 | 62 | + | 
 | 63 | +// DEPRECATED - This group version of Deployment is deprecated by apps/v1beta2/Deployment. See the release notes for  | 
 | 64 | +// more information.  | 
 | 65 | +// Deployment enables declarative updates for Pods and ReplicaSets.  | 
 | 66 | +type Deployment struct {  | 
 | 67 | +	metav1.TypeMeta `json:",inline"`  | 
 | 68 | +	// Standard object metadata.  | 
 | 69 | +	// +optional  | 
 | 70 | +	metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`  | 
 | 71 | + | 
 | 72 | +	// Specification of the desired behavior of the Deployment.  | 
 | 73 | +	// +optional  | 
 | 74 | +	Spec DeploymentSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`  | 
 | 75 | + | 
 | 76 | +	// Most recently observed status of the Deployment.  | 
 | 77 | +	// +optional  | 
 | 78 | +	Status DeploymentStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`  | 
 | 79 | +}  | 
 | 80 | + | 
 | 81 | +// DeploymentSpec is the specification of the desired behavior of the Deployment.  | 
 | 82 | +type DeploymentSpec struct {  | 
 | 83 | +	Replicas *int32 `json:"replicas,omitempty" protobuf:"varint,1,opt,name=replicas"`  | 
 | 84 | +	Selector *metav1.LabelSelector `json:"selector,omitempty" protobuf:"bytes,2,opt,name=selector"`  | 
 | 85 | +	Template v1.PodTemplateSpec `json:"template" protobuf:"bytes,3,opt,name=template"`  | 
 | 86 | +	Strategy DeploymentStrategy `json:"strategy,omitempty" patchStrategy:"retainKeys" protobuf:"bytes,4,opt,name=strategy"`  | 
 | 87 | +	MinReadySeconds int32 `json:"minReadySeconds,omitempty" protobuf:"varint,5,opt,name=minReadySeconds"`  | 
 | 88 | +	RevisionHistoryLimit *int32 `json:"revisionHistoryLimit,omitempty" protobuf:"varint,6,opt,name=revisionHistoryLimit"`  | 
 | 89 | +	Paused bool `json:"paused,omitempty" protobuf:"varint,7,opt,name=paused"`  | 
 | 90 | +	RollbackTo *RollbackConfig `json:"rollbackTo,omitempty" protobuf:"bytes,8,opt,name=rollbackTo"`  | 
 | 91 | +	ProgressDeadlineSeconds *int32 `json:"progressDeadlineSeconds,omitempty" protobuf:"varint,9,opt,name=progressDeadlineSeconds"`  | 
 | 92 | +}  | 
 | 93 | +```  | 
 | 94 | + | 
 | 95 | +### zz_generated.deepcopy.go 文件  | 
 | 96 | + | 
 | 97 | +所有注册到 Scheme 的资源类型都要实现 `runtime.Object` 接口:  | 
 | 98 | + | 
 | 99 | +``` go  | 
 | 100 | +// 来源于:k8s.io/apimachinery/pkg/runtime/interfaces.go  | 
 | 101 | +type Object interface {  | 
 | 102 | +	GetObjectKind() schema.ObjectKind  | 
 | 103 | +	DeepCopyObject() Object  | 
 | 104 | +}  | 
 | 105 | +```  | 
 | 106 | + | 
 | 107 | +K8S 各资源类型的 go struct 定义都嵌入了 `metav1.TypeMeta` 类型,而该类型实现了 `GetObjectKind()` 方法,故各资源类型只需要实现 `DeepCopyObject()` 方法。  | 
 | 108 | + | 
 | 109 | +我们不需要手动为各资源类型定义 `DeepCopyObject()` 方法,而是使用 `deepcopy-gen` 工具命令统一、自动地为各资源类型生成该方法。  | 
 | 110 | + | 
 | 111 | +deepcopy-gen 工具读取 `types.go` 文件中的 `+k8s:deepcopy-gen` 注释,如:  | 
 | 112 | + | 
 | 113 | +	// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object  | 
 | 114 | + | 
 | 115 | +然后将生成的结果保存到 `zz_generated.deepcopy.go` 文件,以 `Deployment` 类型为例:  | 
 | 116 | + | 
 | 117 | +``` go  | 
 | 118 | +// 来源于:k8s.io/api/extensions/v1beta1/zz_generated.deepcopy.go  | 
 | 119 | +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Deployment.  | 
 | 120 | +func (in *Deployment) DeepCopy() *Deployment {  | 
 | 121 | +	if in == nil {  | 
 | 122 | +		return nil  | 
 | 123 | +	}  | 
 | 124 | +	out := new(Deployment)  | 
 | 125 | +	in.DeepCopyInto(out)  | 
 | 126 | +	return out  | 
 | 127 | +}  | 
 | 128 | + | 
 | 129 | +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.  | 
 | 130 | +func (in *Deployment) DeepCopyObject() runtime.Object {  | 
 | 131 | +	if c := in.DeepCopy(); c != nil {  | 
 | 132 | +		return c  | 
 | 133 | +	}  | 
 | 134 | +	return nil  | 
 | 135 | +}  | 
 | 136 | +```  | 
 | 137 | + | 
 | 138 | +### register.go 文件  | 
 | 139 | + | 
 | 140 | +使用 `deepcopy-gen` 工具命令统一、自动地为各资源类型生成`DeepCopyObject()` 方法后,各资源类型就满足了 `runtime.Object` 接口,进而可以注册到 Scheme 中。  | 
 | 141 | + | 
 | 142 | +各 API Group 的各 Version 目录下,都有一个 `register.go` 文件,该文件对外提供的 `AddToScheme()` 方法用于将本 Group/Version 下的各资源类型注册到**传入**的 Scheme 对象中(k8s.io/client-go/kubernetes/scheme/register.go 中创建该 Scheme 对象),然后 Clientset 就可以使用它对各类型对象进行编解码了。  | 
 | 143 | + | 
 | 144 | +``` go  | 
 | 145 | +// 来源于:k8s.io/api/extensions/v1beta1/register.go  | 
 | 146 | +// 本 package 的 Group 名称  | 
 | 147 | +const GroupName = "extensions"  | 
 | 148 | + | 
 | 149 | +// 注册时提供的 Group/Version 信息  | 
 | 150 | +// 一个 Group 目录下,有可能有多个 Version 的子目录  | 
 | 151 | +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta1"}  | 
 | 152 | + | 
 | 153 | +// Resource 实际就是资源类型的完整路径 <Group>/<Version>/<Plural>,如 extensions/v1beta1/deployments  | 
 | 154 | +// Plural 是资源类型的复数形式  | 
 | 155 | +func Resource(resource string) schema.GroupResource {  | 
 | 156 | +	return SchemeGroupVersion.WithResource(resource).GroupResource()  | 
 | 157 | +}  | 
 | 158 | + | 
 | 159 | +var (  | 
 | 160 | +	SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)  | 
 | 161 | +	localSchemeBuilder = &SchemeBuilder  | 
 | 162 | +	// 对外暴露的 AddToScheme() 方法用于注册该 Group/Verion 下的所有资源类型  | 
 | 163 | +	AddToScheme = localSchemeBuilder.AddToScheme  | 
 | 164 | +)  | 
 | 165 | + | 
 | 166 | +// 将本 Group/Version 下的所有资源类型注册到传入的 scheme  | 
 | 167 | +func addKnownTypes(scheme *runtime.Scheme) error {  | 
 | 168 | +	scheme.AddKnownTypes(SchemeGroupVersion,  | 
 | 169 | +		&Deployment{},  | 
 | 170 | +		&DeploymentList{},  | 
 | 171 | +		...  | 
 | 172 | +	)  | 
 | 173 | +	// Add the watch version that applies  | 
 | 174 | +	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)  | 
 | 175 | +	return nil  | 
 | 176 | +}  | 
 | 177 | +```  | 
 | 178 | + | 
 | 179 | +## 注册所有内置资源类型到 Scheme 对象  | 
 | 180 | + | 
 | 181 | +需要将 `k8s.io/api/<group>/<version>` 目录下的各资源类型注册到**全局 Scheme 对象**,这样 Clienset 才能识别和使用它们的对象。  | 
 | 182 | + | 
 | 183 | +client-go 的 `scheme package`(k8s.io/client-go/kubernetes/scheme/)定义了这个全局 `Scheme` 对象,并将各 `k8s.io/api/<Group>/<Version>` 目录下的资源类型注册到它上面。  | 
 | 184 | + | 
 | 185 | +Scheme 对象还被用于创建另外两个外部对象:  | 
 | 186 | +1. 对资源类型对象进行编解码(序列化/反序列化)的工厂对象 `Codecs`,后续使用它配置 `rest.Config.NegotiatedSerializer`;  | 
 | 187 | +2. 参数编解码对象 `ParameterCodec`,后续调用 RestFul 的方法时使用,如 `VersionedParams(&options, scheme.ParameterCodec)`。  | 
 | 188 | + | 
 | 189 | +``` go  | 
 | 190 | +// 来源于 k8s.io/client-go/kubernetes/scheme/register.go  | 
 | 191 | +// 新建一个 Scheme,后续所有 K8S 类型均添加到该 Scheme;  | 
 | 192 | +var Scheme = runtime.NewScheme()  | 
 | 193 | +// 为 Scheme 中的所有类型创建一个编解码工厂;  | 
 | 194 | +var Codecs = serializer.NewCodecFactory(Scheme)  | 
 | 195 | +// 为 Scheme 中的所有类型创建一个参数编解码工厂  | 
 | 196 | +var ParameterCodec = runtime.NewParameterCodec(Scheme)  | 
 | 197 | + | 
 | 198 | +// 将各 `k8s.io/api/<Group>/<Version>` 目录下的资源类型的 AddToScheme() 方法注册到 SchemeBuilder 中  | 
 | 199 | +var localSchemeBuilder = runtime.SchemeBuilder{  | 
 | 200 | + ...  | 
 | 201 | +	extensionsv1beta1.AddToScheme,  | 
 | 202 | + ...  | 
 | 203 | +}  | 
 | 204 | +var AddToScheme = localSchemeBuilder.AddToScheme  | 
 | 205 | + | 
 | 206 | +func init() {  | 
 | 207 | + v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"})  | 
 | 208 | +	// 调用 SchemeBuilder 中各资源对象的 AddToScheme() 方法,将它们注册到到 Scheme 对象。  | 
 | 209 | +	utilruntime.Must(AddToScheme(Scheme))  | 
 | 210 | +}  | 
 | 211 | +```  | 
 | 212 | + | 
 | 213 | +## 创建和使用 Kubernetes Clientset  | 
 | 214 | + | 
 | 215 | +经过前面的铺垫分析后,我们开始分析 Kubernetes Clientset 的创建过程。  | 
 | 216 | + | 
 | 217 | +先从使用者的角度看看如何创建和使用 Kubernetes Clientset:  | 
 | 218 | + | 
 | 219 | +``` go  | 
 | 220 | +var err error  | 
 | 221 | +var config *rest.Config  | 
 | 222 | +// 使用 ServiceAccount 创建集群配置  | 
 | 223 | +if config, err = rest.InClusterConfig(); err != nil {  | 
 | 224 | +	// 使用 kubeConfig 指向的配置文件创建集群配置  | 
 | 225 | +	if config, err = clientcmd.BuildConfigFromFlags("", *kubeConfig); err != nil {  | 
 | 226 | +		panic(err.Error())  | 
 | 227 | +	}  | 
 | 228 | +}  | 
 | 229 | + | 
 | 230 | +// 创建 clientset  | 
 | 231 | +clientset, err = kubernetes.NewForConfig(config)  | 
 | 232 | +if err != nil {  | 
 | 233 | +	panic(err.Error())  | 
 | 234 | +}  | 
 | 235 | + | 
 | 236 | +// 使用 clienset 创建一个 Deploy  | 
 | 237 | +deploy, err := c.kubeclientset.ExtensionsV1beta1().Deployments(aolDeploy.ObjectMeta.Namespace).Create(myDeploy)  | 
 | 238 | +```  | 
 | 239 | + | 
 | 240 | +1. 使用 Kubeconfig 文件或 ServiceAccount 创建 Kubernetes 的 RestFul 配置参数;  | 
 | 241 | +2. 使用 Kubernetes 的 RestFul 配置参数,创建 Clientset;  | 
 | 242 | +3. 调用 Clientset 的方法对资源对象进行 CRUD;  | 
 | 243 | + | 
 | 244 | +## 创建支持所有资源类型的全局 Clientset  | 
 | 245 | + | 
 | 246 | +`k8s.io/client-go/kubernetes/clientset.go` 文件中创建的 Clientset 实际上是对各资源类型的 Clientset 做了一次封装:  | 
 | 247 | + | 
 | 248 | +1. 调用各资源类型的 NewForConfig() 函数创建对应的 Clientset;  | 
 | 249 | +2. 后续可以使用 Clientset.<Group><Version>(),如 Clientset.ExtensionsV1beta1() 来调用具体资源类型的 Clientset;  | 
 | 250 | + | 
 | 251 | +``` go  | 
 | 252 | +// 来源于 k8s.io/client-go/kubernetes/clientset.go  | 
 | 253 | +// 传入的 rest.Config 包含 apiserver 服务器和认证信息  | 
 | 254 | +func NewForConfig(c *rest.Config) (*Clientset, error) {  | 
 | 255 | +	configShallowCopy := *c  | 
 | 256 | + ...  | 
 | 257 | + // 透传 rest.COnfig,调用具体分组和版本的资源类型的 ClientSet 构造函数  | 
 | 258 | +	cs.extensionsV1beta1, err = extensionsv1beta1.NewForConfig(&configShallowCopy)  | 
 | 259 | +	if err != nil {  | 
 | 260 | +		return nil, err  | 
 | 261 | +	}  | 
 | 262 | + ...  | 
 | 263 | +	cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy)  | 
 | 264 | +	if err != nil {  | 
 | 265 | +		return nil, err  | 
 | 266 | +	}  | 
 | 267 | +	return &cs, nil  | 
 | 268 | +}  | 
 | 269 | + | 
 | 270 | +// ExtensionsV1beta1 retrieves the ExtensionsV1beta1Client  | 
 | 271 | +func (c *Clientset) ExtensionsV1beta1() extensionsv1beta1.ExtensionsV1beta1Interface {  | 
 | 272 | +	return c.extensionsV1beta1  | 
 | 273 | +}  | 
 | 274 | +```  | 
 | 275 | + | 
 | 276 | +## 各资源类型的 Clientset  | 
 | 277 | + | 
 | 278 | +各资源类型的 Clientset 定义位于 `k8s.io/client-go/kubernetes/typed/<group>/<version>/<plug>_client.go` 文件中,如   | 
 | 279 | +`k8s.io/client-go/kubernetes/typed/extensions/v1beta1/extensions_client.go`。  | 
 | 280 | + | 
 | 281 | +比较关键的是 `setConfigDefaults()` 函数,它负责为 Clientset 配置参数:  | 
 | 282 | +1. 资源对象的 GroupVersion;  | 
 | 283 | +2. 资源对象的 root path;  | 
 | 284 | +3. 对 wired data 进行编解码(序列化/反序列化)的 `NegotiatedSerializer`,使用的 `scheme.Codecs` 为前面介绍过的 `scheme package`;  | 
 | 285 | + | 
 | 286 | +RESTClient 根据配置的 root path 和 GroupVersion,构造 Resource 地址(格式为 `/apis/<group>/<version>/<name>`)。  | 
 | 287 | + | 
 | 288 | +``` go  | 
 | 289 | +// 来源于 k8s.io/client-go/kubernetes/typed/extensions/v1beta1/extensions_client.go  | 
 | 290 | +// 传入的 rest.Config 包含 apiserver 服务器和认证信息  | 
 | 291 | +func NewForConfig(c *rest.Config) (*ExtensionsV1beta1Client, error) {  | 
 | 292 | + config := *c  | 
 | 293 | + // 为 rest.Config 设置资源对象相关的参数  | 
 | 294 | +	if err := setConfigDefaults(&config); err != nil {  | 
 | 295 | +		return nil, err  | 
 | 296 | + }  | 
 | 297 | + // 创建 ExtensionsV1beta1 的 RestClient  | 
 | 298 | +	client, err := rest.RESTClientFor(&config)  | 
 | 299 | +	if err != nil {  | 
 | 300 | +		return nil, err  | 
 | 301 | +	}  | 
 | 302 | +	return &ExtensionsV1beta1Client{client}, nil  | 
 | 303 | +}  | 
 | 304 | + | 
 | 305 | +func setConfigDefaults(config *rest.Config) error {  | 
 | 306 | + // 资源对象的 GroupVersion  | 
 | 307 | +	gv := v1beta1.SchemeGroupVersion  | 
 | 308 | + config.GroupVersion = &gv  | 
 | 309 | + // 资源对象的 root path  | 
 | 310 | + config.APIPath = "/apis"  | 
 | 311 | + // 使用注册的资源类型 Schema 对请求和响应进行编解码  | 
 | 312 | + // scheme 为前面分析过的 k8s.io/client-go/kubernetes/scheme package  | 
 | 313 | +	config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}  | 
 | 314 | + | 
 | 315 | +	if config.UserAgent == "" {  | 
 | 316 | +		config.UserAgent = rest.DefaultKubernetesUserAgent()  | 
 | 317 | +	}  | 
 | 318 | + | 
 | 319 | +	return nil  | 
 | 320 | +}  | 
 | 321 | + | 
 | 322 | +func (c *ExtensionsV1beta1Client) Deployments(namespace string) DeploymentInterface {  | 
 | 323 | +	return newDeployments(c, namespace)  | 
 | 324 | +}  | 
 | 325 | +```  | 
 | 326 | + | 
 | 327 | +## 各资源类型的 RestFul 方法  | 
 | 328 | + | 
 | 329 | +使用各资源类型的 Clientset 创建资源类型的 RestFul 方法,参数的编解码工厂 `scheme.ParameterCodec` 来源于前面介绍的 `scheme package` 中。  | 
 | 330 | + | 
 | 331 | +``` go  | 
 | 332 | +// 来源于 k8s.io/client-go/kubernetes/typed/extensions/v1beta1/deployment.go  | 
 | 333 | +// newDeployments returns a Deployments  | 
 | 334 | +func newDeployments(c *ExtensionsV1beta1Client, namespace string) *deployments {  | 
 | 335 | +	return &deployments{  | 
 | 336 | +		client: c.RESTClient(),  | 
 | 337 | +		ns: namespace,  | 
 | 338 | +	}  | 
 | 339 | +}  | 
 | 340 | + | 
 | 341 | +// Get takes name of the deployment, and returns the corresponding deployment object, and an error if there is any.  | 
 | 342 | +func (c *deployments) Get(name string, options v1.GetOptions) (result *v1beta1.Deployment, err error) {  | 
 | 343 | +	result = &v1beta1.Deployment{}  | 
 | 344 | +	// 发起实际的 RestFul 请求;  | 
 | 345 | +	err = c.client.Get().  | 
 | 346 | +		Namespace(c.ns).  | 
 | 347 | +		Resource("deployments").  | 
 | 348 | +		Name(name).  | 
 | 349 | +		VersionedParams(&options, scheme.ParameterCodec).  | 
 | 350 | +		Do().  | 
 | 351 | +		Into(result)  | 
 | 352 | +	return  | 
 | 353 | +}  | 
 | 354 | +```  | 
 | 355 | + | 
 | 356 | +## 使用资源类型的 Clientset 创建 Informer 和 Lister  | 
 | 357 | +## 使用 client-gen 工具生成资源类型的 Clientset  | 
 | 358 | +## 使用 informer-gen 工具生成资源类型的 Informer  | 
 | 359 | +## 使用 lister-gen 工具生成资源类型的 Lister  | 
0 commit comments