怎样从 Client-go 访问 Kubernetes 自定义资源定义 (CRD)

介绍

Kubernetes 是一种流行的容器编排平台,负责创建和管理允许软件应用程序横向扩展以处理用户不断增长的工作负载的容器。 除了 Pod 或部署等内置资源外,Kubernetes 还提供自定义资源定义 (CRD) 支持,以便您可以使用所需的确切格式定义资源。 Kubernetes CRD 为您提供以下好处:

  • 您可以使用强大的命令行实用程序 kubectl 具有许多功能,例如创建或更新资源。

  • 自定义资源由 Kubernetes 直接管理,因此它们可以在需要时横向扩展或收缩。

  • Kubernetes 还提供了一个客户端工具,允许您以编程方式与 Kubernetes 资源进行交互。

  • Kubernetes 支持多种流行的客户端工具编程语言,例如 Python、Java、Javascript 或 Go。

本文将向您展示怎样使用 客户去.

演示场景

假设您的软件部门依赖 Kubernetes 来构建用于生产和内部目的的应用程序和工具。 在实现一个新的应用程序时,你想知道现有的 Kubernetes 集群是否已经提供了你需要的数据库来存储新应用程序的数据。 要解决该问题,您可以创建自定义资源来管理 Kubernetes 集群内的数据库。 您可以搜索有关新产品的更多信息 database 资源,例如 Kubernetes 目前支持的数据库,数据库实例总数,或者每个数据库可用的数据库实例。

先决条件

要阅读本文,您需要:

  • 新部署的 Ubuntu 20.04 Vultr云服务器.

  • 一个 Vultr Kubernetes 引擎 (VKE) 集群。 本指南使用版本 1.24.4。

  • 一个安装在本地工作站上的 Go 环境,用于构建使用 Kubernetes client-go 与 database 自定义资源。 该演示使用 Go 版本 1.19。

  • kubectl 安装在本地工作站上的工具,用于从命令行与 Kubernetes 集群交互。

使用 kubectl 访问 VKE 集群

部署 VKE 集群后,从 VKE 概览页面下载 Kubernetes 配置文件。 您需要该配置文件来访问 Vultr Kubernetes 集群。

  1. 导航 VKE部分 Vultr 客户门户网站。

  2. 单击您的 VKE 集群的名称以打开概览页面。

  3. 点击 下载配置 下载配置文件。

    下载的文件的名称将类似于“vke-example-6b5a-4e5e-a92e-example.yaml”。为了方便起见,您应该将其重命名为“vke.yaml”并将其移动到您的主目录。假设您将文件下载到 ~/Downloads 目录,打开终端并输入以下命令:

    $ cd ~/Downloads
    
    $ mv ${your_config_file.yaml} ~/vke.yaml
    
  4. 将配置文件导出为环境变量 kubectl 用于访问 Kubernetes 集群的命令行工具。 运行以下命令:

    $ cd ~
    
    
    
    // Get your current home directory path 
    
    $ echo $HOME 
    
    $ export KUBECONFIG='${path_to_your_home_directory}/vke.yaml'
    
    $ kubectl get node
    
  5. 您应该能够看到 Kubernetes 集群具有的节点,类似于以下内容:

    NAME                   STATUS   ROLES    AGE     VERSION
    
    k8s-crd-ba11fd0aaa9b   Ready    <none>   6d20h   v1.24.4
    
    k8s-crd-e29c4afea916   Ready    <none>   6d20h   v1.24.4
    

现在您可以使用以下方式成功访问 Kubernetes 集群 kubectl,让我们继续下一节,看看怎样创建 database 自定义资源定义使用 kubectl.

使用 kubectl 创建 Kubernetes 自定义资源定义

Kubernetes 使用 yaml 文件作为允许客户端与 Kubernetes 服务器交互的指令。 自定义资源定义文件(CRD文件)在 yaml 格式。 CRD 文件提供了如下信息 apiVersion, metadata, spec, 和 scope 的资源。 查看 用于创建自定义资源定义的 Kubernetes 指南 有关 CRD 文件怎样工作的更多详细信息。

首先,添加一个新的 database 自定义资源定义。 运行以下命令以创建自定义资源定义文件:

$ mkdir k8s-crd-demo

$ cd k8s-crd-demo

$ nano dbs_crd.k8s.yaml

