云原生学习路线导航页(持续更新中)

  • 本文是 Kubernetes operator学习 系列第四篇,主要对 使用 controller-tools 进行 CRD 自动代码生成进行学习
  • Kubernetes operator学习系列 快捷链接
  • Kubernetes operator(一)client-go篇
  • Kubernetes operator(二)CRD篇
  • Kubernetes operator(三)code-generator 篇
  • Kubernetes operator(四)controller-tools 篇

1.controller-tools 简介

1.1.code-generator自动生成代码存在的问题

  • Kubernetes operator(三)code-generator 篇 中,我们提到,code-generator编写CRD控制器有两个问题:
  • 问题一:需要手动编写CRD的yaml,无法自动生成
  • 问题二:types.go文件全部内容都需要我们手写,无法自动生成框架
  • 这部分工作量其实也是挺大的,kubernetes提供了一个工具 controller-tools,可以对这部分内容也进行代码自动生成

1.2.controller-tools是什么

1.2.1.kubernetes-sigs 项目是什么

  • kubernetes-sigs 是一个由 Kubernetes 社区维护的 GitHub 组织,其中包含了许多与 Kubernetes 相关的项目,这些项目通常是为 Kubernetes 生态系统开发的,用于提供各种功能和工具。
  • 一些 kubernetes-sigs 组织中的流行项目包括:
  • kustomize:一种用于 Kubernetes 部署的配置管理工具,可以通过 YAML 声明文件对 Kubernetes 对象进行自定义,并且支持多环境部署(例如 dev、stage、prod)。
  • kubebuilder:一种用于构建 Kubernetes API 的 SDK 工具,可以帮助开发者快速构建和测试 Kubernetes 的自定义控制器。
  • cluster-api:一种 Kubernetes 的 API 扩展,用于管理 Kubernetes 集群的生命周期,包括创建、扩容和删除。它允许开发者使用 Kubernetes 的声明性 API 来管理整个集群的生命周期。
  • kubefed:用于跨 Kubernetes 集群联邦的控制平面。它提供了一种将多个 Kubernetes 集群组合成一个统一的逻辑实体的方法,同时保持每个集群的独立性。
  • controller-tools:用于简化 Kubernetes 控制器的开发,提供了一组工具来生成和更新 Kubernetes API 对象的代码,以及构建自定义控制器所需的代码框架。

1.2.2.controller-tools是什么

  • controller-tools其实是一个由 Kubernetes 社区维护的项目,用于简化 Kubernetes 控制器的开发。其中提供了一组工具来生成和更新 Kubernetes API 对象的代码,以及构建自定义控制器所需的代码框架。
  • controller-tools 的github地址:https://github.com/kubernetes-sigs/controller-tools

1.2.3.controller-tools 包含哪些工具

  • 在controller-tools源码的cmd目录下,可以看到包含三个工具
  • controller-gen:用于生成 zz_xxx.deepcopy.go 文件以及 crd 文件【kubebuilder也是通过这个工具生成crd的相关框架的】
  • type-scaffold:用于生成所需的 types.go 文件
  • helpgen:用于生成针对 Kubernetes API 对象的代码文档,可以包括 API 对象的字段、标签和注释等信息

2.controller-tools 使用过程

2.1.controller-tools 的 安装

  • controller-tools 的 github 地址:https://github.com/kubernetes-sigs/controller-tools.git,克隆代码
git clone https://github.com/kubernetes-sigs/controller-tools.git
  • 将分支切换到 v0.9.0 的tag上
git checkout v0.9.0
  • 编译项目,安装代码生成工具,这里我们只安装需要的2个工具
  • controller-gen工具:生成 deepcopy方法 文件 + crd 文件
  • type-scaffold工具:生成 types.go 文件
cd controller-tools
# linux下安装,执行这一条即可
go install ./cmd/{controller-gen,type-scaffold}

