controller-tool的简单使用

博客 动态
0 223
羽尘
羽尘 2022-05-12 11:59:07
悬赏:0 积分 收藏

controller-tool的简单使用

介绍

在上一篇code-generator简单介绍中重点介绍了如何使用code-generator来自动生成代码,通过自动生成的代码可以帮助我们像访问k8s内置资源那样来操作我们的CRD,其实就是帮助我们生成ClientSet、Informer、Lister等工具包。

但是我们需要自己定义types.go文件以及需要自己去编写crd文件。工作量其实也是很大的,那么有没有工具像code-generator那样帮助我们生成代码呢?答案是肯定的,那就是接下来要介绍的controller-tools

controller-tools

controller-tools主要可以帮我们自动生成types.go所需要的内容以及自动帮我们生成crd。

同样首先将其clone到本地:

$ git clone https://github.com/kubernetes-sigs/controller-tools.git

在项目的cmd目录下,我们可以看到有controller-genhelpgentype-scaffold三个工具。

其中type-scaffold可以用来生成我们需要的types.go文件,controller-gen可以生成zz_xxx.deepcopy.go文件以及crd文件。

我们使用go install进行安装:

$ cd controller-gen$ go install ./cmd/{controller-gen,type-scaffold}

安装完成后我们可以去GOPATH下的bin目录下查看。

image

接着我们就可以新建一个项目,来使用controller-tools提供的工具为我们自动生成代码了。

$ mkdir controller-test && cd controller-test$ go mod init controller-test$ mkdir -p pkg/apis/example.com/v1$ tree.├── go.mod└── pkg    └── apis        └── example.com            └── v14 directories, 1 file

接下来我们就可以使用工具来生成我们所需要的代码了,首先我们生成types.go所需要的内容,由于type-scaffold不支持导入文本,所以生成后我们需要复制到types.go文件中:

$ type-scaffold --kind Foo// FooSpec defines the desired state of Footype FooSpec struct {        // INSERT ADDITIONAL SPEC FIELDS -- desired state of cluster}// FooStatus defines the observed state of Foo.// It should always be reconstructable from the state of the cluster and/or outside world.type FooStatus struct {        // INSERT ADDITIONAL STATUS FIELDS -- observed state of cluster}// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object// Foo is the Schema for the foos API// +k8s:openapi-gen=truetype Foo struct {        metav1.TypeMeta   `json:",inline"`        metav1.ObjectMeta `json:"metadata,omitempty"`        Spec   FooSpec   `json:"spec,omitempty"`        Status FooStatus `json:"status,omitempty"`}// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object// FooList contains a list of Footype FooList struct {        metav1.TypeMeta `json:",inline"`        metav1.ListMeta `json:"metadata,omitempty"`        Items           []Foo `json:"items"`}

然后在types.go文件中将import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"添加上就行。

当然自动生成只是一个模版,里面的具体细节还是需要我们自己去填写,比如我们填充FooSpec

资源类型定义好了,那么如何能让client-go识别我们的资源呢,这里就需要其注册进去。我们可以在register.go中定义GV(Group Version),以及通过标签指定groupName。

// register.go// +groupName=example.compackage v1import (	"k8s.io/apimachinery/pkg/runtime"	"k8s.io/apimachinery/pkg/runtime/schema"	"k8s.io/apimachinery/pkg/runtime/serializer")var (	Scheme       = runtime.NewScheme()	GroupVersion = schema.GroupVersion{		Group:   "example.com",		Version: "v1",	}	Codec = serializer.NewCodecFactory(Scheme))

types.go中调用Scheme.AddKnownTypes方法即可:

// types.gopackage v1import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"// FooSpec defines the desired state of Footype FooSpec struct {	// INSERT ADDITIONAL SPEC FIELDS -- desired state of cluster	Name     string `json:"name"`	Replicas int32  `json:"replicas"`}// FooStatus defines the observed state of Foo.// It should always be reconstructable from the state of the cluster and/or outside world.type FooStatus struct {	// INSERT ADDITIONAL STATUS FIELDS -- observed state of cluster}// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object// Foo is the Schema for the foos API// +k8s:openapi-gen=truetype Foo struct {	metav1.TypeMeta   `json:",inline"`	metav1.ObjectMeta `json:"metadata,omitempty"`	Spec   FooSpec   `json:"spec,omitempty"`	Status FooStatus `json:"status,omitempty"`}// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object// FooList contains a list of Footype FooList struct {	metav1.TypeMeta `json:",inline"`	metav1.ListMeta `json:"metadata,omitempty"`	Items           []Foo `json:"items"`}func init() {	Scheme.AddKnownTypes(GroupVersion, &Foo{}, &FooList{})}

接下来就需要生成deepcopy.go文件了:

$ controller-gen object paths=./pkg/apis/example.com/v1/types.go

同样,我们使用controller-gen生成crd:

$ mkdir config$ go mod tidy$ controller-gen crd paths=./... output:crd:dir=config/crd

这时候我们查看项目结构:

.├── config│   └── crd│       └── example.com_foos.yaml├── go.mod├── go.sum└── pkg    └── apis        └── example.com            └── v1                ├── register.go                ├── types.go                └── zz_generated.deepcopy.go6 directories, 6 files

最后我们来进行验证,首先创建一个cr:

apiVersion: example.com/v1kind: Foometadata:  name: crd-testspec:  name: test  replicas: 2

将crd和cr添加到集群后,我们来编写main.go文件来进行验证:

package mainimport (	"context"	v1 "controller-test/pkg/apis/example.com/v1"	"fmt"	"k8s.io/client-go/rest"	"k8s.io/client-go/tools/clientcmd"	"log")func main() {	config, err := clientcmd.BuildConfigFromFlags("", clientcmd.RecommendedHomeFile)	if err != nil {		log.Fatalln(err)	}	// 这边需要使用原始的 RESTClient	config.APIPath = "/apis/"	config.NegotiatedSerializer = v1.Codec	config.GroupVersion = &v1.GroupVersion	client, err := rest.RESTClientFor(config)	if err != nil {		log.Fatalln(err)	}	foo := &v1.Foo{}	err = client.Get().Namespace("default").Resource("foos").Name("crd-test").Do(context.TODO()).Into(foo)	if err != nil {		log.Fatalln(err)	}	newObj := foo.DeepCopy()	newObj.Spec.Name = "test2"	fmt.Println(foo.Spec.Name)	fmt.Println(newObj.Spec.Name)}//=======// 输出结果testtest2
posted @ 2022-05-12 11:11 李大鹅 阅读(24) 评论(0) 编辑 收藏 举报
回帖
    羽尘

    羽尘 (王者 段位)

    2335 积分 (2)粉丝 (11)源码

     

    温馨提示

    亦奇源码

    最新会员