In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-31 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)05/31 Report--
This article mainly introduces the relevant knowledge of "the method of generating CRD and custom controller". The editor shows you the operation process through the actual case. The operation method is simple, fast and practical. I hope this article "the method of generating CRD and custom controller" can help you solve the problem.
Introduction
We can use code-generator and controller-tools for automatic code generation, through automatic code generation can help us automatically generate CRD resource objects, as well as client-side access to ClientSet, Informer, Lister and other toolkits, then we will learn how to write a custom controller.
CRD definition
First initialize the project:
$mkdir operator-crd & & cd operator-crd$ go mod init operator-crd$ mkdir-p pkg/apis/example.com/v1
Create a new doc.go file under this folder as follows:
/ / + k8s:deepcopy-gen=package// + groupName=example.compackage v1
According to the specification definition of CRD, the group we defined here is example.com and the version is v1. A code-generated tag of deepcopy-gen is added at the top to generate a deep copy method for the types in the entire package.
Then there is the very important structure definition of the resource object. Create a new types.go file, and the types.go content can be generated automatically using type-scaffpld. The specific contents of the file are as follows:
Package v1import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" / / BarSpec defines the desired state of Bartype BarSpec struct {/ / INSERT ADDITIONAL SPEC FIELDS-- desired state of cluster DeploymentName string `json: "deploymentName" `Image string `json: "image" `Replicas * int32 `json: "replicas" `} / / BarStatus defines the observed state of Bar.// It should always be reconstructable from the state of the cluster and/or outside world.type BarStatus struct {/ / INSERT ADDITIONAL STATUS FIELDS-- observed state of cluster} / / the following must be indispensable. Cannot generate lister and informer// + genclient / / + k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object// Bar is the Schema for the bars API// + k8s:openapi-gen=truetype Bar struct {metav1.TypeMeta `json: ", inline" `metav1.ObjectMeta `json: "metadata,omitempty" `Spec BarSpec `json: "spec,omitempty" `Status BarStatus `json: "status without it Omitempty "`} / / + k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object// BarList contains a list of Bartype BarList struct {metav1.TypeMeta `json:", inline "`metav1.ListMeta `json:" metadata,omitempty "`Items [] Bar `json:" items "`}
Then you can refer to the resource object built into the system. You also need to provide two variables, AddToScheme and Resource, for client to register, and create a new register.go file, as shown below:
Package v1import (metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"k8s.io/apimachinery/pkg/runtime"k8s.io/apimachinery/pkg/runtime/schema") / / SchemeGroupVersion registers its own custom resource var SchemeGroupVersion = schema.GroupVersion {Group: "example.com" Version: "v1"} / / Kind takes an unqualified kind and returns back a Group qualified GroupKindfunc Kind (kind string) schema.GroupKind {return SchemeGroupVersion.WithKind (kind). GroupKind ()} / / Resource takes an unqualified resource and returns a Group qualified GroupResourcefunc 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 {/ / add Bar and BarList to scheme scheme.AddKnownTypes (SchemeGroupVersion) & Bar {}, & BarList {},) metav1.AddToGroupVersion (scheme, SchemeGroupVersion) return nil}
Use controller-gen to generate crd:
$controller-gen crd paths=./... Output:crd:dir=crd
Generate the example.com_bars.yaml file as follows:
-apiVersion: apiextensions.k8s.io/v1kind: CustomResourceDefinitionmetadata: annotations: controller-gen.kubebuilder.io/version: (devel) creationTimestamp: null name: bars.example.comspec: group: example.com names: kind: Bar listKind: BarList plural: bars singular: bar scope: Namespaced versions:-name: v1 schema: openAPIV3Schema: description: Bar is the Schema for the bars 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: BarSpec defines the desired state of Bar properties: deploymentName: description: INSERT ADDITIONAL SPEC FIELDS-- desired state of cluster Type: string image: type: string replicas: format: int32 type: integer required:-deploymentName-image-replicas type: object status: description: BarStatus defines the observed state of Bar. It should always be reconstructable from the state of the cluster and/or outside world. Type: object type: object served: true storage: true
The final project structure is as follows:
$tree. ├── crd │ └── example.com_bars.yaml ├── go.mod ├── go.sum └── pkg apis example.com └── v1 ├── doc.go ├── register.go └── types.go5 directories, 6 files generate client related code
Once we have prepared the API resource type of the resource above, we can use the relevant code used by the client that started generating the CRD resource.
Start by creating a script that generates the code, all of which are derived from the examples provided by sample-controller:
$mkdir hack & & cd hack
Create a new tools.go file under this directory and add code-generator dependencies, because go module will not rely on this package for us by default when no code uses code-generator. The contents of the file are as follows:
/ / + build tools// establishes tools.go to rely on code-generator// because when no code uses code-generator, go module will not rely on this package for us by default. Package toolsimport _ "k8s.io/code-generator"
Then create a new update-codegen.sh script to configure the script generated by the code:
#! / usr/bin/env bashset-o errexitset-o nounsetset-o pipefailSCRIPT_ROOT=$ (dirname "${BASH_SOURCE [0]}") /.. CODEGEN_PKG=$ {CODEGEN_PKG:-$ (cd "${SCRIPT_ROOT}") Ls-d-1. / vendor/k8s.io/code-generator 2 > / dev/null | | echo.. / code-generator)} bash "${CODEGEN_PKG}" / generate-groups.sh "deepcopy,client,informer Lister "\ operator-crd/pkg/client operator-crd/pkg/apis example.com:v1\-- output-base" ${SCRIPT_ROOT} "/. /\-- go-header-file" ${SCRIPT_ROOT} "/ hack/boilerplate.go.txt# To use your own boilerplate text append:#-- go-header-file" ${SCRIPT_ROOT} "/ hack/custom-boilerplate.go.txt
There is also a verify-codegen.sh script to verify that the generated code is up to date:
#! / usr/bin/env bashset-o errexitset-o nounsetset-o pipefailSCRIPT_ROOT=$ (dirname "${BASH_SOURCE [0]}") /.. DIFFROOT = "${SCRIPT_ROOT} / pkg" TMP_DIFFROOT= "${SCRIPT_ROOT} / _ tmp/pkg" _ tmp= "${SCRIPT_ROOT} / _ tmp" cleanup () {rm-rf "${_ tmp}"} trap "cleanup" EXIT SIGINTcleanupmkdir-p "${TMP_DIFFROOT}" cp-a "${DIFFROOT}" / * "${TMP_DIFFROOT}"${SCRIPT_ROOT} / hack/update-codegen.sh" echo "diffing ${DIFFROOT} against freshly generated codegen" ret=0diff-Naupr "${DIFFROOT}"${TMP_DIFFROOT}" | | ret=$?cp-a "${TMP_DIFFROOT}" / * "${DIFFROOT}" if [[$ret-eq 0]] then echo "${DIFFROOT} up to date." else echo "${DIFFROOT} is out of date. Please run hack/update-codegen.sh "exit 1fi
There is also a boilerplate.go.txt file that adds quality content to the generated code file, as shown below, which actually adds the following open source protocol declaration to the header of each generated code file:
/ * Copyright The Kubernetes Authors.Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0Unless required by applicable law or agreed to in writing, softwaredistributed under the License is distributed on an "ASIS" BASIS,WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.See the License for the specific language governing permissions andlimitations under the License.*/
Next we can execute the code-generated script, first placing the dependency package in the vendor directory:
$go mod vendor
Then execute the script to generate the code:
$chmod + x. / hack/update-codegen.sh$./hack/update-codegen.sh Generating deepcopy funcsGenerating clientset for example.com:v1 at operator-crd/pkg/client/clientsetGenerating listers for example.com:v1 at operator-crd/pkg/client/listersGenerating informers for example.com:v1 at operator-crd/pkg/client/informers
After the code is generated, the pkg package for the entire project looks like this:
$tree pkg pkg ├── apis │ └── example.com │ └── v1 │ ├── doc.go │ ├── register.go │ ├── types.go │ └── zz_generated.deepcopy.go └── client ├── clientset │ └── versioned │ ├── clientset. Go │ ├── doc.go │ ├── fake │ │ ├── clientset_generated.go │ │ ├── doc.go │ │ └── register.go │ ├── scheme │ │ ├── doc.go │ register.go │ └── typed │ └── example.com │ └── v1 │ ├── bar.go │ ├── doc.go │ ├── example.com_client.go │ ├── fake │ │ ├── doc.go │ │ ├── fake_bar.go │ │ └── fake_example.com_client.go │ └── generated_expansion.go ├── informers │ └── externalversions │ ├── example.com │ │ ├── interface.go │ │ └── v1 │ │ ├── bar.go │ │ └── interface.go │ ├── factory.go │ ├── generic.go │ └── internalinterfaces │ factory_interfaces.go └── listers └── example.com └── v1 ├── bar.go └── expansion_generated.go20 directories 26 files
After careful observation, we can find that there is an extra zz_generated.deepcopy.go file under the pkg/apis/example.com/v1 directory, and three directories, clientset, informers and listers, have been generated under the pkg/client folder. With these automatically generated client-side related operation packages, we can access CRD resources and List and Watch Bar just like using built-in resource objects.
Write a controller
The first step is to get the ClientSet that accesses the resource object and create a new main.go file under the root of the project.
Package mainimport ("k8s.io/client-go/tools/clientcmd"k8s.io/klog/v2" clientset "operator-crd/pkg/client/clientset/versioned"operator-crd/pkg/client/informers/externalversions"time"os"os/signal"syscall") var (onlyOneSignalHandler = make (chan struct {}) shutdownSignals = [] os.Signal {os.Interrupt Syscall.SIGTERM}) / / Register SIGTERM and SIGINT signals / / return a stop channel The channel is closed when the first signal is captured / / if the second signal is captured, the program exits func setupSignalHandler () (stopCh) directly.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.