# windows下安装,需要执行两条命令
go install ./cmd/controller-gen
go install ./cmd/type-scaffold
  • 查看安装结果
  • Linux下,在 GOPATH 下的 bin 目录下,会出现我们安装的工具 controller-gen、type-scaffold
  • Windows下,在GOPATH/bin/windows_amd64下,有这两个工具
  • 检查环境变量设置是否成功(Linux)
  • 打开终端,执行 type-scaffold --help,如果报错:
[root@master zgy]# type-scaffold --help
-bash: type-scaffold: 未找到命令
  • 说明环境变量没有设置成功,需要将 gopath/bin 加入PATH
vim ~/.bashrc
# 在~/.bashrc文件的末尾,加上这么一句
export PATH="$PATH:$GOPATH/bin"
# 然后,source一下
source ~/.bashrc
  • 再执行 type-scaffold --help,就成功了
[root@master zgy]# type-scaffold --help
Quickly scaffold out the structure of a type for a Kubernetes kind and associated types.
Produces:

- a root type with appropriate metadata fields
- Spec and Status types
- a list type

Also applies the appropriate comments to generate the code required to conform to runtime.Object.

Usage:
  type-scaffold [flags]

Examples:
        # Generate types for a Kind called Foo with a resource called foos
                type-scaffold --kind Foo

        # Generate types for a Kind called Bar with a resource of foobars
        type-scaffold --kind Bar --resource foobars

Flags:
  -h, --help              help for type-scaffold
      --kind string       The kind of the typescaffold being scaffolded.
      --namespaced        Whether or not the given resource is namespaced. (default true)
      --resource string   The resource of the typescaffold being scaffolded (defaults to a lower-case, plural version of kind).

2.2.type-scaffold 的使用方法

  • type-scaffold 常用命令
type-scaffold --kind <Kind> [flags]
type-scaffold --help
  • --kind:参数用于指定要创建的资源类型(例如 Application)

2.3.controller-gen 的使用方法

  • controller-gen 常用命令
# 生成 CRD 文件,并将生成的文件输出到 config/crds 目录中
controller-gen crd paths=./... output:crd:dir=config/crds
# 生成与对象相关的代码,通常是指生成控制器相关的代码模板
controller-gen object paths=./...

3.controller-tools实战:自动生成代码

  • 本项目已放入girhub代码仓库:https://github.com/graham924/share-code-operator-study

3.1.初始化项目

  • 创建目录
  • 初始化go项目,并get client-go
cd controller-tools-demo
go mod init controller-tools-demo

go get k8s.io/client-go
go get k8s.io/apimachinery

3.2.使用type-scaffold工具生成types.go

  • 需要注意:
  • type-scaffold并不会生成文件,而是生成types.go的内容,打印到控制台,我们需要手动copy到types.go文件中去
  • 不过使用kubebuilder的时候,会帮我们生成types.go文件的
  • 执行 type-scaffold --kind=Application,得到types.go的内容
[root@master controller-tools-demo]# type-scaffold --kind=Application
// ApplicationSpec defines the desired state of Application
type ApplicationSpec struct {
        // INSERT ADDITIONAL SPEC FIELDS -- desired state of cluster
}

