Cómo acceder a la definición de recursos personalizados (CRD) de Kubernetes desde Client-go

Introducción

Kubernetes es una popular plataforma de orquestación de contenedores responsable de crear y administrar contenedores que permiten que las aplicaciones de software se escalen para manejar la creciente carga de trabajo de los usuarios. Además de los recursos integrados, como pods o implementaciones, Kubernetes proporciona compatibilidad con la definición de recursos personalizados (CRD) para que pueda definir sus recursos con el formato exacto que necesita. Kubernetes CRD le proporciona los siguientes beneficios:

  • Puede utilizar la potente utilidad de línea de comandoskubectlcon una serie de funcionalidades como crear o actualizar recursos.

  • Kubernetes administra directamente los recursos personalizados para que puedan escalar horizontal o verticalmente cuando sea necesario.

  • Kubernetes también proporciona una herramienta de cliente que le permite interactuar con los recursos de Kubernetes mediante programación.

  • Kubernetes admite varios lenguajes de programación populares para herramientas de cliente, como Python, Java, Javascript o Go.

Este artículo le mostrará cómo acceder y manipular Kubernetes CRDS usando elcliente-ir.

Escenario de demostración

Supongamos que su departamento de software confía en Kubernetes para crear aplicaciones y herramientas tanto para producción como para fines internos. Al implementar una nueva aplicación, se pregunta si el clúster de Kubernetes existente ya proporcionó la base de datos que necesita para almacenar datos para la nueva aplicación. Para resolver ese problema, cree un recurso personalizado para administrar las bases de datos dentro del clúster de Kubernetes. Puede buscar más información sobre el nuevodatabaserecurso, como la base de datos admitida actualmente en Kubernetes, el número total de instancias de base de datos o las instancias de base de datos disponibles para cada base de datos.

requisitos previos

Para seguir el artículo, necesitas:

  • Un Ubuntu 20.04 recién implementadoServidor en la nube Vultr.

  • AMotor Vultr Kubernetes(VKE) clúster. Esta guía utiliza la versión 1.24.4.

  • Un entorno de Go instalado en su estación de trabajo local, que se utiliza para crear la herramienta con el cliente-go de Kubernetes para interactuar con eldatabaserecurso personalizado. Esta demostración utiliza la versión 1.19 de Go.

  • loskubectlherramienta instalada en su estación de trabajo local, utilizada para interactuar con el clúster de Kubernetes desde la línea de comandos.

Acceda al clúster de VKE mediante kubectl

Después de implementar el clúster de VKE, descargue el archivo de configuración de Kubernetes desde la página de descripción general de VKE. Necesita ese archivo de configuración para acceder al clúster Vultr Kubernetes.

  1. Navegar ala sección VKEdel portal de clientes de Vultr.

  2. Haga clic en el nombre de su clúster de VKE para abrir la página de descripción general.

  3. Hacer clicDescargar configuraciónpara descargar el archivo de configuración.

    El archivo descargado tendrá un nombre como “vke-example-6b5a-4e5e-a92e-example.yaml”. Debe cambiarle el nombre a “vke.yaml” y moverlo a su directorio de inicio para mayor comodidad. Suponiendo que descargó el archivo en el~/Downloadsdirectorio, abra su terminal y escriba los siguientes comandos:

    $ cd ~/Downloads
    
    $ mv ${your_config_file.yaml} ~/vke.yaml
    
  4. Exporte el archivo de configuración como una variable de entorno para elkubectlherramienta de línea de comandos para acceder al clúster de Kubernetes. Ejecute los siguientes comandos:

    $ cd ~
    
    
    
    // Get your current home directory path 
    
    $ echo $HOME 
    
    $ export KUBECONFIG='${path_to_your_home_directory}/vke.yaml'
    
    $ kubectl get node
    
  5. Debería poder ver los nodos que tiene el clúster de Kubernetes, similar al siguiente:

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

Ahora que puede acceder con éxito al clúster de Kubernetes usandokubectlpasemos a la siguiente sección para ver cómo crear eldatabasedefinición de recurso personalizado usandokubectl.

Crear la definición de recursos personalizados de Kubernetes mediante kubectl