然后,将以下 yaml 定义复​​制到 dbs_crd.k8s.yaml 并保存文件。

apiVersion: apiextensions.k8s.io/v1

kind: CustomResourceDefinition

metadata:

name: databases.resource.example.com

spec:

group: resource.example.com

versions:

    - name: v1

    served: true

    storage: true

    schema:

        openAPIV3Schema:

        type: object

        properties:

            spec:

            type: object

            properties:

                dbName:

                  type: string

                  nullable: false

                description:

                  type: string

                  nullable: false

                total:

                  type: integer

                  default: 10

                  minimum: 1

                  maximum: 100

                available:

                  type: integer

                  default: 10

                  minimum: 1

                  maximum: 100

                dbType:

                  type: string

                  enum:

                  - sql

                  - noSQL

                  - timeSeries

                  - messageQueue

                  - caching

                  nullable: false

                tags:

                  type: string

                  nullable: true

            required: ["dbName", "total", "available", "dbType"]

        required: ["spec"]

scope: Cluster

names:

    plural: databases

    singular: database

    kind: Database

    shortNames:

    - db
  • 你定义了 apiVersion 对于自定义资源 apiextensions.k8s.io/v1,这是 Kubernetes API 扩展的第 1 版。

  • CRD 的名称是 databases.resource.example.com.

  • 资源组的名称是 resource.example.com. 在使用 Kubernetes go-client 工具与 Kubernetes 自定义资源交互时,您需要使用这些名称。

  • scope 默认情况下自定义资源是 Cluster,这意味着您可以从 Kubernetes 集群内的任何地方访问自定义。

  • 您还可以设置 scopeNamespace 限制对特定命名空间内的自定义资源的访问。

database 自定义资源有关于的信息 dbName, description, total, available, dbType, 和 tags. 这 totalavailable 您限制为的字段 integer 数据类型,值范围为 1 到 100 个实例。 这 dbType 一定是 string 并且只能是以下值之一 sql, noSQL, timeSeries, messageQueue, 或者 caching.

要创建这个 database 在 Kubernetes 集群中自定义资源,运行以下命令:

$ kubectl apply -f dbs_crd.k8s.yaml

使用 apply 选项与 kubectl 告诉 Kubernetes 集群创建或更新目标资源。 这 -f 选项表示您正在使用文件来应用该操作。 您应该能够看到类似的输出,例如:

customresourcedefinition.apiextensions.k8s.io/databases.resource.example.com created

现在您已成功创建自定义资源定义。 让我们继续添加一个新的数据库 database 自定义资源定义。

添加一个新的数据库资源项到 database 自定义资源定义。 为此,创建 mysql_resource_object.yaml 与你的编辑:

$ nano mysql_resource_object.yaml

将以下内容复制到 mysql_resource_object.yaml:

apiVersion: "resource.example.com/v1"

kind: Database

metadata:

  name: mysql

spec:

  dbName: mysql

  description: Used for storing relation structured data.

  total: 50

  available: 50

  dbType: sql

  tags: Web Development, Data Engineering, Embedded software
  • 你设置 apiVersion 对于具有值的资源定义 resource.example.com/v1.

  • apiVersion 必须采用以下格式 resourceGroup.version.

  • kind 资源是 Database 并且必须匹配 kind 您之前已经创建的自定义资源定义。

  • 的名称 database 项目是“mysql” dbType 作为“sql”和 available 实例为 50。

运行以下命令添加 mysql 数据库项到 database 资源定义。

$ kubectl apply -f mysql_resource_object.yaml

类似于创建资源定义,使用 kubectlapply 添加新资源的选项。 您应该能够看到类似的输出,例如:

database.resource.example.com/mysql created

您现在已成功将“mysql”资源添加到 database 自定义资源定义。 要检查 Kubernetes 集群中的可用数据库,请运行以下命令:

$ kubectl get db

您应该能够看到如下输出:

NAME    AGE

mysql   2m58s

或者您可以获得有关的详细信息 database 使用以下命令自定义资源定义:

$ kubectl get db -o yaml

输出应如下所示:

apiVersion: v1

items:

  - apiVersion: resource.example.com/v1

kind: Database

