zoukankan      html  css  js  c++  java
  • 混合kubebuilder与code generator编写CRD

    概览

    kubebuilder和k8s.io/code-generator类似,是一个码生成工具,用于为你的CRD生成kubernetes-style API实现。区别在于:

    • Kubebuilder不会生成informers、listers、clientsets,而code-generator会。
    • Kubebuilder会生成Controller、Admission Webhooks,而code-generator不会。
    • Kubebuilder会生成manifests yaml,而code-generator不会。
    • Kubebuilder还带有一些其他便利性设施。

    Resource + Controller = Operator,因此你可以利用Kubebuilder编写你自己的Operator。

    总结:如果你不想做Operator,如果你不会直接or间接生成Pod,只是想存取CRD(把K8S当作数据库使用)。那你可以使用Kubebuilder生成CRD和manifests yaml,再使用code-generator生成informers、listers、clientsets。

    本文讲的就是这个方法。

    第一步:创建项目

    创建一个目录,然后在里面运行 kubebuilder init 命令,初始化一个新项目。示例如下。

    mkdir $GOPATH/src/foo-controller
    cd $GOPATH/src/foo-controller
    # 我们将使用zsy.com域,
    # 所以所有的 API 组将是<group>.zsy.com.
    kubebuilder init --domain zsy.com 
    kubebuilder edit --multigroup=true

    注意:1、确保你已经安装 Kubebuilder,如果你的项目目录不在 $GOPATH 中,你需要运行 go mod init <modulename> 来告诉 kubebuilder 和 Go module 的基本导入路径。
             2、执行kubebuilder edit --multigroup=true命令,之后通过Kubebuilder创建API生成的Resource将放到项目apis路径下,不执行此条命令默认放到api路径下。

    控制台输出类似以下内容:

    apple@appledeMacBook-Pro foo-controller$ kubebuilder init --domain zsy.com
    Writing scaffold for you to edit...
    Get controller runtime:
    $ go get sigs.k8s.io/controller-runtime@v0.5.0
    Update go.mod:
    $ go mod tidy
    Running make:
    $ make
    /usr/local/go/bin/controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."
    go fmt ./...
    go vet ./...
    go build -o bin/manager main.go
    Next: define a resource with:
    $ kubebuilder create api

    会生成以下文件:

    .
    ├── Dockerfile
    ├── Makefile
    ├── PROJECT
    ├── bin
    │   └── manager
    ├── config
    │   ├── certmanager
    │   ├── default
    │   ├── manager
    │   ├── prometheus
    │   ├── rbac
    │   └── webhook
    ├── hack
    │   └── boilerplate.go.txt
    └── main.go

    第二步:生成Resource和manifests

    kubebuilder create api --group webapp --version v1 --kind Guestbook
    Create Resource [y/n]
    y
    Create Controller [y/n]
    n
    

    会生成以下文件go代码和manifests文件:

    .
    ├── apis
    │   └── webapp
    │       └── v1
    │           ├── groupversion_info.go
    │           ├── guestbook_types.go
    │           └── zz_generated.deepcopy.go
    └── config
        ├── crd
        │   ├── kustomization.yaml
        │   ├── kustomizeconfig.yaml
        │   └── patches
        │       ├── cainjection_in_guestbooks.yaml
        │       └── webhook_in_guestbooks.yaml
        ├── rbac
        │   ├── guestbook_editor_role.yaml
        │   ├── guestbook_viewer_role.yaml
        └── samples
            └── webapp_v1_guestbook.yaml

    添加文件apis/webapp/v1/rbac.go,这个文件用生成RBAC manifests:

    // +kubebuilder:rbac:groups=webapp.example.com,resources=guestbooks,verbs=get;list;watch;create;update;patch;delete
    // +kubebuilder:rbac:groups=webapp.example.com,resources=guestbooks/status,verbs=get;update;patch
    
    package v1

    然后生成CRD manifests:

    make manifests

    得到:

    config
    ├── crd
    │   └── bases
    │       └── webapp.example.com_guestbooks.yaml
    └── rbac
        └── role.yaml

    注意:

    如果你修改了guestbook_types.go的结构,你需要执行以下命令来更新代码和manifests:

    make && make manifests

    第三步:使用code-generator

    1)准备脚本

    在hack目录下准备以下文件:

    .
    └── hack
        ├── tools.go
        ├── update-codegen.sh
        └── verify-codegen.sh

    新建hack/tools.go文件:

    // +build tools
    package tools

    新建hack/update-codegen.sh,注意修改几个变量:

    • MODULEgo.mod保持一致
    • API_PKG=apis,和apis目录保持一致
    • OUTPUT_PKG=generated/webapp,生成Resource时指定的group一样
    • GROUP_VERSION=webapp:v1和生成Resource时指定的group version对应
    #!/usr/bin/env bash
    
    set -o errexit
    set -o nounset
    set -o pipefail
    
    # corresponding to go mod init <module>
    MODULE=foo-controller
    # api package
    APIS_PKG=apis
    # generated output package
    OUTPUT_PKG=generated/webapp
    # group-version such as foo:v1alpha1
    GROUP_VERSION=webapp:v1
    
    SCRIPT_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)}
    
    # generate the code with:
    # --output-base    because this script should also be able to run inside the vendor dir of
    #                  k8s.io/kubernetes. The output-base is needed for the generators to output into the vendor dir
    #                  instead of the $GOPATH directly. For normal projects this can be dropped.
    bash "${CODEGEN_PKG}"/generate-groups.sh "client,lister,informer" 
      ${MODULE}/${OUTPUT_PKG} ${MODULE}/${APIS_PKG} 
      ${GROUP_VERSION} 
      --go-header-file "${SCRIPT_ROOT}"/hack/boilerplate.go.txt 
      --output-base "${SCRIPT_ROOT}"
    #  --output-base "${SCRIPT_ROOT}/../../.." 

    新建hack/verify-codegen.sh

    #!/usr/bin/env bash
    
    set -o errexit
    set -o nounset
    set -o pipefail
    
    OUTPUT_PKG=generated/webapp
    MODULE=zsy.com/foo-controller
    
    SCRIPT_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
    
    DIFFROOT="${SCRIPT_ROOT}/${OUTPUT_PKG}"
    TMP_DIFFROOT="${SCRIPT_ROOT}/_tmp/${OUTPUT_PKG}"
    _tmp="${SCRIPT_ROOT}/_tmp"
    
    cleanup() {
      rm -rf "${_tmp}"
    }
    trap "cleanup" EXIT SIGINT
    
    cleanup
    
    mkdir -p "${TMP_DIFFROOT}"
    cp -a "${DIFFROOT}"/* "${TMP_DIFFROOT}"
    
    "${SCRIPT_ROOT}/hack/update-codegen.sh"
    echo "copying generated ${SCRIPT_ROOT}/${MODULE}/${OUTPUT_PKG} to ${DIFFROOT}"
    cp -r "${SCRIPT_ROOT}/${MODULE}/${OUTPUT_PKG}"/* "${DIFFROOT}"
    
    echo "diffing ${DIFFROOT} against freshly generated codegen"
    ret=0
    diff -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 1
    fi

    2)下载code-generator

    先把code-generator下载下来,注意这里的K8S版本号,得和go.mod里的k8s.io/client-go的版本一致:

    K8S_VERSION=v0.18.6
    go get k8s.io/code-generator@$K8S_VERSION
    go mod vendor

    然后给generate-groups.sh添加可执行权限:

    chmod +x vendor/k8s.io/code-generator/generate-groups.sh

    3)更新依赖版本

    因为code-generator用的是v0.18.6,因此要把其他的k8s库也更新到这个版本,修改项目go.mod文件:

    module foo-controller
    
    go 1.13
    
    require (
    	github.com/go-logr/logr v0.1.0
    	github.com/onsi/ginkgo v1.11.0
    	github.com/onsi/gomega v1.8.1
    	k8s.io/apimachinery v0.18.6
    	k8s.io/client-go v0.18.6
    	k8s.io/code-generator v0.18.6
    	sigs.k8s.io/controller-runtime v0.6.0
    )

    执行下面命令更新vendor目录

    go mod vendor

    4)生成代码

    你需要修改guestbook_types.go文件,添加上tag // +genclient

    // +genclient
    // +kubebuilder:object:root=true
    
    // Guestbook is the Schema for the guestbooks API
    type Guestbook struct {

    新建apis/webapp/v1/doc.go,注意// +groupName=webapp.zsy.com

    // +groupName=webapp.zsy.com
    
    package v1

    新建apis/webapp/v1/register.go,code generator生成的代码需要用到它:

    package v1
    
    import (
        "k8s.io/apimachinery/pkg/runtime/schema"
    )
    
    // SchemeGroupVersion is group version used to register these objects.
    var SchemeGroupVersion = GroupVersion
    
    func Resource(resource string) schema.GroupResource {
        return SchemeGroupVersion.WithResource(resource).GroupResource()
    }

    执行hack/update-codegen.sh:

    ./hack/update-codegen.sh

    会得到zsy.com/foo-controller目录:

    foo-controller
    └── generated
        └── webapp
            ├── clientset
            ├── informers
            └── listers

    移动文件:

    • foo-controller/generated直接移出来,放到项目根下面generated

    例子程序

    先apply manifests yaml:

    kubectl apply -f config/crd/bases/webapp.example.com_guestbooks.yaml
    kubectl apply -f config/samples/webapp_v1_guestbook.yaml

    然后执行项目的main.go

    参考:https://segmentfault.com/a/1190000023097945

             https://github.com/chanjarster/kubebuilder-mix-codegen-how-to

             https://chanjarster.github.io/post/k8s/use-code-generator/

             https://cloudnative.to/kubebuilder/cronjob-tutorial/cronjob-tutorial.html

  • 相关阅读:
    Windows下MarialDB使用
    线程同步synchronized和ReentrantLock
    4种事务特性,5种隔离级别,7种传播行为
    Spring bean的作用域
    java经典30笔试题
    finally中的return
    springboot中Controller没有被扫描
    面试如何回答优化数据库
    Windows定时任务没有执行
    .Net应用程序打包部署总结
  • 原文地址:https://www.cnblogs.com/zhangmingcheng/p/15405022.html
Copyright © 2011-2022 走看看