• kubernetes code-generator使用


    Overview#

    Kubernetes中提供了多种自定义控制器的方式:

    Controller 作为CRD的核心,这里将解释如何使用 code-generator 来创建自定义的控制器,作为文章的案例,将完成一个 Firewalld Port 规则的控制器作为描述,通过 Kubernetes 规则来生成对应节点上的 iptables规则。

    Prerequisites#

    CRD#

    apiVersion: apiextensions.k8s.io/v1
    kind: CustomResourceDefinition
    metadata:
      name: ports.firewalld.fedoraproject.org
    spec:
      group: firewalld.fedoraproject.org
      scope: Namespaced
      names:
        plural: ports
        singular: port
        kind: PortRule
        shortNames: 
        - fp
      versions:
      - name: v1
        served: true
        storage: true
        schema:
          openAPIV3Schema:
            type: object
            properties:
              spec:
                type: object
                properties:
                  name:
                    type: string
                  port:
                    type: integer
                  host:
                    type: string
                  isPermanent:
                    type: boolean
    
    

    code-generator#

    需要预先下载 code-generator 。因为这个工具不是必需要求的。

    注意,下载完成后需要将代码库的的分支更改为你目前使用的版本,版本的选择与client-go类似,如果使用master分支,会与当前的 Kubernetes 集群不兼容。

    git clone https://github.com/kubernetes/code-generator
    cd code-generator; git checkout {version}  # ex. v0.18.0
    

    编写代码模板#

    要想使用 code-generator 生成控制器,必须准备三个文件 doc.go , register.go , types.go

    • doc.go 中声明了这个包全局内,要使用生成器的tag
    • register.go 类似于kubernetes API,是将声明的类型注册到schema中
    • type.go 是需要具体声明对象类型

    code-generator Tag说明#

    在使用 code-generator 时,就需要对 code-generator 的tag进行了解。code-generator 的tag是根据几个固定格式进行定义的,tag是 +k8s: + conversion 的组合,在仓库中 cmd 中的 *-gen* 文件夹就代表了 conversion 的替换位置。

    注:最终准备完成的文件( doc.go , register.go , types.go)应该为:apis/example.com/v1 这种类型的

    需要遵循的是,将这些文件放在 <version> 目录中,例如 v1 。这里 v1, v1alpha1, 根据自己需求定义。

    开始填写文件内容#

    type.go#

    package v1
    
    import (
    	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    )
    
    // +genclient
    // +genclient:noStatus
    // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
    type Port struct {
    	metav1.TypeMeta `json:",inline"`
    	// Standard object metadata.
    	// +optional
    	metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
    
    	// Specification of the desired behavior of the Deployment.
    	// +optional
    	Spec PortSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`
    }
    
    // +k8s:deepcopy-gen=false
    type PortSpec struct {
    	Name        string `json:"name"`
    	Host        string `json:"host"`
    	Port        int    `json:"port"`
    	IsPermanent bool   `json:"isPermanent"`
    }
    
    // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
    type PortList struct {
    	metav1.TypeMeta `json:",inline"`
    	// +optional
    	metav1.ListMeta `json:"metadata,omitempty"`
    
    	Items []Port `json:"items"`
    }
    
    

    doc.go#

    // +k8s:deepcopy-gen=package
    // +k8s:protobuf-gen=package
    // +k8s:openapi-gen=true
    
    // +groupName=firewalld.fedoraproject.org
    
    package v1 // import "k8s.io/api/firewalld/v1"
    

    register.go#

    这里是从 k8s.io/api 里任意一个复制的,例如 k8s.io/api/core/v1/register.go

    package v1
    
    import (
    	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    	"k8s.io/apimachinery/pkg/runtime"
    	"k8s.io/apimachinery/pkg/runtime/schema"
    )
    
    // GroupName is the group name use in this package
    const GroupName = "firewalld.fedoraproject.org"
    
    // SchemeGroupVersion is group version used to register these objects
    var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1"}
    
    // Resource takes an unqualified resource and returns a Group qualified GroupResource
    func Resource(resource string) schema.GroupResource {
    	return SchemeGroupVersion.WithResource(resource).GroupResource()
    }
    
    var (
    	// TODO: move SchemeBuilder with zz_generated.deepcopy.go to k8s.io/api.
    	// localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes.
    	SchemeBuilder      = runtime.NewSchemeBuilder(addKnownTypes)
    	localSchemeBuilder = &SchemeBuilder
    	AddToScheme        = localSchemeBuilder.AddToScheme
    )
    
    // Adds the list of known types to the given scheme.
    func addKnownTypes(scheme *runtime.Scheme) error {
    	scheme.AddKnownTypes(SchemeGroupVersion,
    		&Port{},
    		&PortList{},
    	)
    	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
    	return nil
    }
    

    生成所需文件#

    使用 code-generator 时,实际上就是使用这个库中的脚本 generate-groups.sh ,该脚本又四个参数

    • 第一个参数:使用那些生成器,就是 *.gen,用逗号分割,all表示使用全部
    • 第二个参数:client(client-go中informer, lister等)生成的文件存放到哪里
    • 第三个参数:api(api结构,k8s.io/api/) 生成的文件存放到哪里,可以和定义的文件为一个目录
    • 第四个参数:定义group:version
    • -output-base:输出包存放的根目录
    • -go-header-file:生成文件的头注释信息,这个是必要参数,除非生成失败

    注:对于参数二,三,与-output-base,指定的路径,这里可以使用相对路径也可以使用go.mod中的定义的包名,对于使用相对路径而言,生成的文件中的import也将会为 "../../" 的格式

    一个完整的示例

    ../code-generator/generate-groups.sh all \
    	../code-controller/client \
    	../code-controller/apis  \
    	firewalld:v1 \
    	--output-base ../code-controller/ \
    	--go-header-file ../code-generator/hack/boilerplate.go.txt
    

    Reference

    CRD Programming

  • 相关阅读:
    【经典】请求拦截,相应拦截vue3封装,使用dom封装typescript接口
    【云原生布道系列】第二篇:云原生时代领域解决方案专家的价值
    C# Winform之propertyGrid控件使用详解和分组设置
    java源码系列:HashMap源码验证,在JDK8中新增红黑树详解
    C语言查找幸运数字(ZZULIOJ1056:幸运数字)
    JavaWeb基础10——VUE&Element&整合Javaweb的商品管理系统
    Day10—SQL那些事(特殊场景的查询)
    Mongodb的分页优化及索引使用
    解决使用Charles将页面请求代理到本地devServer后热更新失效的问题
    postgresql 数据库导出和导入
  • 原文地址:https://www.cnblogs.com/Cylon/p/16394839.html