metadata:

    annotations:

    kubectl.kubernetes.io/last-applied-configuration: |

        {"apiVersion":"resource.example.com/v1","kind":"Database","metadata":{"annotations":{},"name":"mysql"},"spec":   {"available":50,"dbName":"mysql","dbType":"sql","description":"Used for storing relation structured data.","tags":"Web  Development, Data Engineering, Embedded software","total":50}}

    creationTimestamp: "2022-11-17T17:58:30Z"

    generation: 1

    name: mysql

    resourceVersion: "1419745"

    uid: 40ed6d7e-a372-4f64-8400-20376fd8fdba

spec:

    available: 50

    dbName: mysql

    dbType: sql

    description: Used for storing relation structured data.

    tags: Web Development, Data Engineering, Embedded software

    total: 50

kind: List

metadata:

resourceVersion: ""

在这一步,您成功创建了 database 自定义资源定义并添加了 mysql 数据库。

让我们继续看看怎样以编程方式访问 database 在以下帮助下使用 Go 自定义资源定义 Kubernetes go-client 工具.

使用 go-client 与 Kubernetes 自定义资源交互

您必须启动一个 go 模块环境并安装所需的依赖项以构建与 Kubernetes 自定义资源交互的应用程序。

一、安装需要的依赖

打开终端并输入以下内容 go mod 命令初始化 go 模块环境。

$ go mod init k8s-resource.com/m

go 模块会自动创建一个 go.mod 文件。 将以下依赖项添加到您的应用程序中 go.mod 连接 Kubernetes 集群的文件。

require k8s.io/client-go v0.24.4



require (

    github.com/google/go-cmp v0.5.9 // indirect

    github.com/kr/pretty v0.3.0 // indirect

    github.com/rogpeppe/go-internal v1.8.0 // indirect

    github.com/stretchr/testify v1.7.1 // indirect

    gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect

    sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect

    sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect

    sigs.k8s.io/yaml v1.2.0 // indirect

    )



require (

    k8s.io/api v0.24.4 // indirect

    k8s.io/apimachinery v0.24.4

    )



require (

    github.com/davecgh/go-spew v1.1.1 // indirect

    github.com/go-logr/logr v1.2.3 // indirect

    github.com/gogo/protobuf v1.3.2 // indirect

    github.com/golang/protobuf v1.5.2 // indirect

    github.com/google/gofuzz v1.2.0 // indirect

    github.com/imdario/mergo v0.3.13 // indirect; indirectap

    github.com/json-iterator/go v1.1.12 // indirect

    github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect

    github.com/modern-go/reflect2 v1.0.2 // indirect

    github.com/spf13/pflag v1.0.5 // indirect

    golang.org/x/net v0.2.0 // indirect

    golang.org/x/oauth2 v0.2.0 // indirect

    golang.org/x/sys v0.2.0 // indirect

    golang.org/x/term v0.2.0 // indirect

    golang.org/x/text v0.4.0 // indirect

    golang.org/x/time v0.2.0 // indirect

    google.golang.org/appengine v1.6.7 // indirect

    google.golang.org/protobuf v1.28.1 // indirect

    gopkg.in/inf.v0 v0.9.1 // indirect

    gopkg.in/yaml.v2 v2.4.0 // indirect

    k8s.io/klog/v2 v2.80.1 // indirect

    k8s.io/utils v0.0.0-20221108210102-8e77b1f39fe2 // indirect

    )

笔记: go-client库的版本要和Kubernetes集群版本匹配,防止出现不兼容的问题。 查看 本指南 有关兼容性矩阵的详细信息。

然后运行 go mod tidy 安装这些依赖项:

$ go mod tidy

现在您已经安装了依赖项,让我们编写代码来与 Kubernetes 进行交互 database 自定义资源。

二。 编写与 Kubernetes 自定义资源交互的代码

让我们编写允许应用程序执行以下操作的代码:

  • 创建新的自定义资源

  • 删除现有的

  • 获取当前所有的自定义资源

  • 通过资源名称获取自定义资源

为此,您可以使用 Kubernetes go-client 中的几个内置方法:

type Interface interface {

    GetRateLimiter() flowcontrol.RateLimiter

    Verb(verb string) *Request

    Post() *Request

    Put() *Request

    Patch(pt types.PatchType) *Request

    Get() *Request

    Delete() *Request

    APIVersion() schema.GroupVersion

}

你使用 Post 创建新资源的方法, Get 通过名称检索所有资源或特定资源,以及 Delete 删除现有资源。