Uso de Kubernetesyamlarchivos como instrucciones para permitir que los clientes interactúen con el servidor de Kubernetes. El archivo de definición de recurso personalizado (archivo CRD) está enyamlformato. El archivo CRD proporciona información comoapiVersion,metadata,specyscopedel recurso VerificarGuía de Kubernetes para crear definiciones de recursos personalizadaspara obtener más detalles sobre cómo funciona el archivo CRD.

Primero, agregue un nuevodatabasedefinición de recurso personalizado. Ejecute los siguientes comandos para crear el archivo de definición de recursos personalizado:

$ mkdir k8s-crd-demo

$ cd k8s-crd-demo

$ nano dbs_crd.k8s.yaml

Luego, copie las siguientes definiciones de yaml endbs_crd.k8s.yamly guarde el archivo.

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
  • Tú definiste elapiVersionpara el recurso personalizado conapiextensions.k8s.io/v1que es la versión 1 para las extensiones de API de Kubernetes.

  • El nombre del CRD esdatabases.resource.example.com.

  • El nombre del grupo de recursos esresource.example.com. Debe utilizar estos nombres cuando interactúe con los recursos personalizados de Kubernetes mediante la herramienta Go-Client de Kubernetes.

  • losscopedel recurso personalizado por defecto esClusterlo que significa que puede acceder a la personalización desde cualquier lugar dentro del clúster de Kubernetes.

  • También puede configurar elscopevalor unNamespacepara restringir el acceso al recurso personalizado dentro de un espacio de nombres particular.

losdatabaserecurso personalizado tiene información sobredbName,description,total,available,dbTypeytags. lostotalyavailablecampos que restringe para serintegertipos de datos y tienen valores en el rango de 1 a 100 instancias. losdbTypedebe serstringy solo puede ser uno de los valores comosql,noSQL,timeSeries,messageQueueohcaching.

Para crear estodatabaserecurso personalizado en el clúster de Kubernetes, ejecute el siguiente comando:

$ kubectl apply -f dbs_crd.k8s.yaml

Utilizando elapplyopción conkubectlle dice al clúster de Kubernetes que cree o actualice el recurso de destino. los-fLa opción indica que está utilizando un archivo para aplicar la acción. Debería poder ver resultados similares como:

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

Ahora ha creado con éxito la definición de recurso personalizado. Pasemos a agregar una nueva base de datos adatabasedefinición de recurso personalizado.

Agregar un nuevo elemento de recurso de base de datos en eldatabasedefinición de recurso personalizado. Para hacerlo, creamysql_resource_object.yamlcon su editor:

$ nano mysql_resource_object.yaml

Copie el siguiente contenido enmysql_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
  • Tu configuraste elapiVersionpara la definición de recurso con el valorresource.example.com/v1.

  • losapiVersiondebe estar en el formato deresourceGroup.version.

  • loskindde recurso esDatabasey debe coincidir con elkindde la definición de recurso personalizado que ya creó anteriormente.

  • El nombre dedatabaseel elemento es “mysql” condbTypecomo “sql” yavailableinstancias son 50.

Ejecute el siguiente comando para agregar elmysqlelemento de la base de datos aldatabasedefinición de recurso.

$ kubectl apply -f mysql_resource_object.yaml

Similar a la creación de la definición de recurso, utilicekubectlcon elapplyopción para agregar un nuevo recurso. Debería poder ver resultados similares como:

database.resource.example.com/mysql created

Ahora agregó con éxito el recurso “mysql” aldatabasedefinición de recurso personalizado. Para verificar las bases de datos disponibles en el clúster de Kubernetes, ejecute lo siguiente:

$ kubectl get db

Debería poder ver la salida como:

NAME    AGE

mysql   2m58s

O puede obtener información detallada para eldatabasedefinición de recurso personalizado usando el siguiente comando:

$ kubectl get db -o yaml

La salida debería verse así:

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: ""

En este paso, crea con éxito eldatabasedefinición de recurso personalizado y agregó elmysqlbase de datos.

Pasemos a ver cómo puede acceder programáticamente aldatabasedefinición de recurso personalizado usando Go con la ayuda deHerramienta de cliente de Kubernetes.

