K8s源码分析(21)-client go组件之资源操作对象

2022-10-30 13:22:59 浏览数 (1)

上一篇文章里,我们主要介绍了 client go 这个基础组件相关的 request 和 result 对象,这两个对象主要用来发送资源操作的请求,以及处理相关的响应。众所周知, kubernetes 中的资源是分 group/version 的,本篇文章里我们主要来介绍对于不同组以及版本的资源操作对象。

资源操作对象层级

kubernetes 资源对象是区分组和版本的,对于不同组和不同版本下的资源有不同的操作对象定义,在源码结构里资源操作对象如下:

  • 对于不同组下资源操作对象
  • 对于组内不同版本下资源操作对象
  • 资源操作对象的具体定义

资源操作对象的定义

由于kubernetes 资源对象有非常多的组和版本,这里我们就以常见的 apps 组下的 v1 版本中的 deployment 资源为例,介绍该资源的操作对象。其图解和相关源码如下:

代码语言:javascript复制
//staging/src/k8s.io/client-go/kubernetes/typed/apps/v1/deployment.go
type DeploymentInterface interface {
  Create(ctx context.Context, deployment *v1.Deployment, opts metav1.CreateOptions) (*v1.Deployment, error)
  Update(ctx context.Context, deployment *v1.Deployment, opts metav1.UpdateOptions) (*v1.Deployment, error)
  UpdateStatus(ctx context.Context, deployment *v1.Deployment, opts metav1.UpdateOptions) (*v1.Deployment, 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.Deployment, error)
  List(ctx context.Context, opts metav1.ListOptions) (*v1.DeploymentList, 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.Deployment, err error)
  Apply(ctx context.Context, deployment *appsv1.DeploymentApplyConfiguration, opts metav1.ApplyOptions) (result *v1.Deployment, err error)
  ApplyStatus(ctx context.Context, deployment *appsv1.DeploymentApplyConfiguration, opts metav1.ApplyOptions) (result *v1.Deployment, err error)
  GetScale(ctx context.Context, deploymentName string, options metav1.GetOptions) (*autoscalingv1.Scale, error)
  UpdateScale(ctx context.Context, deploymentName string, scale *autoscalingv1.Scale, opts metav1.UpdateOptions) (*autoscalingv1.Scale, error)
  ApplyScale(ctx context.Context, deploymentName string, scale *applyconfigurationsautoscalingv1.ScaleApplyConfiguration, opts metav1.ApplyOptions) (*autoscalingv1.Scale, error)
  DeploymentExpansion
}

type deployments struct {
  client rest.Interface
  ns     string
}

func (c *deployments) Get(ctx context.Context, name string, options metav1.GetOptions) (result *v1.Deployment, err error) 
func (c *deployments) List(ctx context.Context, opts metav1.ListOptions) (result *v1.DeploymentList, err error) 
func (c *deployments) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error)
func (c *deployments) Create(ctx context.Context, deployment *v1.Deployment, opts metav1.CreateOptions) (result *v1.Deployment, err error)
func (c *deployments) Update(ctx context.Context, deployment *v1.Deployment, opts metav1.UpdateOptions) (result *v1.Deployment, err error)
func (c *deployments) UpdateStatus(ctx context.Context, deployment *v1.Deployment, opts metav1.UpdateOptions) (result *v1.Deployment, err error)
func (c *deployments) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error 
func (c *deployments) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error
func (c *deployments) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.Deployment, err error)
func (c *deployments) Apply(ctx context.Context, deployment *appsv1.DeploymentApplyConfiguration, opts metav1.ApplyOptions) (result *v1.Deployment, err error)
func (c *deployments) ApplyStatus(ctx context.Context, deployment *appsv1.DeploymentApplyConfiguration, opts metav1.ApplyOptions) (result *v1.Deployment, err error) 
func (c *deployments) GetScale(ctx context.Context, deploymentName string, options metav1.GetOptions) (result *autoscalingv1.Scale, err error)
func (c *deployments) UpdateScale(ctx context.Context, deploymentName string, scale *autoscalingv1.Scale, opts metav1.UpdateOptions) (result *autoscalingv1.Scale, err error) 
func (c *deployments) ApplyScale(ctx context.Context, deploymentName string, scale *applyconfigurationsautoscalingv1.ScaleApplyConfiguration, opts metav1.ApplyOptions)


func (c *deployments) Get(ctx context.Context, name string, options metav1.GetOptions) (result *v1.Deployment, err error) {
  result = &v1.Deployment{}
  err = c.client.Get().
    Namespace(c.ns).
    Resource("deployments").
    Name(name).
    VersionedParams(&options, scheme.ParameterCodec).
    Do(ctx).
    Into(result)
  return
}

type DeploymentsGetter interface {
  Deployments(namespace string) DeploymentInterface
}
  • DeploymentInterface 接口定义了对于该资源的所有操作,例如常见的增删改查,扩容,修改状态,list/watch 等等。
  • deployments 结构体实现了上面定义的接口,是实际的资源操作对象。该结构体中封装了 rest.Interface 接口类型对象,也就是以前文章中介绍的 RESTClient 对象实现的接口。同时也封装了 namespace 信息,表示被操作的资源属于哪个命名空间。
  • 在上述结构体实现的接口方法的定义里,利用内部封装的之前文章介绍的接口类型来发起对资源的操作请求,并处理相应结果,例如反序列化成资源对象。
  • DeploymentGetter 接口定义了获取该资源的操作对象,可以认为是源的操作对象对应的工厂方法。