二.1. 实现了与 Kubernetes 运行时交互的数据库结构和方法

  1. 创造 Database 结构

    您必须为创建结构 DatabaseSpec, Database, 和 DatabaseList 与现有的互动 database 自定义资源定义。 运行以下命令创建一个新的 database.go 文件。

    $ mkdir api
    
    $ cd api
    
    $ nano database.go
    

    将以下代码复制到 database.go 文件:

    package api
    
    
    
    import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    
    
    
    type DatabaseSpec struct {
    
    DbName      string `json:"dbName"`
    
    Description string `json:"description,omitempty"`
    
    Total       int    `json:"total"`
    
    Available   int    `json:"available"`
    
    DbType      string `json:"dbType"`
    
    Tags        string `json:"tags,omitempty"`
    
    }
    
    
    
    // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
    
    type Database struct {
    
    metav1.TypeMeta   `json:",inline"`
    
    metav1.ObjectMeta `json:"metadata,omitempty"`
    
    
    
    Spec DatabaseSpec `json:"spec"`
    
    }
    
    
    
    // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
    
    type DatabaseList struct {
    
    metav1.TypeMeta `json:",inline"`
    
    metav1.ListMeta `json:"metadata,omitempty"`
    
    
    
    Items []Database `json:"items"`
    
    }
    

    DatabaseSpec 具有与当前规范匹配的字段 database 资源定义是 dbName, description, total, available,dbType, 和 tags. 同样, DatabaseDatabaseList 结构由匹配的字段组成 database 资源定义元数据信息。

  2. 创造 deepcopy 方法。 你创造一个 deepcopy.go 文件来定义方法,以便您的应用程序可以与 Kubernetes 运行时交互。

    $ nano deepcopy.go
    

    将以下代码复制到 deepcopy.go 文件。

    package api
    
    
    
    import "k8s.io/apimachinery/pkg/runtime"
    
    
    
    func (in *Database) DeepCopyInto(out *Database) {
    
    out.TypeMeta = in.TypeMeta
    
    out.ObjectMeta = in.ObjectMeta
    
    out.Spec = DatabaseSpec{
    
        DbName:      in.Spec.DbName,
    
        Description: in.Spec.Description,
    
        Total:       in.Spec.Total,
    
        Available:   in.Spec.Available,
    
        DbType:      in.Spec.DbType,
    
        Tags:        in.Spec.Tags,
    
        }
    
    }
    
    
    
    func (in *Database) DeepCopyObject() runtime.Object {
    
        out := Database{}
    
        in.DeepCopyInto(&out)
    
    
    
        return &out
    
    }
    
    
    
    func (in *DatabaseList) DeepCopyObject() runtime.Object {
    
        out := DatabaseList{}
    
        out.TypeMeta = in.TypeMeta
    
        out.ListMeta = in.ListMeta
    
    
    
        if in.Items != nil {
    
            out.Items = make([]Database, len(in.Items))
    
            for i := range in.Items {
    
                in.Items[i].DeepCopyInto(&out.Items[i])
    
        }
    
        }
    
    
    
    return &out
    
    }
    

    在这里你定义 DeepCopyInto 的方法 Database 结构, DeepCopyObject 的方法 Database 结构和另一个 DeepCopyObject 的方法 DatabaseList 结构,以便 Kubernetes 运行时可以与这些定义的结构进行交互。

  3. 添加模式类型以与 Kubernetes 运行时一起使用。 创建 register.go 用于添加模式类型以与 Kubernetes 运行时一起使用的文件。

    $ nano register.go
    

    将以下代码复制到 register.go 文件:

    package api
    
    
    
    import (
    
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    
        "k8s.io/apimachinery/pkg/runtime"
    
        "k8s.io/apimachinery/pkg/runtime/schema"
    
    )
    
    
    
    const GroupName = "resource.example.com"
    
    const GroupVersion = "v1"
    
    
    
    var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: GroupVersion}
    
    
    
    var (
    
        SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
    
        AddToScheme   = SchemeBuilder.AddToScheme
    
    )
    
    
    
    func addKnownTypes(scheme *runtime.Scheme) error {
    
        scheme.AddKnownTypes(SchemeGroupVersion,
    
        &Database{},
    
        &DatabaseList{},
    
        )
    
    
    
        metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
    
        return nil
    
    }
    