// ApplicationStatus defines the observed state of Application.
// It should always be reconstructable from the state of the cluster and/or outside world.
type ApplicationStatus struct {
        // INSERT ADDITIONAL STATUS FIELDS -- observed state of cluster
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// Application is the Schema for the applications API
// +k8s:openapi-gen=true
type Application struct {
        metav1.TypeMeta   `json:",inline"`
        metav1.ObjectMeta `json:"metadata,omitempty"`

        Spec   ApplicationSpec   `json:"spec,omitempty"`
        Status ApplicationStatus `json:"status,omitempty"`
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// ApplicationList contains a list of Application
type ApplicationList struct {
        metav1.TypeMeta `json:",inline"`
        metav1.ListMeta `json:"metadata,omitempty"`
        Items           []Application `json:"items"`
}
  • 在 v1alpha1 目录下创建 types.go 文件,将控制台的内容copy进去,记得导包
package v1alpha1

import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

// ApplicationSpec defines the desired state of Application
type ApplicationSpec struct {
	// INSERT ADDITIONAL SPEC FIELDS -- desired state of cluster
}

// ApplicationStatus defines the observed state of Application.
// It should always be reconstructable from the state of the cluster and/or outside world.
type ApplicationStatus struct {
	// INSERT ADDITIONAL STATUS FIELDS -- observed state of cluster
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// Application is the Schema for the applications API
// +k8s:openapi-gen=true
type Application struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`

	Spec   ApplicationSpec   `json:"spec,omitempty"`
	Status ApplicationStatus `json:"status,omitempty"`
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// ApplicationList contains a list of Application
type ApplicationList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata,omitempty"`
	Items           []Application `json:"items"`
}

3.3.使用controller-gen生成deepcopy和crd文件

3.3.1.controller-gen --help 查看帮助文档

  • 帮助文档给出了很多 examples
[root@master v1alpha1]# controller-gen --help
Generate Kubernetes API extension resources and code.

Usage:
  controller-gen [flags]

Examples:
        # Generate RBAC manifests and crds for all types under apis/,
        # outputting crds to /tmp/crds and everything else to stdout
        controller-gen rbac:roleName=<role name> crd paths=./apis/... output:crd:dir=/tmp/crds output:stdout

        # Generate deepcopy/runtime.Object implementations for a particular file
        controller-gen object paths=./apis/v1beta1/some_types.go

        # Generate OpenAPI v3 schemas for API packages and merge them into existing CRD manifests
        controller-gen schemapatch:manifests=./manifests output:dir=./manifests paths=./pkg/apis/...

        # Run all the generators for a given project
        controller-gen paths=./apis/...

        # Explain the markers for generating CRDs, and their arguments
        controller-gen crd -ww


Flags:
  -h, --detailed-help count   print out more detailed help
                              (up to -hhh for the most detailed output, or -hhhh for json output)
      --help                  print out usage and a summary of options
      --version               show version
  -w, --which-markers count   print out all markers available with the requested generators
                              (up to -www for the most detailed output, or -wwww for json output)


Options


generators

+webhook                                                                                                                                           package  generates (partial) {Mutating,Validating}WebhookConfiguration objects.
+schemapatch[:generateEmbeddedObjectMeta=<bool>],manifests=<string>[,maxDescLen=<int>]                                                             package  patches existing CRDs with new schemata.
+rbac:roleName=<string>                                                                                                                            package  generates ClusterRole objects.
+object[:headerFile=<string>][,year=<string>]                                                                                                      package  generates code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations.
+crd[:allowDangerousTypes=<bool>][,crdVersions=<[]string>][,generateEmbeddedObjectMeta=<bool>][,ignoreUnexportedFields=<bool>][,maxDescLen=<int>]  package  generates CustomResourceDefinition objects.


generic

+paths=<[]string>  package  represents paths and go-style path patterns to use as package roots.


output rules (optionally as output:<generator>:...)

+output:artifacts[:code=<string>],config=<string>  package  outputs artifacts to different locations, depending on whether they're package-associated or not.
+output:dir=<string>                               package  outputs each artifact to the given directory, regardless of if it's package-associated or not.
+output:none                                       package  skips outputting anything.                                             
+output:stdout                                     package  outputs everything to standard-out, with no separation.

3.3.2.使用controller-gen生成deepcopy

  • 先刷新一下包
go mod tidy
  • 执行命令
cd controller-tools-demo
controller-gen object paths=pkg/apis/appcontroller/v1alpha1/types.go
  • 执行后,查看目录文件,发现生成了一个 zz_generated.deepcopy.go 文件
[root@master controller-tools-demo]# tree
.
├── go.mod
├── go.sum
└── pkg
    └── apis
        └── appcontroller
            └── v1alpha1
                ├── types.go
                └── zz_generated.deepcopy.go
  • 查看 zz_generated.deepcopy.go 文件内容
//go:build !ignore_autogenerated
// +build !ignore_autogenerated

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

package v1alpha1

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

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Application) DeepCopyInto(out *Application) {
	*out = *in
	out.TypeMeta = in.TypeMeta
	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
	out.Spec = in.Spec
	out.Status = in.Status
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Application.
func (in *Application) DeepCopy() *Application {
	if in == nil {
		return nil
	}
	out := new(Application)
	in.DeepCopyInto(out)
	return out
}

// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *Application) DeepCopyObject() runtime.Object {
	if c := in.DeepCopy(); c != nil {
		return c
	}
	return nil
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ApplicationList) DeepCopyInto(out *ApplicationList) {
	*out = *in
	out.TypeMeta = in.TypeMeta
	in.ListMeta.DeepCopyInto(&out.ListMeta)
	if in.Items != nil {
		in, out := &in.Items, &out.Items
		*out = make([]Application, len(*in))
		for i := range *in {
			(*in)[i].DeepCopyInto(&(*out)[i])
		}
	}
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationList.
func (in *ApplicationList) DeepCopy() *ApplicationList {
	if in == nil {
		return nil
	}
	out := new(ApplicationList)
	in.DeepCopyInto(out)
	return out
}

// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ApplicationList) DeepCopyObject() runtime.Object {
	if c := in.DeepCopy(); c != nil {
		return c
	}
	return nil
}

3.3.3.使用controller-gen生成crd

  • 先刷新一下包
go mod tidy
  • 执行命令
cd controller-tools-demo
controller-gen crd paths=./... output:crd:dir=config/crd
  • paths=./... 表示将当前目录下的所有子目录都包括在生成过程中
  • output:crd:dir=config/crd 指定了输出目录为 config/crd
  • 执行后,生成目录 config 和 文件 _.yaml
[root@master controller-tools-demo]# tree
.
├── config
│   └── crd
│       └── _.yaml
├── go.mod
├── go.sum
└── pkg
    └── apis
        └── appcontroller
            └── v1alpha1
                ├── types.go
                └── zz_generated.deepcopy.go
  • 文件 _.yaml 没有名字?指定groupName后重新生成 crd 文件
  • 因为我们没有给它指定 groupName,所以生成的yaml文件默认没有名字
  • 我们在 pkg/apis/appcontroller/v1alpha1 下创建一个 doc.go 文件,并在里面写上如下内容
// +groupName=appcontroller.k8s.io
package v1alpha1
  • 然后删除原config后,重新生成crd
cd controller-tools-demo
rm -rf config
controller-gen crd paths=./... output:crd:dir=config/crd
  • 生成完成后,目录如下
  • crd文件名称为:appcontroller.k8s.io_applications.yaml
[root@master controller-tools-demo]# tree
.
├── config
│   └── crd
│       └── appcontroller.k8s.io_applications.yaml
├── go.mod
├── go.sum
└── pkg
    └── apis
        └── appcontroller
            └── v1alpha1
                ├── doc.go
                ├── types.go
                └── zz_generated.deepcopy.go

6 directories, 6 files
  • appcontroller.k8s.io_applications.yaml 内容如下
  • 可以看到,openAPIV3Schema.properties.spec 下面,没有 properties 项,因为我们的ApplicationSpec 为空,内部一个属性都没有。
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  annotations:
    controller-gen.kubebuilder.io/version: (devel)
  creationTimestamp: null
  name: applications.appcontroller.k8s.io
spec:
  group: appcontroller.k8s.io
  names:
    kind: Application
    listKind: ApplicationList
    plural: applications
    singular: application
  scope: Namespaced
  versions:
  - name: v1alpha1
    schema:
      openAPIV3Schema:
        description: Application is the Schema for the applications API
        properties:
          apiVersion:
            description: 'APIVersion defines the versioned schema of this representation
              of an object. Servers should convert recognized schemas to the latest
              internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
            type: string
          kind:
            description: 'Kind is a string value representing the REST resource this
              object represents. Servers may infer this from the endpoint the client
              submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
            type: string
          metadata:
            type: object
          spec:
            description: ApplicationSpec defines the desired state of Application
            type: object
          status:
            description: ApplicationStatus defines the observed state of Application.
              It should always be reconstructable from the state of the cluster and/or
              outside world.
            type: object
        type: object
    served: true
    storage: true

3.4.为ApplicationSpec添加内容,并重新生成crd文件

  • 修改types.go,在 ApplicationSpec 中添加两个字段
type ApplicationSpec struct {
	// INSERT ADDITIONAL SPEC FIELDS -- desired state of cluster
	Name     string `json:"name"`
	Replicas int32  `json:"replicas"`
}
  • 删除原config后,重新生成crd文件
cd controller-tools-demo
rm -rf config
controller-gen crd paths=./... output:crd:dir=config/crd
  • 新的crd文件内容如下:
  • 可以看到,openAPIV3Schema.properties.spec 下面,出现了 properties 项,因为我们为ApplicationSpec 添加了Name、Replicas两个值。
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  annotations:
    controller-gen.kubebuilder.io/version: (devel)
  creationTimestamp: null
  name: applications.appcontroller.k8s.io
spec:
  group: appcontroller.k8s.io
  names:
    kind: Application
    listKind: ApplicationList
    plural: applications
    singular: application
  scope: Namespaced
  versions:
  - name: v1alpha1
    schema:
      openAPIV3Schema:
        description: Application is the Schema for the applications API
        properties:
          apiVersion:
            description: 'APIVersion defines the versioned schema of this representation
              of an object. Servers should convert recognized schemas to the latest
              internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
            type: string
          kind:
            description: 'Kind is a string value representing the REST resource this
              object represents. Servers may infer this from the endpoint the client
              submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
            type: string
          metadata:
            type: object
          spec:
            description: ApplicationSpec defines the desired state of Application
            properties:
              name:
                description: INSERT ADDITIONAL SPEC FIELDS -- desired state of cluster
                type: string
              replicas:
                format: int32
                type: integer
            required:
            - name
            - replicas
            type: object
          status:
            description: ApplicationStatus defines the observed state of Application.
              It should always be reconstructable from the state of the cluster and/or
              outside world.
            type: object
        type: object
    served: true
    storage: true

3.5.手动注册版本v1alpha1的CRD资源

  • 在生成了客户端代码后,我们还需要手动注册版本v1alpha1的CRD资源,才能真正使用这个client,不然在编译时会出现 undefined: v1alpha1.AddToScheme 错误、undefined: v1alpha1.Resource 错误。
  • v1alpha1.AddToScheme、v1alpha1.Resource 这两个是用于 client 注册的
  • 编写 v1alpha1/register.go
package v1alpha1

import (
	"controller-tools-demo/pkg/apis/appcontroller"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
)

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

// Kind takes an unqualified kind and returns back a Group qualified GroupKind
func Kind(kind string) schema.GroupKind {
	return SchemeGroupVersion.WithKind(kind).GroupKind()
}

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

var (
	// SchemeBuilder initializes a scheme builder
	SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
	// AddToScheme is a global function that registers this API group & version to a scheme
	AddToScheme = SchemeBuilder.AddToScheme
)

// Adds the list of known types to Scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&Application{},
		&ApplicationList{},
	)
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}