Interactuar con los recursos personalizados de Kubernetes usando go-client

Debe iniciar un entorno de módulo go e instalar las dependencias necesarias para crear una aplicación que interactúe con los recursos personalizados de Kubernetes.

I. Instalar las dependencias necesarias

Abra la terminal y escriba lo siguientego modcomando para inicializar el entorno del módulo go.

$ go mod init k8s-resource.com/m

El módulo go creará automáticamente ungo.modexpediente. Agregue las siguientes dependencias en su aplicacióngo.modarchivo para conectarse con el clúster de 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

    )

USARNota: la versión de la biblioteca go-client debe coincidir con la versión del clúster de Kubernetes para evitar problemas de incompatibilidad. Verificaresta guíapara detalles de la matriz de compatibilidad.

Entonces corrego mod tidypara instalar estas dependencias:

$ go mod tidy

Ahora que ha instalado las dependencias, escribamos código para interactuar con Kubernetesdatabasecaracterísticas personalizadas.

II. Escriba el código para interactuar con los recursos personalizados de Kubernetes

Escribamos el código que permite a la aplicación:

  • Crear un nuevo recurso personalizado

  • Eliminar uno existente

  • Obtenga todos los recursos personalizados actuales

  • Obtenga el recurso personalizado por el nombre del recurso

Para hacerlo, utiliza varios métodos integrados de 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

}

usas elPostmétodo para crear un nuevo recurso,Getpara recuperar todos los recursos o un recurso específico por su nombre, yDeletepara eliminar un recurso existente.

II.1. Estructuras y métodos de base de datos implementados para interactuar con el tiempo de ejecución de Kubernetes

  1. CrearDatabaseestructuras

    Debes crear estructuras paraDatabaseSpec,DatabaseyDatabaseListpara interactuar con lo existentedatabasedefinición de recurso personalizado. Ejecute los siguientes comandos para crear un nuevodatabase.gohora de oficina.

    $ mkdir api
    
    $ cd api
    
    $ nano database.go
    

    Copie los siguientes códigos en eldatabase.gohora de oficina:

    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"`
    
    }
    

    losDatabaseSpectener campos que coincidan con la especificación actualdatabasedefinición de recurso sondbName,description,total,available,dbTypeytags. Del mismo modo, elDatabaseyDatabaseListLas estructuras constan de campos que coinciden condatabaseinformación de metadatos de definición de recursos.

  2. Creardeepcopymétodos. creas undeepcopy.gopara definir métodos para que su aplicación pueda interactuar con el tiempo de ejecución de Kubernetes.

    $ nano deepcopy.go
    

    Copie el siguiente código en eldeepcopy.gohora de oficina.

    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
    
    }
    

    Aquí se define elDeepCopyIntométodo para elDatabaseestructura, laDeepCopyObjectmétodo para elDatabaseestructura, y otraDeepCopyObjectmétodo para elDatabaseListstruct para que el tiempo de ejecución de Kubernetes pueda interactuar con estas estructuras definidas.

  3. Agregar tipos de esquema para trabajar con el tiempo de ejecución de Kubernetes. Crear elregister.goarchivo para agregar tipos de esquema para trabajar con el tiempo de ejecución de Kubernetes.

    $ nano register.go
    

    Copie el siguiente código enregister.gohora de oficina:

    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
    
    }
    

Tu configuraste elGroupNameyGroupVersionque coincidan con el nombre del grupo y la versión del grupo deldatabasedefinición de recurso personalizado. Luego dentro deladdKnownTypesfunción, agrega el tipo paraDatabaseyDatabaseListal tiempo de ejecución de Kubernetes.

Acaba de implementar las estructuras, funciones y métodos de Go para interactuar con el tiempo de ejecución de Kubernetes en este paso. La siguiente parte del artículo trata sobre la definición del cliente y los métodos de Kubernetes para:

  • Crear un nuevo recurso

  • Obtener recursos existentes

  • Eliminar uno existente.