你设置 GroupNameGroupVersion 匹配的组名和组版本 database 自定义资源定义。 然后在里面 addKnownTypes 功能,你添加的类型 DatabaseDatabaseList 到 Kubernetes 运行时。

在此步骤中,您刚刚实现了与 Kubernetes 运行时交互的 Go 结构、函数和方法。 本文的下一部分是关于定义 Kubernetes 客户端和方法以:

  • 创建新资源

  • 获取现有资源

  • 删除一个现有的。

二.2. 实现 Kubernetes 客户端和与 Kubernetes 自定义资源交互的方法

  1. 定义 Kubernetes Rest 客户端的配置。 您需要为 Kubernetes Rest 客户端定义配置。 运行以下命令创建一个新的 api.go 文件。

    $ cd ..
    
    $ mkdir clientset
    
    $ cd clientset
    
    $ nano api.go
    

    将以下代码复制到 api.go:

    package clientset
    
    
    
    import (
    
        "context"
    
    
    
        "k8s-resource.com/m/api"
    
        "k8s.io/apimachinery/pkg/runtime/schema"
    
        "k8s.io/client-go/kubernetes/scheme"
    
        "k8s.io/client-go/rest"
    
    )
    
    
    
    type ExampleInterface interface {
    
    Databases(ctx context.Context) DatabaseInterface
    
    }
    
    
    
    type ExampleClient struct {
    
    restClient rest.Interface
    
    }
    
    
    
    func NewForConfig(c *rest.Config) (*ExampleClient, error) {
    
    config := *c
    
    config.ContentConfig.GroupVersion = &schema.GroupVersion{Group: api.GroupName, Version: api.GroupVersion}
    
    config.APIPath = "/apis"
    
    config.NegotiatedSerializer = scheme.Codecs.WithoutConversion()
    
    config.UserAgent = rest.DefaultKubernetesUserAgent()
    
    
    
    client, err := rest.RESTClientFor(&config)
    
    if err != nil {
    
        return nil, err
    
    }
    
    
    
    return &ExampleClient{restClient: client}, nil
    
    }
    
    
    
    func (c *ExampleClient) Databases(ctx context.Context) DatabaseInterface {
    
    return &databaseClient{
    
        restClient: c.restClient,
    
        ctx:        ctx,
    
    }
    
    }
    

    在这里,您添加 Kubernetes 客户端连接的其余配置 database 自定义资源。

  2. 添加用于创建、删除和获取自定义资源的方法。 您需要创建一个名为 databases.go.

    $ nano databases.go
    

    将以下代码复制到 databases.go 文件。

    package clientset
    
    
    
    import (
    
    "context"
    
    
    
    "k8s-resource.com/m/api"
    
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    
    "k8s.io/client-go/kubernetes/scheme"
    
    "k8s.io/client-go/rest"
    
    )
    
    
    
    type DatabaseInterface interface {
    
    List(opts metav1.ListOptions) (*api.DatabaseList, error)
    
    Get(name string, options metav1.GetOptions) (*api.Database, error)
    
    Create(*api.Database) (*api.Database, error)
    
    Delete(name string, options metav1.DeleteOptions) (*api.Database, error)
    
    }
    
    
    
    type databaseClient struct {
    
    restClient rest.Interface
    
    ctx        context.Context
    
    }
    
    
    
    func (c *databaseClient) List(opts metav1.ListOptions) (*api.DatabaseList, error) {
    
    result := api.DatabaseList{}
    
    err := c.restClient.
    
        Get().
    
        AbsPath("/apis/resource.example.com/v1/databases").
    
        Do(c.ctx).
    
        Into(&result)
    
    
    
    return &result, err
    
    }
    
    
    
    func (c *databaseClient) Get(name string, opts metav1.GetOptions) (*api.Database, error) {
    
    result := api.Database{}
    
    err := c.restClient.
    
        Get().
    
        AbsPath("/apis/resource.example.com/v1/databases").
    
        Name(name).
    
        VersionedParams(&opts, scheme.ParameterCodec).
    
        Do(c.ctx).
    
        Into(&result)
    
    
    
    return &result, err
    
    }
    
    
    
    func (c *databaseClient) Create(database *api.Database) (*api.Database, error) {
    
    result := api.Database{}
    
    err := c.restClient.
    
        Post().
    
        AbsPath("/apis/resource.example.com/v1/databases").
    
        Body(database).
    
        Do(c.ctx).
    
        Into(&result)
    
    
    
    return &result, err
    
    }
    
    
    
    func (c *databaseClient) Delete(name string, opts metav1.DeleteOptions) (*api.Database, error) {
    
    
    
    result := api.Database{}
    
    
    
    err := c.restClient.
    
        Delete().
    
        AbsPath("/apis/resource.example.com/v1/databases").
    
        Name(name).
    
        VersionedParams(&opts, scheme.ParameterCodec).
    
        Do(c.ctx).Into(&result)
    
    return &result, err
    
    }
    

