![Kubernetes源码剖析](https://wfqqreader-1252317822.image.myqcloud.com/cover/962/32435962/b_32435962.jpg)
2.5 代码生成器
顶层Makefile中定义了generated_files命令,该命令用于构建代码生成器,下面看一下generated_files在Makefile.generated_files中的定义:
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_39_2.jpg?sign=1738890166-kcPfMd6U2TTzqmWHWr5MkRIxjIToLZLp-0-c8bd903ee9409e1810fb64ac105f1aaf)
generated_files中定义了5个代码生成器,执行make all命令后,这些二进制文件被输出至_output/bin/目录,如下面的输出内容所示。如果二进制文件不存在,也可以通过make generated_files命令单独构建代码生成器的二进制工具。下面分别介绍这些代码生成器,如表2-1所示。
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_40_1.jpg?sign=1738890166-Hd4jwvsLNEmnIUqML44gTqb2PpR7QUSB-0-ed81fd6bd3741d6984eec63889ee80c6)
表2-1 代码生成器说明
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_40_2.jpg?sign=1738890166-KuDNT2RVoLYEZhKsSZx8SMIsKGAaF4Nj-0-814dbb543e9b33cc786dbd22130dee3e)
除了以上5个代码生成器,Kubernetes实际上还支持更多的代码生成器,例如client-gen、lister-gen、informer-gen等代码生成器。这些代码生成器会在后面的章节中进行介绍,本节提及的这5个代码生成器是构建Kubernetes源码过程中所需要的。
2.5.1 Tags
代码生成器通过Tags(标签)来识别一个包是否需要生成代码及确定生成代码的方式,Kubernetes提供的Tags可以分为如下两种。
● 全局Tags:定义在每个包的doc.go文件中,对整个包中的类型自动生成代码。
● 局部Tags:定义在Go语言的类型声明上方,只对指定的类型自动生成代码。
Tags的定义规则通常为//+tag-name或//+tag-name=value,它们被定义在注释中。
1.全局Tags
全局Tags定义在pkg/apis/<group>/<version>/doc.go中,代码示例如下:
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_41_1.jpg?sign=1738890166-4qZ5zqDB5WwdiDaIiKmhTAoOfbsHocrI-0-fa9bbb2fd2f6c1e911d50b5447b3dada)
全局Tags告诉deepcopy-gen代码生成器为该包中的每个类型自动生成DeepCopy函数。其中的//+groupName定义了资源组名称,资源组名称一般使用域名形式命名。
2.局部Tags
局部Tags定义在Go语言的类型声明上方,代码示例如下:
代码路径:pkg/apis/core/types.go
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_41_2.jpg?sign=1738890166-vndGFSrqO77fGFmXiCsRuodahbcvrbk7-0-99293be5ee3293cd9817e4b7284b0670)
局部Tags定义在Pod资源类型的上方,它定义了该类型有两个代码生成器,分别为genclient(即client-gen)和deepcopy-gen。其中genclient代码生成器为这个资源类型自动生成对应的客户端代码,deepcopy-gen代码生成器为这个资源类型自动生成DeepCopy函数。
注意:关于Tags的位置,局部Tags一般定义在类型声明的上方,但如果该类型有注释信息,则局部Tags的定义需要与类型声明的注释信息之间至少有一个空行。例如:
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_42_1.jpg?sign=1738890166-BhRuSHUxaOsDW6LSZJ9RqzMq1FFvFDfc-0-1575adb48b08e0de1adc3583b7c02cca)
这是因为Kubernetes的API文档生成器会根据类型声明的注释信息(comment-block)生成文档。为了避免Tags信息出现在文档中,故将Tags定义在注释的上方并空一行。
2.5.2 deepcopy-gen代码生成器
deepcopy-gen是一个自动生成DeepCopy函数的代码生成器。给定一个包的目录路径作为输入源,它可以为其生成DeepCopy相关函数,这些函数可以有效地执行每种类型的深复制操作。
为整个包生成DeepCopy相关函数时,其Tags形式如下:
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_42_2.jpg?sign=1738890166-mB8Ym29Q6gHq4AXtGLZVcbFogQcsV3uh-0-bcebd23cd5ec360efe87153935bbf278)
为单个类型生成DeepCopy相关函数时,其Tags形式如下:
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_42_3.jpg?sign=1738890166-4Nn0jwxQMFbjOexCg4nr1CageazKDkAz-0-61272348b8d2ba76037cc14e21555de0)
为整个包生成DeepCopy相关函数时,可以忽略单个类型,其Tags形式如下:
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_42_4.jpg?sign=1738890166-5q7LHyVpLHzv0ozUa06g9ZohAZyLZq7F-0-2cce776598188defa3f5079ab89f2650)
有时在Kubernetes源码里会看到deepcopy-gen的Tags被定义成runtime.Object,这时deepcopy-gen会为该类型生成返回值为runtime.Obejct类型的DeepCopyObject函数,代码示例如下:
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_42_5.jpg?sign=1738890166-A28ts9PP9BsofhstYp58x7n7wwmY1AVT-0-a15cd875efcc00f6ea5f8c8c1bf1013f)
生成如下代码:
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_43_1.jpg?sign=1738890166-pNzT6DxfK8kMqeSQwCnaJ8vhiyTXRSts-0-c66c366fa06bd059fff428f5b809052c)
下面介绍deepcopy-gen的使用示例和生成规则。
1.deepcopy-gen的使用示例
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_43_2.jpg?sign=1738890166-31VIaw6bVFm0Ml3fUlyzu6xPBc5cvAaS-0-b158d056a2d5548c26c10f84c2fb398b)
构建deepcopy-gen二进制文件,并执行deepcopy-gen代码生成器,为k8s.io/kubernetes/pkg/apis/abac/v1beta1包生成zz_generated.deepcopy.go代码文件。
2.deepcopy-gen的生成规则
代码路径:vendor/k8s.io/gengo/examples/deepcopy-gen/generators/deepcopy.go
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_43_3.jpg?sign=1738890166-nugrU6kxlFytLd8Iax7oNR7dn9Ivj5cJ-0-f7e03d43ab665b600c3e37110fc55800)
deepcopy-gen会遍历包中的所有类型,若类型为types.Struct,则会为该类型生成深复制函数。
2.5.3 defaulter-gen代码生成器
defaulter-gen是一个自动生成Defaulter函数的代码生成器。给定一个包的目录路径作为输入源,它可以为其生成Defaulter相关函数,这些函数可以为资源对象生成默认值。
为拥有TypeMeta属性的类型生成Defaulter相关函数时,其Tags形式如下:
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_44_1.jpg?sign=1738890166-hXtdRHbj5BzVs3aDXQV0KyGDjaWUqb6u-0-2aa3f6835fb9467a6427c6757a45c0b0)
为拥有ListMeta属性的类型生成Defaulter相关函数时,其Tags形式如下:
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_44_2.jpg?sign=1738890166-Eig1BkL3KWINaRIekfsYRnCsvVnejRpp-0-ff318065f5e0d66b2c70631db3754f37)
为拥有ObjectMeta属性的类型生成Defaulter相关函数时,其Tags形式如下:
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_44_3.jpg?sign=1738890166-gIVPn9rm5wOtW00YukmsSe8Zsefn5h11-0-750a30a7c41101436003c179528d994b)
defaulter-gen的Tags都属于全局Tags,没有局部Tags。其值可以为TypeMeta、ListMeta、ObjectMeta,最常用的是TypeMeta。有时在Kubernetes源码里会看到defaulter-gen-input,这说明当前包会依赖于指定的路径包,代码示例如下:
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_44_4.jpg?sign=1738890166-pAUlyaP9ywF33174s4Oz2FP8bXZDOFGH-0-175be372b5ba1ceab1e6ab5e79ab7106)
下面介绍defaulter-gen的使用示例和生成规则。
1.defaulter-gen的使用示例
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_44_5.jpg?sign=1738890166-7ihsJKcSWAiQGODyCNvL6IyxrwBoIOgh-0-f2a3513067916f0949065c2677f9c15f)
构建defaulter-gen二进制文件,并执行defaulter-gen代码生成器,为k8s.io/kubernetes/pkg/apis/rbac/v1包生成zz_generated.defaults.go代码文件。
2.defaulter-gen的生成规则
代码路径:k8s.io/gengo/examples/defaulter-gen/generators/defaulter.go
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_44_6.jpg?sign=1738890166-N21g6eOezUqI9eFk32uuf4dznw2BIsBL-0-40311c0416fedf917da2c86033894877)
defaulter-gen会遍历包中的所有类型,若类型属性拥有特定类型(如TypeMeta、ListMeta、ObjectMeta),则为该类型生成Defaulter函数,并为其生成RegisterDefaults注册函数,代码示例如下:
代码路径:pkg/apis/rbac/v1/defaults.go
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_45_1.jpg?sign=1738890166-M2uo10mQrp6NojSkpVywnPEYPeVaiOyH-0-f300d50fe7757de4d755450d2ae7e2a9)
生成的Defaults函数如下:
代码路径:pkg/apis/rbac/v1/zz_generated.defaults.go
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_45_2.jpg?sign=1738890166-2Iv1jphNfs5PexUra0I3NQ5y3zwz8mAi-0-9e90161e0c9f91834c3786d9d5567988)
在defaults.go中定义了rbacv1.ClusterRoleBinding类型,该类型拥有TypeMeta属性,并为该属性生成SetObjectDefaults_ClusterRoleBinding函数。
2.5.4 conversion-gen代码生成器
conversion-gen是一个自动生成Convert函数的代码生成器。给定一个包的目录路径作为输入源,它可以为其生成Convert相关函数,这些函数可以为对象在内部和外部类型之间提供转换函数。
为整个包生成Convert相关函数时,其Tags形式如下:
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_45_3.jpg?sign=1738890166-gO9JNJndlaLnBKjUw61iTAmkq9EPKlaw-0-69eb0a956537eff0fd33d115c7442d01)
其中的<peer-pkg>用于定义包的导入路径,例如k8s.io/kubernetes/pkg/apis/abac。
为整个包生成Convert相关函数且依赖其他包时,其Tags形式如下:
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_45_4.jpg?sign=1738890166-lhO216E41ul42prOwynU38eyzDlycVqY-0-6f949740efdbe8bd295167a43d8f5f53)
其中的<type-pkg>用于定义其他包的路径,例如k8s.io/api/autoscaling/v1。
在排除某个属性后生成Convert相关函数时,其Tags形式如下:
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_45_5.jpg?sign=1738890166-8i1arvDcS7RAyIW6dx847aZXVGkTTocK-0-12a44a3ba143c3c0ff488575622d5ff1)
下面介绍conversion-gen的使用示例和生成规则。
1.conversion-gen的使用示例
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_46_1.jpg?sign=1738890166-BjzoYPFrk8XJHnz8PlE4pJHxbzPI3K2R-0-2a90fa40770c4f42a15b397d706f8e17)
构建conversion-gen二进制文件,并执行conversion-gen代码生成器,为k8s.io/kubernetes/pkg/apis/abac/v1beta1包生成zz_generated.conversion.go代码文件。
2.conversion-gen的生成规则
代码路径:vendor/k8s.io/code-generator/cmd/conversion-gen/generators/conversion.go
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_46_2.jpg?sign=1738890166-7G29pO74wCzwkg37GLa4WITCxQdzanpj-0-89c3333959257eed8ed1cbb33af3ab15)
conversion-gen会遍历包中的所有类型,若类型为types.Struct且过滤掉了私有的Struct类型,则为该类型生成Convert函数,并为该类型同时生成RegisterConversions注册函数,代码示例如下:
代码路径:pkg/apis/abac/v1beta1/types.go
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_46_3.jpg?sign=1738890166-RE3n7HYwcBfL55CoaMW01ef172Q1iCU6-0-fb2cf529a9692e9637304051b7caf8a6)
生成的Convert函数如下:
代码路径:pkg/apis/abac/v1beta1/zz_generated.conversion.go
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_47_1.jpg?sign=1738890166-NogBrXGVSGreONZ7tEjciUQIZspD0KSj-0-4cb9cfe05278c5b9de37e4a7287cd98f)
在types.go中定义了Policy类型,conversion-gen为该类型生成了Convert函数,例如从v1beta1转换为internal内部版本,从internal内部版本转换为v1版本,代码示例如下:
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_47_2.jpg?sign=1738890166-Rouuj3jsB6cOQRixBTlrHsOIU2xBpH5w-0-22cceb7b309379bdbaf6a3e7af246d7d)
定义old变量为v1beta1资源版本,通过Convert函数将v1beta1版本转换为内部版本(即internal变量)。
2.5.5 openapi-gen代码生成器
openapi-gen是一个自动生成OpenAPI定义文件(OpenAPI Definition File)的代码生成器,给定一个包的目录路径作为输入源,它可以为其生成OpenAPI定义文件,该文件用于kube-apiserver服务上的OpenAPI规范的生成。更多关于OpenAPI规范的内容,详情请参考7.1.3节“OpenAPI/Swagger核心原理”。
为特定类型或包生成OpenAPI定义文件时,其Tags形式如下:
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_47_3.jpg?sign=1738890166-xd5dcKEfzmtcXGQUSL7Mr7RjuPRVPZTV-0-723e20bae73457c4cfce98e72639158b)
排除为特定类型或包生成OpenAPI定义文件时,其Tags形式如下:
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_47_4.jpg?sign=1738890166-7YicImH3cvinuSAoqdNFlALutJVQgf9Q-0-2198711986971856f5d3287f2b7949a0)
下面介绍openapi-gen的使用示例和生成规则。
1.openapi-gen的使用示例
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_48_1.jpg?sign=1738890166-prh0UMB9lmMUptCfLmsdqNY3dqt3hHCn-0-c77a89ac88cb386f6ba9cf30401b6503)
构建openapi-gen二进制文件,并执行openapi-gen代码生成器,为k8s.io/kubernetes/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1包生成zz_generated.openapi.go代码文件,该代码文件存放在k8s.io/kubernetes/pkg/generated/openapi目录下。
2.openapi-gen的生成规则
代码路径:vendor/k8s.io/kube-openapi/pkg/generators/openapi.go
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_48_2.jpg?sign=1738890166-U85eU12BwQO0ehQ8Hhrwg0zdN2HBUlHG-0-6ddded7a5e19dbf5d9a7ff5531b4dd59)
openapi-gen会遍历包中的所有类型,若类型为types.Struct并忽略其他类型,则为types.Struct类型生成OpenAPI定义文件。例如:
代码路径:vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/types.go
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_48_3.jpg?sign=1738890166-kLO0h3Gx5yyIU12UF6P6nye6IKCqas58-0-2bc514f44287ff662c146d308ebc91e8)
生成的OpenAPIDefinition如下:
代码路径:pkg/generated/openapi/zz_generated.openapi.go
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_49_1.jpg?sign=1738890166-4uTcgvmTrGbJgPNfIsn68XUxJfFjxfqq-0-f64a7341df2bea57f8c5f61841332cf8)
在types.go中定义了CustomResourceDefinitionSpec类型,openapi-gen为该类型生成了OpenAPIDefinition。
2.5.6 go-bindata代码生成器
go-bindata是一个第三方工具,它能够将静态资源文件嵌入Go语言中,例如在Web开发中,它可以将静态的HTML、JavaScript等静态资源文件嵌入Go语言代码文件中并提供一些操作方法。给定一个静态资源目录路径作为输入源,go-bindata可以为其生成go文件。go-bindata使用示例如下:
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_49_2.jpg?sign=1738890166-78zBX17jtzkOQ1eLnydmhEwboM01aiWe-0-16d7620f1e1adf5248e20d86d06e7875)
generate-bindata.sh脚本重点执行如下代码:
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_49_3.jpg?sign=1738890166-Hjn4yVxnHpuXeBneEmaaWpKFoLKL1gvU-0-7bb8dfbf13cb2f21b3f22b0b496845f2)
构建go-bindata二进制文件,并执行go-bindata代码生成器,为translations静态资源目录生成pkg/kubectl/generated/bindata.go.tmp文件。translations目录存放的是与i18n(国际化)语言包相关的文件,在不修改内部代码的情况下支持不同语言及地区。例如,Zh语言包的二进制数据在Go语言中的存储内容如下:
代码路径:pkg/kubectl/generated/bindata.go
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_50_1.jpg?sign=1738890166-ZjlUZ6TPdNSyUl6drkZnQXHBPreMsOIj-0-095be16cd1e913bb45aa1f3bece92d75)