3.6.在kubernetes集群中应用CRD

3.6.1.kubectl apply crd 资源

  • 上面我们已经使用 controller-gen 自动生成了 CRD 文件,名称为 appcontroller.k8s.io_applications.yaml,再 config/crd 目录下
  • 我们需要使用 kubectl apply 命令创建CR资源
cd controller-tools-demo
kubectl apply -f config/crd/appcontroller.k8s.io_applications.yaml
  • 有可能报错:
The CustomResourceDefinition "applications.appcontroller.k8s.io" is invalid: metadata.annotations[api-approved.kubernetes.io]: Required value: protected groups must have approval annotation "api-approved.kubernetes.io", see https://github.com/kubernetes/enhancements/pull/1111
  • 解决方法
  • 这是kubernetes的保护机制,防止外部随意创建crd,破坏环境
  • 报错中已经给了提示,查看github:https://github.com/kubernetes/enhancements/pull/1111
  • 只需要在crd中,添加一条 annotation,然后再执行 kubectl apply -f 命令就可以了
metadata:
  annotations:
    api-approved.kubernetes.io: "https://github.com/kubernetes/kubernetes/pull/78458"
  • 添加之后,完整的 crd 文件内容如下:
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  annotations:
    controller-gen.kubebuilder.io/version: (devel)
    api-approved.kubernetes.io: "https://github.com/kubernetes/kubernetes/pull/78458"
  creationTimestamp: null
  name: applications.appcontroller.k8s.io
