分享这篇文章的主要目的,

是如何利用kubernetes来自定义类型,如SparkApplication,从而使用脚本,生成响应的代码的

这些代码是专门为自定义的类型SparkApplication对象服务的

0、最终效果如下:

Kubernetes operator 如何根据自定义类型生成响应的代码的?_第1张图片

1、测试环境说明

VMware + Centos 7

2、我们需要编写的文件,我测试需要3个(可能测试不够充分)

doc.go

register.go

types.go

3、创建Go工程,利用k8s的特性自定义类型

types.go的主要内容,如下(你需要根据自己的实际情况去自定义类型)

我这里仅仅截图了一部分:

Kubernetes operator 如何根据自定义类型生成响应的代码的?_第2张图片

doc.go的内容:

// +k8s:deepcopy-gen=package,register

// Package v1beta1 is the v1beta1 version of the API.
// +groupName=sparkoperator
package v1beta1

register.go的内容:

package v1beta1

import (
   metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
   "k8s.io/apimachinery/pkg/runtime"
   "k8s.io/apimachinery/pkg/runtime/schema"
   "xingej-go/xingej-k8s-spark/SparkOperatorOnK8sForApp/pkg/apis/spark"
)

var (
   SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
   AddToScheme   = SchemeBuilder.AddToScheme
)

// SchemeGroupVersion is the group version used to register these objects.
var SchemeGroupVersion = schema.GroupVersion{Group: spark.GroupName, Version: spark.Version}

func init() {
   SchemeBuilder.Register(addDefaultingFunc)
}

// Resource takes an unqualified resource and returns a Group-qualified GroupResource.
func Resource(resource string) schema.GroupResource {
   return SchemeGroupVersion.WithResource(resource).GroupResource()
}

func addKnownTypes(scheme *runtime.Scheme) error {
   scheme.AddKnownTypes(SchemeGroupVersion,
      &SparkApplication{},
      &SparkApplicationList{},
   )
   metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
   return nil
}

func addDefaultingFunc(scheme *runtime.Scheme) error {
   return RegisterDefaults(scheme)
}

说明,你在编写声明函数addKnownTypes时,会抛异常,不用担心,是因为缺少文件导致的(根本原因应该是你自定义的类型,并没有添加到schema里),

生成代码后,会自动消失的


编写好上面的文件后,就可以利用脚本来生成代码了

4、我自己根据git上参考的实例,编写了一个脚本,如下update-codegen.sh

Kubernetes operator 如何根据自定义类型生成响应的代码的?_第3张图片

具体说明:

    四个参数:

    第一个 参数:all, 是说,要生成所有的模块,如clientset,informers,listers等

    第二个参数:xingej-go/xingej-k8s-spark/spark-operator-on-k8s-for-app/pkg/client 这个是你要生成代码的目录,目录的名称是client, 也有叫generated的

    第三个参数:xingej-go/xingej-k8s-spark/spark-operator-on-k8s-for-app/pkg/apis  这个目录就是你自己创建的,里面至少包括types.go那个目录

    第四个参数:"spark:v1beta1": 这个就是目录,spark是apis下的目录,v1beta1是spark下面的目录

脚本思路:

    就是进入vendor下的code-generator目录,利用里面的generate-groups.sh脚本,生成代码。

其实跟git 上 参考实例中的脚本 思路大体一样的。

另外:

    运行generate-groups.sh后,会在gopath目录的bin目录下,生成5个工具,如client-gen,deepcopy-gen等

就是利用这几个工具,来生成代码的。


5、如果要生成zz_generated.defaults.go文件的话,需要做两件事:

a、在自定义的类型上,多添加一个tag, 如// +k8s:defaulter-gen=true

b、修改generate-groups.sh脚本,添加对应的模块,如下面的形式:

Kubernetes operator 如何根据自定义类型生成响应的代码的?_第4张图片

其实,也是根据上面的if语句,参考写的。

当然,生成之后,zz_generated.defaults.go文件的内容,好像是不符合要求的,如下所示:

// Code generated by defaulter-gen. DO NOT EDIT.

package v1beta1

import (
   runtime "k8s.io/apimachinery/pkg/runtime"
)

// RegisterDefaults adds defaulters functions to the given scheme.
// Public to allow building arbitrary schemes.
// All generated defaulters are covering - they call all nested defaulters.
func RegisterDefaults(scheme *runtime.Scheme) error {
   return nil
}

生成的函数中,什么也没有做。

如果你觉得不能满足要求,也可以在函数RegisterDefaults中,自己添加必要的逻辑

6、遇到的主要问题:

Error: Failed executing generator: some packages had errors:

type k8s.io/apimachinery/pkg/runtime.Object in k8s.deepcopy-gen:interfaces tag of type k8s.io/apimachinery/pkg/runtime.Object is ont an interface, but: ""

问题描述,标签 k8s.io/apimachinery/pkg/runtime.Object 类型有问题,不是一个接口;

就是下面声明的地方

Kubernetes operator 如何根据自定义类型生成响应的代码的?_第5张图片

解决措施:

     是因为路径问题,少添加了一个vendor

      具体原因,也没有搞清楚(也不需要花费太多的时间),因为这是我第三次生成代码,前两次用的环境已经删除了,

添加上venddor就可以了,如下图所示:

Kubernetes operator 如何根据自定义类型生成响应的代码的?_第6张图片,但是,会造成另一个问题,就是生成的文件zz_generated.deepcopy.go 中,导入包会报异常:

Kubernetes operator 如何根据自定义类型生成响应的代码的?_第7张图片


建议:

    工程名称最好全是小写,不然生成的代码中,不能导入对应的包


希望对其他人有所帮助