![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=1738847423-nCpz9Ci7nrUpeZSaVkPDHpYGUVYuZQ49-0-737ba9b9fc88d6d0eacee46aded5dec8)
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=1738847423-jAapxUWUFYwIbWE1OEVogAJnnyszYB93-0-eed383f2b14b1fa99fc0fbfda95b702d)
表2-1 代码生成器说明
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_40_2.jpg?sign=1738847423-XZFyyP24mgqXGAp2ZFfBdniYBj87z31r-0-b9235dfe2adb503df3898b6bdf32ce3a)
除了以上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=1738847423-1H3aNlCrlC3HqXhgtOnjJd6yiadFbxNN-0-2f93fb45dd836564195c8d8d179ff9d3)
全局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=1738847423-oh61vmpSPMdsbSnviBXdXPC8UcvFwXLx-0-bb3e7677a42f303dc873b1ffd6cfd230)
局部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=1738847423-eDTcjYyVAxhza79H1LMc7tFXyb7gt392-0-f609f3ee2bd1392a9f624722a7e3585a)
这是因为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=1738847423-la1QLWyuiKVbebxWNIFbmAXcK1mwFQbk-0-138dccfaa066706e9ae08ee567f713a8)
为单个类型生成DeepCopy相关函数时,其Tags形式如下:
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_42_3.jpg?sign=1738847423-ibRWSEfwFAvMhhMtMW94jPgKnmm8IXiK-0-b3163c1b9ae7bd3bd790dcb04a518773)
为整个包生成DeepCopy相关函数时,可以忽略单个类型,其Tags形式如下:
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_42_4.jpg?sign=1738847423-j0BiqDORXVNmfyLXmZ9Ck2bNT1kf8bLr-0-373afc543e868be076c9064741cdaeb4)
有时在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=1738847423-R3c0EX0FyxkVXBoZ1qyvTEJLi5ZHyCqh-0-d145b5917bdbe1e3de60318d973a2d5d)
生成如下代码:
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_43_1.jpg?sign=1738847423-UcGZg99Aulph19DGfpUl9l72sV4Z2Bo7-0-f04c42b50c84fe7c2c7bebf6be0935c7)
下面介绍deepcopy-gen的使用示例和生成规则。
1.deepcopy-gen的使用示例
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_43_2.jpg?sign=1738847423-vuxO28ZQmlH27kiRWU3D9m6jpLArxQfp-0-eff28bdcb665a19bd03854e1b8f10516)
构建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=1738847423-8PFqq8L9Dk7E20UfsI4ldtUaB1LwbCb4-0-ca491943ed874fbad1ce40eea3a3f222)
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=1738847423-3p3yJySSAvINOFZgt4mhCpvqTbxDXMzD-0-decc7c34769eba829e70ff76a4dd9ae3)
为拥有ListMeta属性的类型生成Defaulter相关函数时,其Tags形式如下:
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_44_2.jpg?sign=1738847423-xcO1IwnE9NcPfxDsUxkxN1Pza7PFeKcO-0-acf7e93a4b56a4b910f1b5606e5597e7)
为拥有ObjectMeta属性的类型生成Defaulter相关函数时,其Tags形式如下:
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_44_3.jpg?sign=1738847423-SWmWqFku2mKggKxnEI7iETpwrfI6uXl5-0-164515d475c5368ee8aba46c302835ac)
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=1738847423-0iRrdFgc8hxFkkaSRrUkUyC52Xpw8bJC-0-7ab126867c74b54e335a483e3f72192f)
下面介绍defaulter-gen的使用示例和生成规则。
1.defaulter-gen的使用示例
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_44_5.jpg?sign=1738847423-4tMeMIB3jEd4ixH6CdZ8uDoODyYhDl4B-0-4efb255923ea0ce098d7c24e0ca29984)
构建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=1738847423-y3DpuktOphZx6CrduGk1Rmx1nflerKJr-0-e6153d1b1cc1c0ba5f841aa37c309290)
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=1738847423-HIJPo7I1Osr4HsriJ0sbwtDD9nutp6GY-0-d59cf2bfd6c6d88f35e16f4efac86dcc)
生成的Defaults函数如下:
代码路径:pkg/apis/rbac/v1/zz_generated.defaults.go
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_45_2.jpg?sign=1738847423-eOgbxKbLGhf2yZO0TovJ3ZKTlIOxqjTV-0-a352e0f0207af70c9731b415574cd065)
在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=1738847423-zrGFDizuALd8UUgV5DpUlDQREXDYoBCP-0-410c0aca3ba5973ddf7c0875f44e8445)
其中的<peer-pkg>用于定义包的导入路径,例如k8s.io/kubernetes/pkg/apis/abac。
为整个包生成Convert相关函数且依赖其他包时,其Tags形式如下:
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_45_4.jpg?sign=1738847423-TPVKmaThR65A9DARY9Ur838Dt23NsTvf-0-1610f39062bae19e34433ecd42e7bc3c)
其中的<type-pkg>用于定义其他包的路径,例如k8s.io/api/autoscaling/v1。
在排除某个属性后生成Convert相关函数时,其Tags形式如下:
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_45_5.jpg?sign=1738847423-nvSAcZ7MPw8Ul2RpjcUT4sTdsJl9JJHY-0-5f4d9a3cd1aeaad285a19c6dfc64b9cd)
下面介绍conversion-gen的使用示例和生成规则。
1.conversion-gen的使用示例
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_46_1.jpg?sign=1738847423-QuUiKIicicaUQZgRvqiKd6msfSxsit2O-0-4efad0f7187650fc005b1b533ede230a)
构建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=1738847423-Ap5NE6FrEnEEGkLGUVrsOBZ8VMs8vY28-0-43481fbf0e4100f1171a4e7ab6836dd0)
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=1738847423-f0IpCtAqwEKjj60oh51U9p8tGutg58Aw-0-38329781de5c9fa4130c8711adf41ea5)
生成的Convert函数如下:
代码路径:pkg/apis/abac/v1beta1/zz_generated.conversion.go
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_47_1.jpg?sign=1738847423-WHvO29sJRuczAkhyUNZY4MYusxCZQw0f-0-c172ec4a9d173ba8c6c629f7c8074837)
在types.go中定义了Policy类型,conversion-gen为该类型生成了Convert函数,例如从v1beta1转换为internal内部版本,从internal内部版本转换为v1版本,代码示例如下:
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_47_2.jpg?sign=1738847423-qmHuuG1aDLbCMnpmDep3HYQwbHR9VNHI-0-884d93c58fc7815def95de637254ff6a)
定义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=1738847423-D1uTxKlrzuaxDhZ9tnjNJotCEs03L2sN-0-19c475230e4fd72fa74ad4e96991842c)
排除为特定类型或包生成OpenAPI定义文件时,其Tags形式如下:
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_47_4.jpg?sign=1738847423-Lal1PugNY7TwBH7XyqwczOtZupoKl2xp-0-0afe454106bfe946f884d6a235e62a30)
下面介绍openapi-gen的使用示例和生成规则。
1.openapi-gen的使用示例
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_48_1.jpg?sign=1738847423-dl35uSUoEnmGcxRJDbjFaREpla4wDEak-0-a25730a4778b56117cda96b9e92ed496)
构建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=1738847423-TzcgbQn9mPqjPAJ2wBrpqpGeJpkIKkuY-0-fec025c94297b289ac0a0c7d452129b2)
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=1738847423-LFMJ7RxLAE9MQPisrENLt4dhwygTuwaM-0-fed687af330439cbc77337652deb58e5)
生成的OpenAPIDefinition如下:
代码路径:pkg/generated/openapi/zz_generated.openapi.go
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_49_1.jpg?sign=1738847423-En2r95yW6ngz4vbj5r5ZZ0sshTzf8uSK-0-b953698ea0a1e6c3e8e70a236042a3d0)
在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=1738847423-Mkh1LVRiCPJRIaEbTFsUHlsDqxWbY0dz-0-a61027ed4c049e92620729344f0062d1)
generate-bindata.sh脚本重点执行如下代码:
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_49_3.jpg?sign=1738847423-0HRqJmNa0SXCNujSkAEaW1JRglYGSJA2-0-239b5478b9ce1f5e44d80ba37f305862)
构建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=1738847423-bXBFWleMN7jmulIT8DxLKCBXyjSVQfQu-0-99d94ca02b8ec4a79304d5dd706e0c67)