client-go之kubernetes包源码分析

320 阅读7分钟

@TOC

kubernetes包

生成原生k8s的对象的client,用于访问kubernetes API(create、update、patch等等)

clientset.go

k8s原生type的restclient的集合,用来统一管理和调配

  • 接口
    // Interface 定义了一个DiscoveryInterface用来和apiserver交互(公共的),和每个gv(k8s原生)下来获取所有resource的client。
    type Interface interface {
      // 一个DiscoveryInterface用来和apiserver交互(公共的,获取group version resource)
    	Discovery() discovery.DiscoveryInterface
      
      // 每个gv(k8s原生)下来获取所有resource的client。
      AdmissionregistrationV1() admissionregistrationv1.AdmissionregistrationV1Interface
      AdmissionregistrationV1beta1() admissionregistrationv1beta1.AdmissionregistrationV1beta1Interface
      InternalV1alpha1() internalv1alpha1.InternalV1alpha1Interface
      AppsV1() appsv1.AppsV1Interface
      AppsV1beta1() appsv1beta1.AppsV1beta1Interface
     	AppsV1beta2() appsv1beta2.AppsV1beta2Interface
     	AuthenticationV1() authenticationv1.AuthenticationV1Interface
      ....等等  太多了就不罗列了,可以看源码
    }
    
  • 结构体
    // Clientset 定义了一个DiscoveryClient用来和apiserver交互(公共的),和每个gv(k8s原生)下来获取所有resource的client。
    type Clientset struct {
      // DiscoveryClient用来和apiserver交互(公共的,获取group version resource)
    	*discovery.DiscoveryClient
    
      // 每个gv(k8s原生)下来获取所有resource的client
    	admissionregistrationV1      *admissionregistrationv1.AdmissionregistrationV1Client
    	admissionregistrationV1beta1 *admissionregistrationv1beta1.AdmissionregistrationV1beta1Client
    	internalV1alpha1             *internalv1alpha1.InternalV1alpha1Client
    	appsV1                       *appsv1.AppsV1Client
    	appsV1beta1                  *appsv1beta1.AppsV1beta1Client
    	appsV1beta2                  *appsv1beta2.AppsV1beta2Client
    	authenticationV1             *authenticationv1.AuthenticationV1Client
      ....等等  太多了就不罗列了,可以看源码
    }
    
    // 其他实现接口类似,不再展示,只是获取了Clientset中的属性
    // 实现Interface接口的AdmissionregistrationV1方法
    func (c *Clientset) AdmissionregistrationV1() admissionregistrationv1.AdmissionregistrationV1Interface {
    	return c.admissionregistrationV1
    }
    
  • 函数
    // NewForConfigOrDie 为给定的配置创建一个新的 Clientset,详情代码请参考源码
    func NewForConfigOrDie(c *rest.Config) *Clientset 
    
    // New 为给定的 RESTClient 创建一个新的 Clientset,详情代码请参考源码
    func New(c rest.Interface) *Clientset 
    

scheme包

该包包含自动生成的clientset的scheme

  • register.go
    • 定义全局变量
      var Scheme = runtime.NewScheme() // 定义scheme(内部是很多map组成,缓存gvkToType/typeToGVK等)变量,这里用来注册kubernetes/api对应的gvr和注册自定义资源
      var Codecs = serializer.NewCodecFactory(Scheme) // 用来创建NegotiatedSerializer(编解码器变量(目前有三种类型:json/yaml/protobuf)),用来编码Request的body和解码Request响应(Response)
      var ParameterCodec = runtime.NewParameterCodec(Scheme) // 用来处理UpdateOptions/CreateOptions等信息形成Request.params
      // 本地(client-go)定义的添加kubernetes/api中的gvr到scheme中
      var localSchemeBuilder = runtime.SchemeBuilder{
      	admissionregistrationv1.AddToScheme,
      	admissionregistrationv1beta1.AddToScheme,
      	internalv1alpha1.AddToScheme,
      	appsv1.AddToScheme,
      	appsv1beta1.AddToScheme,
          ....等等....
      }
      
      // AddToScheme 将上面定义的所有类型添加到给定的scheme(自定义controller一般也是使用该scheme)中。
      // 在此之后,Kubernetes 类型中的 RawExtensions 将正确序列化 kube-aggregator 类型。
      var AddToScheme = localSchemeBuilder.AddToScheme
      
    • 函数
      // 初始化
      func init() {
          // 添加核心gv到scheme
      	v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"})
          // 添加上面定义的AddToScheme到scheme(注册到scheme)
      	utilruntime.Must(AddToScheme(Scheme))
      }
      

typed包