spec:
  group: appcontroller.k8s.io
  names:
    kind: Application
    listKind: ApplicationList
    plural: applications
    singular: application
  scope: Namespaced
  versions:
  - name: v1alpha1
    schema:
      openAPIV3Schema:
        description: Application is the Schema for the applications API
        properties:
          apiVersion:
            description: 'APIVersion defines the versioned schema of this representation
              of an object. Servers should convert recognized schemas to the latest
              internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
            type: string
          kind:
            description: 'Kind is a string value representing the REST resource this
              object represents. Servers may infer this from the endpoint the client
              submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
            type: string
          metadata:
            type: object
          spec:
            description: ApplicationSpec defines the desired state of Application
            properties:
              name:
                description: INSERT ADDITIONAL SPEC FIELDS -- desired state of cluster
                type: string
              replicas:
                format: int32
                type: integer
            required:
            - name
            - replicas
            type: object
          status:
            description: ApplicationStatus defines the observed state of Application.
              It should always be reconstructable from the state of the cluster and/or
              outside world.
            type: object
        type: object
    served: true
    storage: true

3.6.2.编写 crd 资源的 example

  • 在 config 目录下,创建一个example目录,内部可以编写一些 application资源的yaml,用于测试Application资源的创建是否可以成功
  • 在config/example目录下,编写一个test_app.yaml