在这里你定义 Create 创建新资源的方法, Get 通过名称获取资源的方法, List 获取所有当前资源,以及 Delete 删除不再需要的现有资源。

现在您已经添加了用于定义 Kubernetes 客户端和与 Kubernetes 自定义资源交互的方法的代码。 让我们继续创建一个 main.go 文件。

二.3. 创建一个 main.go 文件与 Kubernetes 资源进行交互。

假设在您的下一个软件项目中,您需要使用 MongoDB 为您的应用程序存储数据。 将“mongodb”数据库添加到 database 自定义资源定义,您需要执行以下步骤:

  1. 复制 vke.yaml 配置文件到当前目录。

    $ cd ..
    
    $ cp ~/vke.yaml .
    
  2. 创建一个 main.go 文件。

    $ cd ..
    
    $ nano main.go
    
  3. 将以下代码添加到 main.go 文件:

    package main
    
    
    
    import (
    
    "context"
    
    "flag"
    
    "fmt"
    
    "log"
    
    "os"
    
    
    
    "k8s-resource.com/m/api"
    
    client "k8s-resource.com/m/clientset"
    
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    
    "k8s.io/client-go/tools/clientcmd"
    
    
    
    "k8s.io/client-go/kubernetes/scheme"
    
    "k8s.io/client-go/rest"
    
    )
    
    
    
    var kubeconfig string
    
    
    
    func init() {
    
    path, err := os.Getwd()
    
    if err != nil {
    
        log.Println(err)
    
    }
    
    flag.StringVar(&kubeconfig, "kubeconfig", path+"/vke.yaml", "path to Kubernetes config file")
    
    flag.Parse()
    
    }
    
    
    
    func main() {
    
    var config *rest.Config
    
    var err error
    
    
    
    if kubeconfig == "" {
    
        log.Printf("using in-cluster configuration")
    
        config, err = rest.InClusterConfig()
    
    } else {
    
        log.Printf("using configuration from '%s'", kubeconfig)
    
        config, err = clientcmd.BuildConfigFromFlags("", kubeconfig)
    
    }
    
    
    
    if err != nil {
    
        panic(err)
    
    }
    
    
    
    api.AddToScheme(scheme.Scheme)
    
    
    
    clientSet, err := client.NewForConfig(config)
    
    if err != nil {
    
        panic(err)
    
    }
    
    
    
    context := context.TODO()
    
    
    
    newDatabase := new(api.Database) // pa == &Student{"", 0}
    
    newDatabase.Name = "mongodb"
    
    newDatabase.Kind = "Database" // pa == &Student{"Alice", 0}
    
    newDatabase.APIVersion = "resource.example.com/v1"
    
    newDatabase.Spec.DbName = "mongodb"
    
    newDatabase.Spec.Description = "Used storing unstructured data"
    
    newDatabase.Spec.Total = 100
    
    newDatabase.Spec.Available = 50
    
    newDatabase.Spec.DbType = "noSQL"
    
    newDatabase.Spec.Tags = "Web Development, nosql data"
    
    newDatabase.Spec.Available = 70
    
    
    
    projectCreated, err := clientSet.Databases(context).Create(newDatabase)
    
    if err != nil {
    
        panic(err)
    
    }
    
    
    
    fmt.Println(projectCreated)
    
    }
    

    在这里你调用 Create 添加方法 mongodb 数据库到 database 自定义资源定义。

  4. 执行动作。 跑过 main.go 文件。

    $ go run main.go
    

    运行此命令后,您应该会在下面看到类似的输出:

    2022/11/18 02:14:55 using configuration from '/home/example/Projects/Personal/vultr/k8s-crd/k8s-crd-full-    demo/vke.yaml'
    
    &{{ } {mongodb    f8ba273e-fd1f-4b40-b036-cf13b8c72366 1430720 1 2022-11-18 02:14:55 +0700 +07 <nil> <nil>  map[] map[] [] []  [{main Update resource.example.com/v1 2022-11-18 02:14:55 +0700 +07 FieldsV1 {"f:spec":{".":{},"f:available":{},"f:dbName":{},"f:dbType":{},"f:description":{},"f:tags":{},"f:total":{}}} }]} {mongodb Used storing unstructured data 100 70 noSQL Web Development, nosql data}}
    

    您刚刚添加了“mongodb”数据库。 让我们尝试使用以下方法获取有关“mongodb”数据库的详细信息 Get 方法。

  5. 获取“mongodb”数据库的详细信息。 为此,请更换 main.go 使用以下代码进行编码。

    package main
    
    
    
    import (
    
    "context"
    
    "flag"
    
    "fmt"
    
    "log"
    
    "os"
    
    
    
    "k8s-resource.com/m/api"
    
    client "k8s-resource.com/m/clientset"
    
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    
    "k8s.io/client-go/tools/clientcmd"
    
    
    
    "k8s.io/client-go/kubernetes/scheme"
    
    "k8s.io/client-go/rest"
    
    )
    
    
    
    var kubeconfig string
    
    
    
    func init() {
    
    path, err := os.Getwd()
    
    if err != nil {
    
        log.Println(err)
    
    }
    
    flag.StringVar(&kubeconfig, "kubeconfig", path+"/vke.yaml", "path to Kubernetes config file")
    
    flag.Parse()
    
    }
    
    
    
    func main() {
    
    var config *rest.Config
    
    var err error
    
    
    
    if kubeconfig == "" {
    
        log.Printf("using in-cluster configuration")
    
        config, err = rest.InClusterConfig()
    
    } else {
    
        log.Printf("using configuration from '%s'", kubeconfig)
    
        config, err = clientcmd.BuildConfigFromFlags("", kubeconfig)
    
    }
    
    
    
    if err != nil {
    
        panic(err)
    
    }
    
    
    
    api.AddToScheme(scheme.Scheme)
    
    
    
    clientSet, err := client.NewForConfig(config)
    
    if err != nil {
    
        panic(err)
    
    }
    
    
    
    context := context.TODO()
    
    
    
    projectGet, err := clientSet.Databases(context).Get("mongodb", metav1.GetOptions{})
    
    if err != nil {
    
        panic(err)
    
    }
    
    
    
    fmt.Println(projectGet)
    
    
    
    }
    

    然后运行命令:

    $ go run main.go
    

    您应该会看到类似如下的输出:

    2022/11/18 02:18:20 using configuration from '/home/example/Projects/Personal/vultr/k8s-crd/k8s-crd-full-demo/vke.yaml'
    
    &{{ } {mongodb    f8ba273e-fd1f-4b40-b036-cf13b8c72366 1430720 1 2022-11-18 02:14:55 +0700 +07 <nil> <nil> map[] map[] [] []  [{main Update resource.example.com/v1 2022-11-18 02:14:55 +0700 +07 FieldsV1 {"f:spec":{".":{},"f:available":{},"f:dbName":{},"f:dbType":{},"f:description":{},"f:tags":{},"f:total":{}}} }]} {mongodb Used storing unstructured data 100 70 noSQL Web Development, nosql data}}
    
  6. 从 Kubernetes 集群中删除“mysql”数据库。 假设您不再需要 mysql Kubernetes 集群中的数据库。 删除 mysql 来自 Kubernetes 集群的资源,将代码替换为 main.go 使用以下代码:

    package main
    
    
    
    import (
    
    "context"
    
    "flag"
    
    "log"
    
    "os"
    
    
    
    "k8s-resource.com/m/api"
    
    client "k8s-resource.com/m/clientset"
    
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    
    "k8s.io/client-go/tools/clientcmd"
    
    
    
    "k8s.io/client-go/kubernetes/scheme"
    
    "k8s.io/client-go/rest"
    
    )
    
    
    
    var kubeconfig string
    
    
    
    func init() {
    
    path, err := os.Getwd()
    
    if err != nil {
    
        log.Println(err)
    
    }
    
    flag.StringVar(&kubeconfig, "kubeconfig", path+"/vke.yaml", "path to Kubernetes config file")
    
    flag.Parse()
    
    }
    
    
    
    func main() {
    
    var config *rest.Config
    
    var err error
    
    
    
    if kubeconfig == "" {
    
        log.Printf("using in-cluster configuration")
    
        config, err = rest.InClusterConfig()
    
    } else {
    
        log.Printf("using configuration from '%s'", kubeconfig)
    
        config, err = clientcmd.BuildConfigFromFlags("", kubeconfig)
    
    }
    
    
    
    if err != nil {
    
        panic(err)
    
    }
    
    
    
    api.AddToScheme(scheme.Scheme)
    
    
    
    clientSet, err := client.NewForConfig(config)
    
    if err != nil {
    
        panic(err)
    
    }
    
    
    
    context := context.TODO()
    
    
    
    _, err = clientSet.Databases(context).Delete("mysql", metav1.DeleteOptions{})
    
    if err != nil {
    
        panic(err)
    
    }
    
    
    
    }
    

    然后运行:

    $ go run main.go
    
  7. 检查“mysql”数据库是否真的被删除了。 现在,让我们尝试获取当前所有自定义资源,看看是否成功删除了“mysql”数据库。 替换现有的代码 main.go 包含以下内容的文件:

    package main
    
    
    
    import (
    
    "context"
    
    "flag"
    
    "fmt"
    
    "log"
    
    "os"
    
    
    
    "k8s-resource.com/m/api"
    
    client "k8s-resource.com/m/clientset"
    
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    
    "k8s.io/client-go/tools/clientcmd"
    
    
    
    "k8s.io/client-go/kubernetes/scheme"
    
    "k8s.io/client-go/rest"
    
    )
    
    
    
    var kubeconfig string
    
    
    
    func init() {
    
    path, err := os.Getwd()
    
    if err != nil {
    
    log.Println(err)
    
    }
    
    flag.StringVar(&kubeconfig, "kubeconfig", path+"/vke.yaml", "path to Kubernetes config file")
    
    flag.Parse()
    
    }
    
    
    
    func main() {
    
    var config *rest.Config
    
    var err error
    
    
    
    if kubeconfig == "" {
    
    log.Printf("using in-cluster configuration")
    
    config, err = rest.InClusterConfig()
    
    } else {
    
    log.Printf("using configuration from '%s'", kubeconfig)
    
    config, err = clientcmd.BuildConfigFromFlags("", kubeconfig)
    
    }
    
    
    
    if err != nil {
    
    panic(err)
    
    }
    
    
    
    api.AddToScheme(scheme.Scheme)
    
    
    
    clientSet, err := client.NewForConfig(config)
    
    if err != nil {
    
    panic(err)
    
    }
    
    
    
    context := context.TODO()
    
    
    
    projects, err := clientSet.Databases(context).List(metav1.ListOptions{})
    
    if err != nil {
    
    panic(err)
    
    }
    
    
    
    for _, k := range projects.Items {
    
    
    
    fmt.Println(k.Name)
    
    
    
    }
    
    
    
    }
    

    让我们运行 main.go 文件:

    $ go run main.go
    

    你应该只看到 mongodb 输出中显示的数据库。

    2022/11/18 02:24:08 using configuration from '/home/example/Projects/Personal/vultr/k8s-crd/k8s-crd-full-  demo/vke.yaml'
    
    mongodb
    

这就是您怎样使用 Kubernetes go-client 工具与 Kubernetes 自定义资源进行交互。

结论

这篇文章解释了 Kubernetes CRD 是什么,为什么要在当前工作项目中使用 Kubernetes CRD,以及怎样使用 Kubernetes go-client 工具以编程方式与 Kubernetes CRD 交互。 使用 Kubernetes 既有趣又充满挑战,因此请准备好在使用它时面对新的障碍。 如果您想了解有关使用 Kubernetes go-client 的其他用例的更多信息,请参阅:

  • 使用 cdk8s 在 Go 中编写你的 Kubernetes 基础设施

  • 使用 client-go API 在 Go 中创建和管理 Kubernetes 作业

文章标题 名称(可选) 电子邮件(可选) 描述

发送建议

注:本教程在Vultr VPS上测试通过,如需部署请前往Vultr.com