code-generator 简介

存在的问题

  • 在 client-go篇 文章中,我们详细讲述了 如何使用 RESTClient、ClientSet 操作kubernetes的内建资源。然而,对于CRD资源,我们只能使用 DynamicClient 这种通用的Client去操作。
  • DynamicClient 是为操作所有资源而编写的通用Client,自然没有 某种资源 对应的Informer、Lister代码,所以使用DynamicClient,就无法像 使用ClientSet 那样,操作某一个特定资源的Informer、Lister等。
  • 为此我们想,能否为 CRD资源 生成和内建资源一样的Informer、Lister代码,这样的话,开发控制器的时候,我们就可以像使用内建资源一样,为CRD的informer注册事件方法,并使用Lister从缓存中获取数据。

code-generator是什么

  • kubernetes的开发中,有很多代码是相似而重复的,开发起来耗时耗力,因此就希望制作成了自动化工具,提高代码的可维护性和一致性。code-generator应运而生。

  • code-generator 是一个 代码生成工具集合,内部包含很多gen工具,用于自动生成与 Kubernetes 相关的客户端库、API 服务器(API server)和其他与 Kubernetes 相关的代码。

  • code-generator 位于 Kubernetes 代码库中的 staging/src/k8s.io/code-generator 包中,github地址为:https://github.com/kubernetes/code-generator

  • code-generator 的主要功能包括:

    • 自动生成客户端库clientset:通过定义自定义资源的 API 规范,code-generator 可以自动生成用于访问和操作这些自定义资源的客户端库。
    • 自动生成 API 服务器代码:code-generator 可以根据自定义资源的 API 规范,自动生成与之对应的 API 服务器代码。这使得开发者可以快速构建自己的自定义资源的 API 服务器,并将其部署到 Kubernetes 集群中。
    • 自动生成 DeepCopy 方法:对于 Kubernetes 对象,深拷贝是一种常见的操作,用于创建对象的副本。
    • 自动生成其他辅助代码:除了上述功能外,code-generator 还可以生成其他与 Kubernetes 相关的辅助代码,如列表(List)、转换器(Converter)等。

code-generator的常见应用场景

  • 为CRD编写自定义controller时,可以使用它来生成我们需要的versioned client、informer、lister以及其他工具方法
  • 编写自定义API Server时,可以用它来生成 internal 和 versioned类型的转换defaulters、internal 和 versioned的clients和informers

code-generator 的使用方法

  • code-generator是使用注释标记工作的,不同的gen工具,有不同的注释标记

code-generator 常用的gen工具

  • deepcopy-gen:为每个 T 类型生成 func (t* T) DeepCopy() *T 方法,API 类型都需要实现深拷贝
  • client-gen:生成类型化客户端集合(typed client sets),即与 Kubernetes API 服务器通信的客户端代码。
  • informer-gen:用于生成基于 Kubernetes API 资源的 Informer,提供事件机制来响应资源的事件,方便开发者执行资源监视操作。
  • lister-gen:用于生成 Kubernetes API 资源的 Lister,为 get 和 list 请求提供只读缓存层(通过 indexer 获取),可以实现高效的资源列表查询。
  • register-gen:自动生成 API 资源类型的注册表代码
  • conversion-gen:用于生成 Kubernetes 对象之间的转换器(Converter),方便在不同版本之间进行对象转换。
  • openapi-gen:用于生成 Kubernetes API 的 OpenAPI 规范,以便进行文档化和验证。

code-generator标记Tag

1、tag分类

  • code-generator 将 tag 分为了两种:
    • Global tags: 全局的tag,放在具体版本的doc.go文件中
    • Local tags: 本地的tag,放在types.go文件中的具体的struct上

2、tag使用语法

  • 使用语法:
    1
    2
    3
    4
    // +tag-name 

    // +tag-name=value

deepcopy-gen的常用标记

  • 在要生成 client 代码的类型type上方使用

    1
    2
    3
    4
    5
    6
    7
    8
    告诉代码生成器不生成该对象的深拷贝方法
    // +k8s:deepcopy-gen=false

    告诉代码生成器生成该对象的深拷贝方法
    // +k8s:deepcopy-gen=true

    指定生成的代码中实现的接口,这里指定了实现 k8s.io/apimachinery/pkg/runtime.Object 接口的代码
    // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
  • 在doc.go文件中使用

    1
    2
    3
    4
    5
    6
    7
    告诉代码生成器生成整个包的对象深拷贝方法。这意味着生成的代码将包含用于深拷贝包中所有对象的相关代码
    // +k8s:deepcopy-gen=package

    指定自定义 API 组的名称。这个注释用于定义自定义 API 资源的 API 组,使其能够与其他资源进行区分
    // +groupName=foo.example.com

    package v1

client-gen的常用标记

  • 在要生成 client 代码的类型type上方使用
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    指示代码生成器生成用于客户端库的代码
    // +genclient

    不要为自定义资源生成状态字段相关的代码
    // +genclient:noStatus

    表示这是一个集群级别的资源
    // +genclient:nonNamespaced

    不要生成默认的 HTTP 动词(verbs)相关的代码,这可能是因为该资源的操作方式与常规的 RESTful 操作并不完全相同
    // +genclient:noVerbs

    指示代码生成器只生成用于创建和删除操作的代码
    // +genclient:onlyVerbs=create,delete

    告诉代码生成器跳过指定的动词相关的代码生成,这表明生成的客户端库将不包含与这些操作相关的代码
    // +genclient:skipVerbs=get,list,create,update,patch,delete,deleteCollection,watch

    为特定的方法指定生成代码的细节,这里指定了当执行创建操作时所使用的方法以及其返回结果
    // +genclient:method=Create,verb=create,result=k8s.io/apimachinery/pkg/apis/meta/v1.Status

informer-gen的常用标记

  • 在要生成 client 代码的类型type上方使用
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    使用informer-gen必须要写这一行
    // +k8s:informers

    指定生成的 Informer 代码对应的 API 组和版本
    // +k8s:informers:groupVersion=${group}/${version}

    指定生成的 Informer 代码对应的内部 API 版本
    // +k8s:informers:internalVersion=internal/version

    指定生成的 Informer 代码是否需要为版本化的客户端集(Versioned ClientSet)生成代码
    // +k8s:informers:versionedClientSet=false

    指定生成的 Informer 代码是否需要使用缓存
    // +k8s:informers:cache

code-generator的运行脚本

  • 手动使用code-generator中某个gen工具,存在很多重复参数,也比较繁琐
  • 因此 code-generator 为我们提供了 两个脚本:generate-groups.sh 和 generate-internal-groups.sh
  • 在kubernetes 1.28 alpha 之后。提供了表述更清晰更好维护的脚本 kube_codegen.sh