controller-tool的简单使用-《GO开发知识笔记》

admin 2025-11-04 01:01:03 编程 来源:ZONE.CI 全球网 0 阅读模式
  • 介绍
  • controller-tools

    介绍

    在上一篇code-generator简单介绍中重点介绍了如何使用code-generator来自动生成代码,通过自动生成的代码可以帮助我们像访问k8s内置资源那样来操作我们的CRD,其实就是帮助我们生成ClientSet、Informer、Lister等工具包。但是我们需要自己定义types.go文件以及需要自己去编写crd文件。工作量其实也是很大的,那么有没有工具像code-generator那样帮助我们生成代码呢?答案是肯定的,那就是接下来要介绍的controller-tools

    controller-tools

    controller-tools主要可以帮我们自动生成types.go所需要的内容以及自动帮我们生成crd。同样首先将其clone到本地:

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

    在项目的cmd目录下,我们可以看到有controller-gen、helpgen、type-scaffold三个工具。其中type-scaffold可以用来生成我们需要的types.go文件,controller-gen可以生成zz_xxx.deepcopy.go文件以及crd文件。我们使用go install进行安装:

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

    安装完成后我们可以去GOPATH下的bin目录下查看。image.png接着我们就可以新建一个项目,来使用controller-tools提供的工具为我们自动生成代码了。

    1. $ mkdir controller-test && cd controller-test
    2. $ go mod init controller-test
    3. $ mkdir -p pkg/apis/example.com/v1
    4. $ tree
    5. .
    6. ├── go.mod
    7. └── pkg
    8. └── apis
    9. └── example.com
    10. └── v1
    11. 4 directories, 1 file

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

    1. $ type-scaffold --kind Foo
    2. // FooSpec defines the desired state of Foo
    3. type FooSpec struct {
    4. // INSERT ADDITIONAL SPEC FIELDS -- desired state of cluster
    5. }
    6. // FooStatus defines the observed state of Foo.
    7. // It should always be reconstructable from the state of the cluster and/or outside world.
    8. type FooStatus struct {
    9. // INSERT ADDITIONAL STATUS FIELDS -- observed state of cluster
    10. }
    11. // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
    12. // Foo is the Schema for the foos API
    13. // +k8s:openapi-gen=true
    14. type Foo struct {
    15. metav1.TypeMeta `json:",inline"`
    16. metav1.ObjectMeta `json:"metadata,omitempty"`
    17. Spec FooSpec `json:"spec,omitempty"`
    18. Status FooStatus `json:"status,omitempty"`
    19. }
    20. // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
    21. // FooList contains a list of Foo
    22. type FooList struct {
    23. metav1.TypeMeta `json:",inline"`
    24. metav1.ListMeta `json:"metadata,omitempty"`
    25. Items []Foo `json:"items"`
    26. }

    然后在types.go文件中将import metav1 “k8s.io/apimachinery/pkg/apis/meta/v1”添加上就行。当然自动生成只是一个模版,里面的具体细节还是需要我们自己去填写,比如我们填充FooSpec。资源类型定义好了,那么如何能让client-go识别我们的资源呢,这里就需要其注册进去。我们可以在register.go中定义GV(Group Version),以及通过标签指定groupName。

    1. // register.go
    2. // +groupName=example.com
    3. package v1
    4. import (
    5. "k8s.io/apimachinery/pkg/runtime"
    6. "k8s.io/apimachinery/pkg/runtime/schema"
    7. "k8s.io/apimachinery/pkg/runtime/serializer"
    8. )
    9. var (
    10. Scheme = runtime.NewScheme()
    11. GroupVersion = schema.GroupVersion{
    12. Group: "example.com",
    13. Version: "v1",
    14. }
    15. Codec = serializer.NewCodecFactory(Scheme)
    16. )

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

    1. // types.go
    2. package v1
    3. import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    4. // FooSpec defines the desired state of Foo
    5. type FooSpec struct {
    6. // INSERT ADDITIONAL SPEC FIELDS -- desired state of cluster
    7. Name string `json:"name"`
    8. Replicas int32 `json:"replicas"`
    9. }
    10. // FooStatus defines the observed state of Foo.
    11. // It should always be reconstructable from the state of the cluster and/or outside world.
    12. type FooStatus struct {
    13. // INSERT ADDITIONAL STATUS FIELDS -- observed state of cluster
    14. }
    15. // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
    16. // Foo is the Schema for the foos API
    17. // +k8s:openapi-gen=true
    18. type Foo struct {
    19. metav1.TypeMeta `json:",inline"`
    20. metav1.ObjectMeta `json:"metadata,omitempty"`
    21. Spec FooSpec `json:"spec,omitempty"`
    22. Status FooStatus `json:"status,omitempty"`
    23. }
    24. // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
    25. // FooList contains a list of Foo
    26. type FooList struct {
    27. metav1.TypeMeta `json:",inline"`
    28. metav1.ListMeta `json:"metadata,omitempty"`
    29. Items []Foo `json:"items"`
    30. }
    31. func init() {
    32. Scheme.AddKnownTypes(GroupVersion, &Foo{}, &FooList{})
    33. }

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

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

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

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

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

    1. .
    2. ├── config
    3. │ └── crd
    4. │ └── example.com_foos.yaml
    5. ├── go.mod
    6. ├── go.sum
    7. └── pkg
    8. └── apis
    9. └── example.com
    10. └── v1
    11. ├── register.go
    12. ├── types.go
    13. └── zz_generated.deepcopy.go
    14. 6 directories, 6 files

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

    1. apiVersion: example.com/v1
    2. kind: Foo
    3. metadata:
    4. name: crd-test
    5. spec:
    6. name: test
    7. replicas: 2

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

    1. package main
    2. import (
    3. "context"
    4. v1 "controller-test/pkg/apis/example.com/v1"
    5. "fmt"
    6. "k8s.io/client-go/rest"
    7. "k8s.io/client-go/tools/clientcmd"
    8. "log"
    9. )
    10. func main() {
    11. config, err := clientcmd.BuildConfigFromFlags("", clientcmd.RecommendedHomeFile)
    12. if err != nil {
    13. log.Fatalln(err)
    14. }
    15. // 这边需要使用原始的 RESTClient
    16. config.APIPath = "/apis/"
    17. config.NegotiatedSerializer = v1.Codec
    18. config.GroupVersion = &v1.GroupVersion
    19. client, err := rest.RESTClientFor(config)
    20. if err != nil {
    21. log.Fatalln(err)
    22. }
    23. foo := &v1.Foo{}
    24. err = client.Get().Namespace("default").Resource("foos").Name("crd-test").Do(context.TODO()).Into(foo)
    25. if err != nil {
    26. log.Fatalln(err)
    27. }
    28. newObj := foo.DeepCopy()
    29. newObj.Spec.Name = "test2"
    30. fmt.Println(foo.Spec.Name)
    31. fmt.Println(newObj.Spec.Name)
    32. }
    33. //=======
    34. // 输出结果
    35. test
    36. test2
    以太坊cppgolang区别 编程

    以太坊cppgolang区别

    以太坊是一种去中心化的开源平台,它采用智能合约技术,旨在构建和运行不受干扰的分布式应用程序。作为目前最受欢迎的区块链平台之一,以太坊提供了多种编程语言的支持,其
    progolang 编程

    progolang

    Go语言(Golang)是由Google开发的一门静态类型编程语言。作为一名专业的Golang开发者,我深知这门语言的优势和特点。在本文中,我将介绍Golang
    golangn个发送者 编程

    golangn个发送者

    Golang是一种开源的编程语言,由Google团队开发,旨在提高程序的并发性和简化软件开发过程。在Go语言中,有时需要向多个接收者发送信息。本文将介绍如何在G
    golang技能图谱 编程

    golang技能图谱

    从互联网行业的快速发展到人工智能技术的日益成熟,各种编程语言也应运而生。而在这众多的编程语言中,Golang(即Go)作为一门强大且高效的开发语言备受关注。Go
    评论:0   参与:  0