II.2. Implementación de clientes y métodos de Kubernetes para interactuar con recursos personalizados de Kubernetes

  1. Defina la configuración para el cliente Rest de Kubernetes. Debe definir la configuración para el cliente de Kubernetes Rest. Ejecute los siguientes comandos para crear un nuevoapi.gohora de oficina.

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

    Copie el siguiente código enapi.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,
    
    }
    
    }
    

    Aquí agrega la configuración restante para que el cliente de Kubernetes se conectedatabasecaracterísticas personalizadas.

  2. Agregue métodos para crear, eliminar y obtener recursos personalizados. Necesitas crear un nuevo archivo llamadodatabases.go.

    $ nano databases.go
    

    Copie el siguiente código en eldatabases.gohora de oficina.

    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
    
    }
    

Aquí se define elCreatemétodo para crear un nuevo recurso, elGetmétodo para obtener un recurso por nombre, elListpara obtener todos los recursos actuales, y elDeletepara eliminar un recurso existente que ya no se necesita.

Ahora ha agregado los códigos para definir el cliente y los métodos de Kubernetes para interactuar con los recursos personalizados de Kubernetes. Pasemos a crear unmain.gohora de oficina.

II.3. Al crear unmain.gopara interactuar con los recursos de Kubernetes.

Suponga que en su próximo proyecto de software necesita usar MongoDB para almacenar datos para su aplicación. Para agregar la base de datos “mongodb” a ladatabasedefinición de recurso personalizado, debe realizar los siguientes pasos:

  1. Copia elvke.yamlarchivo de configuración en el directorio actual.

    $ cd ..
    
    $ cp ~/vke.yaml .
    
  2. Crear unmain.gohora de oficina.

    $ cd ..
    
    $ nano main.go
    
  3. Agregue el siguiente código a lamain.gohora de oficina:

    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)
    
    }
    

    Aquí llamas a laCreatemétodo para agregarmongodbbase de datos a ladatabasedefinición de recurso personalizado.

  4. Ejecutar la acción. ejecutar elmain.gohora de oficina.

    $ go run main.go
    

    Después de ejecutar este comando, debería ver un resultado similar a continuación:

    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}}
    

    Acaba de agregar la base de datos “mongodb”. Intentemos obtener información detallada sobre la base de datos “mongodb” usando elGetmétodo.

  5. Obtenga información detallada para la base de datos “mongodb”. Para hacer esto, reemplace elmain.gocódigo con el siguiente código.

    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)
    
    
    
    }
    

    Luego ejecuta el comando:

    $ go run main.go
    

    Debería ver una salida similar a la siguiente:

    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. Eliminar la base de datos “mysql” del clúster de Kubernetes. Digamos que ya no necesita elmysqlbase de datos en el clúster de Kubernetes. para quitar elmysqlrecurso del clúster de Kubernetes, reemplace el código enmain.gocon el siguiente código:

    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)
    
    }
    
    
    
    }
    

    Entonces corre:

    $ go run main.go
    
  7. Compruebe si la base de datos “mysql” se eliminó realmente. Ahora, intentemos obtener todos los recursos personalizados actuales para ver si eliminó con éxito la base de datos “mysql”. Reemplace el código existente en elmain.goarchivo con el siguiente contenido:

    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)
    
    
    
    }
    
    
    
    }
    

    Ejecutemos elmain.gohora de oficina:

    $ go run main.go
    

    Solo debe ver elmongodbbase de datos que se muestra en la salida.

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

Y así es como puede interactuar con los recursos personalizados de Kubernetes utilizando la herramienta Go-Client de Kubernetes.

Conclusión

El artículo explica qué es Kubernetes CRD, por qué querría usar Kubernetes CRD en su proyecto de trabajo actual y cómo usar la herramienta Go-Client de Kubernetes para interactuar con Kubernetes CRD mediante programación. Trabajar con Kubernetes es divertido y desafiante, así que prepárese para enfrentar nuevos obstáculos cuando trabaje con él. Si desea obtener más información sobre otros casos de uso de Kubernetes go-client, consulte:

  • Escriba su infraestructura de Kubernetes en Go con cdk8s

  • Cree y administre trabajos de Kubernetes en Go con la API client-go

Título del artículo Nombre (opcional) Correo electrónico (opcional) Descripción

Enviar sugerencia

Artículos Relacionados