![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=1739220410-GcsHu6WLNnDF3TGHUInLpax3CkZ9RFsV-0-f6ed4fe4b3c379bb420d39a516004d21)
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=1739220410-A8Or8qu90aCNsTB3eBhp57JKhvL7pnNP-0-0175d2f1660fded8af05533e9bd24422)
表2-1 代码生成器说明
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_40_2.jpg?sign=1739220410-EIAYYO5w50qiFsgmQuPgNg9275uiQ6tK-0-4163452379980c3bd56be3ed3c15b462)
除了以上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=1739220410-oCdUN5LRnVyGvocpBtxf0GEsaTq2Uf2b-0-aa5df52e24ba53fc18cd43943d6beaa7)
全局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=1739220410-tdM9KeY2mo8JmhYuelyQUVWsBISS9ut0-0-ea2d52ec3fbed12fa8d3f86ec90ffee5)
局部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=1739220410-527tl3nJVJQpef0HsBT5ayzntBdBpr7y-0-313a8bc9ac199ec450177ba63e954b7c)
这是因为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=1739220410-YwrTmAH0XPIHsYXMuAYkXZ7dcxjuBkFn-0-d3a2d43697aff1d3d67b8b5dcb569b6a)
为单个类型生成DeepCopy相关函数时,其Tags形式如下:
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_42_3.jpg?sign=1739220410-vCUr1kBnInhbZBjKZul6Fk1iBnhFCHLf-0-1833b116d7606202b673d22e600d9ecd)
为整个包生成DeepCopy相关函数时,可以忽略单个类型,其Tags形式如下:
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_42_4.jpg?sign=1739220410-EshtxwXYtGqKTy6BpCMMPqTBIsLr9jcm-0-e197538eba3cc98fbe23d1ec61bf3cf8)
有时在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=1739220410-fOmTvBSkQFiYaRYdx3DClfw3ls6ROznk-0-97b6ffc52ee8da6001a74d1a22e93ae5)
生成如下代码:
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_43_1.jpg?sign=1739220410-nBLobXkrbVc0d3MbF0ZBcdyu8JfDM5LK-0-a71152012f47e9ec63ce71a30820a0cb)
下面介绍deepcopy-gen的使用示例和生成规则。
1.deepcopy-gen的使用示例
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_43_2.jpg?sign=1739220410-lCW0BX0gedXuiLpTrwr7nfAIK19ofOpl-0-3f8302a73e15aaddcb4b3bf20e88c72d)
构建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=1739220410-JQm1UsgQqrX2HnOlRqZvfmUGCQ6DOjfg-0-0d09c817ff514e8379e06fa535bc4dc1)
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=1739220410-qIZuhgkjeR2nNlI8etNFsxcLHku1Qd3M-0-af142294b5ec9f40a61e3b4ce32c2e9d)
为拥有ListMeta属性的类型生成Defaulter相关函数时,其Tags形式如下:
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_44_2.jpg?sign=1739220410-4LgS9kFiSbvaENffymCfQokZaEyxJdmg-0-71d95f6f751fa874fe12adc67b3195e2)
为拥有ObjectMeta属性的类型生成Defaulter相关函数时,其Tags形式如下:
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_44_3.jpg?sign=1739220410-NzkxKFcdCXLIIRCxsShk4mf6XuXXsWvR-0-acc366264101d0c5ffb10986a685957e)
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=1739220410-Tmqiq2YcH0XIfikFDAUCLDNPEYVzYGQv-0-3efd74388bf925a6df3dcaa12bb6a620)
下面介绍defaulter-gen的使用示例和生成规则。
1.defaulter-gen的使用示例
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_44_5.jpg?sign=1739220410-cxLox6pH3S2Fl6qzeb2ONaiU7GJ7z3wC-0-1082140d6363cf2ec207b9611c18c47d)
构建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=1739220410-I5vQE9RHz7RC5KmlP40OGwDZx6udgfkI-0-c3411c3f4f1da2a179799d56e6439374)
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=1739220410-e4MWqcKtD4gYlzEwVaIme4I6hwqNTbYW-0-6e56add9e2e871e37653a60d81c5145b)
生成的Defaults函数如下:
代码路径:pkg/apis/rbac/v1/zz_generated.defaults.go
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_45_2.jpg?sign=1739220410-D1Gd6SUxyBmcDUUsMQnX1H4VQBxT4Afj-0-6230ed716fcbb2b46279f734251c3e93)
在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=1739220410-88uF7vrHfq1NU1PGXqawb7Fc1eU9DQ98-0-87be098c558e1b5b60a42b75b2d40c57)
其中的<peer-pkg>用于定义包的导入路径,例如k8s.io/kubernetes/pkg/apis/abac。
为整个包生成Convert相关函数且依赖其他包时,其Tags形式如下:
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_45_4.jpg?sign=1739220410-s25NOpxbwwaLomDjXAYe1Qf61hs1W86c-0-ab89c8aec4cb1b63a27145066b61f1d0)
其中的<type-pkg>用于定义其他包的路径,例如k8s.io/api/autoscaling/v1。
在排除某个属性后生成Convert相关函数时,其Tags形式如下:
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_45_5.jpg?sign=1739220410-Fvzb8tB5jJJqCUDTASMzygg1jyZffoxk-0-8e3bd4624bbb6f249af9150f71dcb3ff)
下面介绍conversion-gen的使用示例和生成规则。
1.conversion-gen的使用示例
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_46_1.jpg?sign=1739220410-ArNnR1Z35Kiz4t1oy97JLkpegNtmSWpY-0-e35e4b0b405e5f2089822e2bcc6fcad7)
构建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=1739220410-imyDoq2xBDgQYGzenpYAGJPJT9kckx9v-0-97eb663bf1ba10b27d8d8f83167f894b)
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=1739220410-5UL3dNmaXqy2LbB7Lt7JuSZxE2Y3Rrbc-0-c3b07386abba8a15982bace4836730f8)
生成的Convert函数如下:
代码路径:pkg/apis/abac/v1beta1/zz_generated.conversion.go
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_47_1.jpg?sign=1739220410-lUFm8TTzlnbhg63zH4XTImAk3g8dZyqv-0-73ae1acfe0057507bcd7a623c3783a71)
在types.go中定义了Policy类型,conversion-gen为该类型生成了Convert函数,例如从v1beta1转换为internal内部版本,从internal内部版本转换为v1版本,代码示例如下:
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_47_2.jpg?sign=1739220410-5qmHBW5yDvKZHEsJipfLr5WO86p4uPxT-0-c4054543bd0ac9c1974c97649615c01a)
定义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=1739220410-f0R2LzNqpPQgiDZQvCFnhEfAc6SFzgk3-0-38806114d4b16e64a9fe3658c5d6f50d)
排除为特定类型或包生成OpenAPI定义文件时,其Tags形式如下:
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_47_4.jpg?sign=1739220410-cbrCAbBFdj4BxbRmLBK8pRs9wXIEzimv-0-34dbf550d7315b2d56093921765c25a2)
下面介绍openapi-gen的使用示例和生成规则。
1.openapi-gen的使用示例
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_48_1.jpg?sign=1739220410-kJBOpA89pUFwIaXkvJYrYxYirWmLZFFZ-0-69a02e5701974258bfe90a82fbbb47b7)
构建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=1739220410-oKzMpMTWsr8tEaEoBDLeAJUCeNzB5xoL-0-695d04cd0ef85f93daac88ce7a421943)
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=1739220410-PJD3Py3lPNVIgBXaNNP3znyWiwWFD5Jq-0-2edcd60ebf97d98d5d6df8c5e02eab3c)
生成的OpenAPIDefinition如下:
代码路径:pkg/generated/openapi/zz_generated.openapi.go
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_49_1.jpg?sign=1739220410-81qsRCQ5M4RI1ycuSTfUvEr4CBkC7jiq-0-4a46d810488cb3f00064b2f26fa36323)
在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=1739220410-ZSIwKwFjJdzCWkVsNFXqCmU7orivVazB-0-f2707c8edbd1af7d4e59e8ea2fed48b0)
generate-bindata.sh脚本重点执行如下代码:
![](https://epubservercos.yuewen.com/FF83E6/17517091906682706/epubprivate/OEBPS/Images/38914_49_3.jpg?sign=1739220410-JBPU9nBIxH79RciDzn5gNokLb72ngqAa-0-e9b9f78c6d8e62a76608bd8d94fcd8a0)
构建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=1739220410-T04KFlvHDWERBIBFyxRMB7suAyp2bGxT-0-f27fc9417a066b2d14f60f81f5e541fe)