以admissionregistration包做分析,其他的类似,不在分析

  • v1
    • admissionregistration_client.go
      • 接口
        // 提供访问此gv中所有resource的restclient(增删改查等)的权限。
        type AdmissionregistrationV1Interface interface {
          // 增删改查等操作的restclient
        	RESTClient() rest.Interface
          // 用来获取gv下对应MutatingWebhookConfigurationClient(用来操作MutatingWebhookConfigurations)的接口
        	MutatingWebhookConfigurationsGetter
          // 用来获取gv下对应的MutatingWebhookConfigurationClient(用来操作ValidatingWebhookConfigurations)的接口
        	ValidatingWebhookConfigurationsGetter
        }
        
      • 函数
        // 设置默认配置
        func setConfigDefaults(config *rest.Config) error {
          // 设置kubernetes/api对应的gv
        	gv := v1.SchemeGroupVersion
        	config.GroupVersion = &gv
          // 设置核心包(/api)外的路径
        	config.APIPath = "/apis"
          // 设置序列化(用来编码请求内容和解析请求响应)
        	config.NegotiatedSerializer = scheme.Codecs.WithoutConversion()
        
          // 设置用户代理
        	if config.UserAgent == "" {
        		config.UserAgent = rest.DefaultKubernetesUserAgent()
        	}
        
        	return nil
        }
        
        // NewForConfig 为给定的配置创建一个新的 AdmissionregistrationV1Client(实现了MutatingWebhookConfigurationsGetter和ValidatingWebhookConfigurationsGetter接口)。
        func NewForConfig(c *rest.Config) (*AdmissionregistrationV1Client, error) {
        	config := *c
          // 设置默认配置
        	if err := setConfigDefaults(&config); err != nil {
        		return nil, err
        	}
          // 获取restclient(用于用户操作api)
        	client, err := rest.RESTClientFor(&config)
        	if err != nil {
        		return nil, err
        	}
        	return &AdmissionregistrationV1Client{client}, nil
        }
        
        // NewForConfigOrDie 为给定的配置创建一个新的 AdmissionregistrationV1Client 并且如果配置中有错误,则发生panic。
        func NewForConfigOrDie(c *rest.Config) *AdmissionregistrationV1Client {
          // 调用NewForConfig
        	client, err := NewForConfig(c)
          // 这里和NewForConfig的区别是,如果有err,则panic
        	if err != nil {
        		panic(err)
        	}
        	return client
        }
        
        // New 为给定的 RESTClient 创建一个新的 AdmissionregistrationV1Client(实现了AdmissionregistrationV1Interface)。
        func New(c rest.Interface) *AdmissionregistrationV1Client {
        	return &AdmissionregistrationV1Client{c}
        }
        
      • 结构体
        // AdmissionregistrationV1Client 用于与admissionregistration.k8s.io (restClient中限定了kubernetes/api对应的group)组提供的功能进行交互。
        type AdmissionregistrationV1Client struct {
        	restClient rest.Interface
        }
        
        // MutatingWebhookConfigurations 实现了MutatingWebhookConfigurationsGetter接口。
        func (c *AdmissionregistrationV1Client) MutatingWebhookConfigurations() MutatingWebhookConfigurationInterface {
          // 获取gv下MutatingWebhookConfigurations对应的client
        	return newMutatingWebhookConfigurations(c)
        }
        
        // ValidatingWebhookConfigurations实现了ValidatingWebhookConfigurationsGetter接口。
        func (c *AdmissionregistrationV1Client) ValidatingWebhookConfigurations() ValidatingWebhookConfigurationInterface {
          // 获取gv下ValidatingWebhookConfigurations对应的client
        	return newValidatingWebhookConfigurations(c)
        }
        
        // RESTClient 返回一个 RESTClient,用于通过此客户端实现与 API 服务器通信。
        func (c *AdmissionregistrationV1Client) RESTClient() rest.Interface {
        	if c == nil {
        		return nil
        	}
        	return c.restClient
        }
        
    • generated_expansion.go 用于扩展resource client
      • 接口
        // 定义了两个接口,扩展gv下MutatingWebhookConfiguration和ValidatingWebhookConfiguration的client
        type MutatingWebhookConfigurationExpansion interface{}
        
        type ValidatingWebhookConfigurationExpansion interface{}
        
    • mutatingwebhookconfiguration.go
      • 接口
        // MutatingWebhookConfigurationsGetter 有一个返回 MutatingWebhookConfigurationInterface (与apiserver交互,操作gvr)的方法。
        type MutatingWebhookConfigurationsGetter interface {
        	MutatingWebhookConfigurations() MutatingWebhookConfigurationInterface
        }
        
        // MutatingWebhookConfigurationInterface 具有使用 MutatingWebhookConfiguration 资源的方法。
        type MutatingWebhookConfigurationInterface interface {
        	Create(ctx context.Context, mutatingWebhookConfiguration *v1.MutatingWebhookConfiguration, opts metav1.CreateOptions) (*v1.MutatingWebhookConfiguration, error)
        	Update(ctx context.Context, mutatingWebhookConfiguration *v1.MutatingWebhookConfiguration, opts metav1.UpdateOptions) (*v1.MutatingWebhookConfiguration, error)
        	Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error
        	DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error
        	Get(ctx context.Context, name string, opts metav1.GetOptions) (*v1.MutatingWebhookConfiguration, error)
        	List(ctx context.Context, opts metav1.ListOptions) (*v1.MutatingWebhookConfigurationList, error)
        	Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error)
        	Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.MutatingWebhookConfiguration, err error)
        	Apply(ctx context.Context, mutatingWebhookConfiguration *admissionregistrationv1.MutatingWebhookConfigurationApplyConfiguration, opts metav1.ApplyOptions) (result *v1.MutatingWebhookConfiguration, err error)
        	MutatingWebhookConfigurationExpansion
        }
        
      • 结构体
        // mutatingWebhookConfigurations 实现了 MutatingWebhookConfigurationInterface接口
        type mutatingWebhookConfigurations struct {
        	client rest.Interface
        }
        
        // Get 使用mutatingWebhookConfiguration 的名称,获取相应的 mutatingWebhookConfiguration 对象,如果有err则返回错误。
        func (c *mutatingWebhookConfigurations) Get(ctx context.Context, name string, options metav1.GetOptions) (result *v1.MutatingWebhookConfiguration, err error) {
          // 定义变量接收与apiserver交互结果
        	result = &v1.MutatingWebhookConfiguration{}
          // 请求apiserver,获取get信息并转化为result(ps: 这里不做具体分析,待分析rest包再做分析)
        	err = c.client.Get().
        		Resource("mutatingwebhookconfigurations").
        		Name(name).
        		VersionedParams(&options, scheme.ParameterCodec).
        		Do(ctx).
        		Into(result)
        	return
        }
        
        // List 接受标签和字段选择器,并返回与这些选择器匹配的 MutatingWebhookConfigurations 列表。
        func (c *mutatingWebhookConfigurations) List(ctx context.Context, opts metav1.ListOptions) (result *v1.MutatingWebhookConfigurationList, err error) {
          // 设置请求timeout
        	var timeout time.Duration
        	if opts.TimeoutSeconds != nil {
        		timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
        	}
          // 用来存储请求结果
        	result = &v1.MutatingWebhookConfigurationList{}
          // 请求apiserver,获取list信息并转化为result(ps: 这里不做具体分析,待分析rest包再做分析)
        	err = c.client.Get().
        		Resource("mutatingwebhookconfigurations").
        		VersionedParams(&opts, scheme.ParameterCodec).
        		Timeout(timeout).
        		Do(ctx).
        		Into(result)
        	return
        }
        
        // Watch 返回一个 watch.Interface 来监视请求的 mutatingWebhookConfigurations。
        func (c *mutatingWebhookConfigurations) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) {
          // 设置请求timeout
        	var timeout time.Duration
        	if opts.TimeoutSeconds != nil {
        		timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
        	}
          // 设置是watch类型的请求
        	opts.Watch = true
          // 请求apiserver,获取watch接口(ps: 这里不做具体分析,待分析rest包再做分析)
        	return c.client.Get().
        		Resource("mutatingwebhookconfigurations").
        		VersionedParams(&opts, scheme.ParameterCodec).
        		Timeout(timeout).
        		Watch(ctx)
        }
        
        // Create 接受 mutatingWebhookConfiguration 的表示并创建它。返回服务器对 mutatingWebhookConfiguration 的表示,以及错误(如果有)。
        func (c *mutatingWebhookConfigurations) Create(ctx context.Context, mutatingWebhookConfiguration *v1.MutatingWebhookConfiguration, opts metav1.CreateOptions) (result *v1.MutatingWebhookConfiguration, err error) {
          // 定义请求结果(版本为v1的type)
        	result = &v1.MutatingWebhookConfiguration{}
          // 请求apiserver,获取create的请求结果(ps: 这里不做具体分析,待分析rest包再做分析)
        	err = c.client.Post().
        		Resource("mutatingwebhookconfigurations").
        		VersionedParams(&opts, scheme.ParameterCodec).
        		Body(mutatingWebhookConfiguration).
        		Do(ctx).
        		Into(result)
        	return
        }
        
        // 更新采用 mutatingWebhookConfiguration 的表示并更新它。返回服务器对 mutatingWebhookConfiguration 的表示,以及错误(如果有)。
        func (c *mutatingWebhookConfigurations) Update(ctx context.Context, mutatingWebhookConfiguration *v1.MutatingWebhookConfiguration, opts metav1.UpdateOptions) (result *v1.MutatingWebhookConfiguration, err error) {
          // 定义更新请求结果(版本为v1的type)
        	result = &v1.MutatingWebhookConfiguration{}
          // 请求apiserver,获取update的请求结果(ps: 这里不做具体分析,待分析rest包再做分析)
        	err = c.client.Put().
        		Resource("mutatingwebhookconfigurations").
        		Name(mutatingWebhookConfiguration.Name).
        		VersionedParams(&opts, scheme.ParameterCodec).
        		Body(mutatingWebhookConfiguration).
        		Do(ctx).
        		Into(result)
        	return
        }
        
        // 删除采用 mutatingWebhookConfiguration 的名称并将其删除。如果发生错误,则返回错误。
        func (c *mutatingWebhookConfigurations) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error {
          // 请求apiserver,获取delete的请求结果(ps: 这里不做具体分析,待分析rest包再做分析)
        	return c.client.Delete().
        		Resource("mutatingwebhookconfigurations").
        		Name(name).
        		Body(&opts).
        		Do(ctx).
        		Error()
        }
        
        // DeleteCollection 删除对象集合。
        func (c *mutatingWebhookConfigurations) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error {
          // 设置请求timeout
        	var timeout time.Duration
        	if listOpts.TimeoutSeconds != nil {
        		timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
        	}
          // 请求apiserver,获取delete的请求结果(ps: 这里不做具体分析,待分析rest包再做分析)
        	return c.client.Delete().
        		Resource("mutatingwebhookconfigurations").
        		VersionedParams(&listOpts, scheme.ParameterCodec).
        		Timeout(timeout).
        		Body(&opts).
        		Do(ctx).
        		Error()
        }
        
        // Patch 应用patch并返回打过补丁的 mutatingWebhookConfiguration。
        func (c *mutatingWebhookConfigurations) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.MutatingWebhookConfiguration, err error) {
        	result = &v1.MutatingWebhookConfiguration{}
        	err = c.client.Patch(pt).
        		Resource("mutatingwebhookconfigurations").
        		Name(name).
        		SubResource(subresources...).
        		VersionedParams(&opts, scheme.ParameterCodec).
        		Body(data).
        		Do(ctx).
        		Into(result)
        	return
        }
        
        // Apply 接受给定的 apply 声明性配置,应用它并返回应用的 mutatingWebhookConfiguration。其实和Patch方法类似,只是此方法不需要序列化请求数据(只支持json),可以使用config对象代替(内部做了序列化)
        func (c *mutatingWebhookConfigurations) Apply(ctx context.Context, mutatingWebhookConfiguration *admissionregistrationv1.MutatingWebhookConfigurationApplyConfiguration, opts metav1.ApplyOptions) (result *v1.MutatingWebhookConfiguration, err error) {
          // 这里mutatingWebhookConfiguration参数必须不能为空
        	if mutatingWebhookConfiguration == nil {
        		return nil, fmt.Errorf("mutatingWebhookConfiguration provided to Apply must not be nil")
        	}
          // 转化为PatchOptions
        	patchOpts := opts.ToPatchOptions()
          // json 序列化为字节数组
        	data, err := json.Marshal(mutatingWebhookConfiguration)
        	if err != nil {
        		return nil, err
        	}
          // 这里用config中的name作为resourcename(用来形成path和apiserver交互)
        	name := mutatingWebhookConfiguration.Name
          // 注意:此处判断name必须不能为空
        	if name == nil {
        		return nil, fmt.Errorf("mutatingWebhookConfiguration.Name must be provided to Apply")
        	}
          // 用来接收apply请求结果
        	result = &v1.MutatingWebhookConfiguration{}
          // 请求apiserver,获取apply的请求结果(ps: 这里不做具体分析,待分析rest包再做分析)
        	err = c.client.Patch(types.ApplyPatchType).
        		Resource("mutatingwebhookconfigurations").
        		Name(*name).
        		VersionedParams(&patchOpts, scheme.ParameterCodec).
        		Body(data).
        		Do(ctx).
        		Into(result)
        	return
        }
        
    • validatingwebhookconfiguration.go
      类似与mutatingwebhookconfiguration.go 这里不做分析