同一组下相同版本资源操作对象工厂

上面介绍了具体某一个资源的操作对象,同样我们还是以 apps 组下的 v1 版本中所有的资源为例子,看看它们是怎么聚合起来以达到方便操作的目的。对于 apps 组下的 v1 版本中所有的资源操作对象聚合图解和相关源码如下:

代码语言:javascript复制
// k8s.io/client-go/kubernetes/typed/apps/v1/apps_client.go
type AppsV1Interface interface {
  RESTClient() rest.Interface
  ControllerRevisionsGetter
  DaemonSetsGetter
  DeploymentsGetter
  ReplicaSetsGetter
  StatefulSetsGetter
}

type AppsV1Client struct {
  restClient rest.Interface
}

func (c *AppsV1Client) ControllerRevisions(namespace string) ControllerRevisionInterface {
  return newControllerRevisions(c, namespace)
}

func (c *AppsV1Client) DaemonSets(namespace string) DaemonSetInterface {
  return newDaemonSets(c, namespace)
}

func (c *AppsV1Client) Deployments(namespace string) DeploymentInterface {
  return newDeployments(c, namespace)
}

func (c *AppsV1Client) ReplicaSets(namespace string) ReplicaSetInterface {
  return newReplicaSets(c, namespace)
}

func (c *AppsV1Client) StatefulSets(namespace string) StatefulSetInterface {
  return newStatefulSets(c, namespace)
}

func (c *AppsV1Client) RESTClient() rest.Interface {
  if c == nil {
    return nil
  }
  return c.restClient
}
// k8s.io/client-go/kubernetes/typed/apps/v1/deployment.go
type DeploymentsGetter interface {
  Deployments(namespace string) DeploymentInterface
}

func newDeployments(c *AppsV1Client, namespace string) *deployments {
  return &deployments{
    client: c.RESTClient(),
    ns:     namespace,
  }
}
  • AppsV1Interface 接口封装了该组的版本下所有资源操作对象的工厂方法,同时也封装了之前文章介绍的 rest.Interface 接口,所以可以把该接口看作是更高一级的资源操作对象工厂定义。
  • AppsV1Client 结构体实现了上面定义的接口,所以通过该结构体可以得到某一组某一版本下所有资源操作对象的工厂,也就间接获得了所有的资源操作对象。

资源操作对象工厂的实例化

我们还是以 apps 组下的 v1 版本中的资源操作对象工厂为例,来介绍该工厂是如何被创建的,其相关的源代码如下:

代码语言:javascript复制
// k8s.io/client-go/kubernetes/typed/apps/v1/apps_client.go
func NewForConfig(c *rest.Config) (*AppsV1Client, error) {
  config := *c
  if err := setConfigDefaults(&config); err != nil {
    return nil, err
  }
  client, err := rest.RESTClientFor(&config)
  if err != nil {
    return nil, err
  }
  return &AppsV1Client{client}, nil
}

func setConfigDefaults(config *rest.Config) error {
  gv := v1.SchemeGroupVersion
  config.GroupVersion = &gv
  config.APIPath = "/apis"
  config.NegotiatedSerializer = scheme.Codecs.WithoutConversion()

  if config.UserAgent == "" {
    config.UserAgent = rest.DefaultKubernetesUserAgent()
  }

  return nil
}

// staging/src/k8s.io/client-go/kubernetes/scheme/register.go
var Scheme = runtime.NewScheme()
var Codecs = serializer.NewCodecFactory(Scheme)
var ParameterCodec = runtime.NewParameterCodec(Scheme)
var localSchemeBuilder = runtime.SchemeBuilder{
  admissionregistrationv1.AddToScheme,
  admissionregistrationv1beta1.AddToScheme,
  internalv1alpha1.AddToScheme,
  appsv1.AddToScheme,
  appsv1beta1.AddToScheme,
  appsv1beta2.AddToScheme,
  authenticationv1.AddToScheme,
  authenticationv1beta1.AddToScheme,
  authorizationv1.AddToScheme,
  authorizationv1beta1.AddToScheme
  .........
}
var AddToScheme = localSchemeBuilder.AddToScheme
func init() {
  v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"})
  utilruntime.Must(AddToScheme(Scheme))
}
  • 资源操作对象工厂创建的核心就是构造 config 对象,由该对象构造之前文章中介绍的 rest.Interface 接口类型对象,进而构造资源操作对象工厂。
  • 在构造 config 对象的时候会用到之前文章中介绍的 schema 对象,该对象中注册了所有的 kubernetes 资源以及提供相应的对象创建,版本转化,序列化反序列化等系列功能。
  • 所以其整个资源操作对象工厂创建过程可以用如下图表示:

目前先我们写到这里,在下一篇文章中我们继续来介绍 clientset 对象。

0 人点赞