apiVersion: appcontroller.k8s.io/v1alpha1
kind: Application
metadata:
  name: testapp
  namespace: tcs
spec:
  name: testapp1
  replicas: 2
  • 创建Application资源
cd controller-tools-demo
kubectl apply -f ./config/example/test_app.yaml

3.7.测试Application资源的获取

  • 在项目根目录下,创建一个cmd目录,里面创建一个main.go文件
  • 下面我们演示如何使用 code-generator 为 Application 的 v1alpha1 生成的客户端 AppcontrollerV1alpha1Client
  • 编写main.go
package main

import (
	"context"
	"controller-tools-demo/pkg/apis/appcontroller/v1alpha1"
	"fmt"
	"log"

	"k8s.io/client-go/kubernetes/scheme"

	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/clientcmd"
)

func main() {
	config, err := clientcmd.BuildConfigFromFlags("", clientcmd.RecommendedHomeFile)
	if err != nil {
		log.Fatalln(err)
	}

	config.APIPath = "/apis/"
	config.GroupVersion = &v1alpha1.SchemeGroupVersion
	config.NegotiatedSerializer = scheme.Codecs

	client, err := rest.RESTClientFor(config)
	if err != nil {
		log.Fatalln(err)
	}

	app := v1alpha1.Application{}
	err = client.Get().Namespace("tcs").Resource("applications").Name("testapp").Do(context.TODO()).Into(&app)
	if err != nil {
		log.Fatalln(err)
	}

	newObj := app.DeepCopy()
	newObj.Spec.Name = "testapp2"

	fmt.Println(app.Spec.Name)
	fmt.Println(app.Spec.Replicas)

	fmt.Println(newObj.Spec.Name)
}
  • 输出结果
[root@master controller-tools-demo]# go run cmd/main.go
testapp1
2
testapp2
  • 如果没有在kubernetes集群中 应用 CRD资源,直接执行上面的代码,会报错:找不到这个资源。因此一定要先执行 3.6 的步骤
go run cmd/main.go
2024/01/31 16:01:17 the server could not find the requested resource (get applications.appcontroller.k8s.io test_app)

参考优质博客

  • controller-tool的简单使用
  • kubebuilder文档controller-gen
  • kubebuilder文档generating-crd
  • markers