How to Access Kubernetes Custom Resource Definitions (CRDs) Using Client-go?
Introduction
Kubernetes is a powerful container orchestration platform that enables seamless scaling and management of containerized applications. It provides built-in resources such as Pods and Deployments, and also supports custom resource definitions Kubernetes users rely on to define resources tailored to their specific needs.
Benefits of Kubernetes CRDs:
– CRDs allow you to extend Kubernetes’ capabilities by defining resources with customized formats.
– You can manage custom resources using `kubectl`, just like built-in resources.
– Kubernetes automatically handles the scaling of custom resources as needed.
– CRDs integrate seamlessly with Kubernetes API and client tools for programmatic interaction.
One such client tool is client-go, a Go-based library that facilitates interaction with Kubernetes resources programmatically. In this guide, we’ll explore how to access and manage Kubernetes CRDs using client-go. Learn more on What is Kubernetes.
Demonstration Scenario
Imagine your development team relies on Kubernetes for application deployment. When building a new application, you need to verify whether a required database is already available within the cluster. To streamline database management, you create a custom resource that maintains information about databases, such as:
– The list of supported databases.
– The total number of instances.
– Available instances for each database type.
By defining a CRD for databases, you can programmatically retrieve and manage this information using client-go.
Prerequisites
Before proceeding, ensure you have the following:
– A newly deployed Ubuntu 20.04 server on Cantech.
– A Cantech Kubernetes Engine (CKE) cluster (this guide uses version 1.24.4).
– A Go development environment (Go version 1.19 is used in this demo).
– The kubectl
command-line tool installed to interact with Kubernetes.
Accessing the CKE Cluster Using kubectl
Once your CKE cluster is deployed, follow these steps to configure access:
1. Log in to your Cantech customer portal.
2. Navigate to the CKE section and select your cluster.
3. Click Download Configuration to get the Kubernetes config file.
The downloaded file will have a name similar to `cke-example-6b5a-4e5e-a92e-example.yaml`. Rename it to `cke.yaml` and move it to your home directory:
$ cd ~/Downloads $ mv cke-example-6b5a-4e5e-a92e-example.yaml ~/cke.yaml
Next, export the config file as an environment variable so `kubectl
` can access the cluster:
$ cd ~ $ echo $HOME Get the home directory path $ export KUBECONFIG='${HOME}/cke.yaml'
Verify the connection by running:
$ kubectl get node
If successful, the output
should resemble:
NAME STATUS ROLES AGE VERSION k8s-crd-ba11fd0aaa9b Ready <none> 6d20h v1.24.4 k8s-crd-e29c4afea916 Ready <none> 6d20h v1.24.4
Now that you have access to the Kubernetes cluster using kubectl
, let’s proceed with creating a CRD.
Creating a Custom Resource Definition (CRD) Using kubectl
Kubernetes uses YAML configuration files to define resources and instruct the server on how to handle them. A CRD file provides essential information, including:
– apiVersion
: The Kubernetes API version.
– metadata
: Identifies the resource.
– spec
: Specifies whether the resource is namespaced or cluster-wide.
– scope
: Defines the structure and scope of the custom resource.
Refer to the official Kubernetes documentation on creating CRDs for a detailed guide on structuring these YAML files.
By defining a CRD for database management, you gain improved visibility and control over your Kubernetes cluster resources. In the next steps, we’ll explore how to interact with CRDs programmatically using client-go.
Creating a Database Custom Resource Definition (CRD)
To define a new database custom resource in Kubernetes, follow these steps:
Step 1: Create a CRD Definition File
Run the following commands to create a directory and a new CRD YAML file:
$ mkdir k8s-crd-demo $ cd k8s-crd-demo $ nano dbs_crd.k8s.yaml
Step 2: Define the CRD in YAML
Copy and paste the following YAML code into the dbs_crd.k8s.yaml
file and save it:
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
Step 3: Understanding the CRD Definition
- The
apiVersion
is set toapiextensions.k8s.io/v1
, the stable version for defining CRDs in Kubernetes. - The
metadata.name
isdatabases.resource.example.com
, which uniquely identifies the CRD. - The
group
isresource.example.com
, which is required when using the Kubernetes Go client to interact with custom resources. - The
scope
is set toCluster
, meaning the resource can be accessed from anywhere in the cluster. To limit access to a specific namespace, changescope
toNamespace
. - The database custom resource includes fields like
dbName
,description
,total
,available
,dbType
, andtags
. total
andavailable
are integers constrained to values between 1 and 100.dbType
is a string and must be one ofsql
,noSQL
,timeSeries
,messageQueue
, orcaching
.
Step 4: Apply the CRD to the Cluster
Run the following command to create the database
CRD in your Kubernetes cluster:
$ kubectl apply -f dbs_crd.k8s.yaml
This command uses the apply
option to create or update the custom resource, while the -f
option specifies the YAML file to apply. If successful, you should see output similar to:
customresourcedefinition.apiextensions.k8s.io/databases.resource.example.com created
The custom resource definition is ready. Now, add a new database
to it.
Create a file named mysql_resource_object.yaml
with your editor to add a new database
resource to the custom resource definition.
$ nano mysql_resource_object.yaml
Copy the following content into 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
- You set the
apiVersion
for the resource definition with the valueresource.example.com/v1
. - The
apiVersion
must be in the format ofresourceGroup.version
. - The resource type should be
database
and must match the custom resource definition you created earlier. - The name of the
database
item is “mysql” withdbType
as “sql” andavailable
instances are 50.
Run the following command to add the mysql
database item to the database
resource definition.
$ kubectl apply -f mysql_resource_object.yaml
Similar to creating the resource definition, use kubectl with the apply option to add a new resource. You should be able to see similar output like:
database.resource.example.com/mysql created
You now successfully added the “mysql” resource to the database custom resource definition. To check the available databases in the Kubernetes cluster, run the following:
$ kubectl get db
You should be able to see the output
like:
NAME AGE mysql 2m58s
Or you can get detailed information for the database custom resource definition using the following command:
$ kubectl get db -o yaml
The output
should look like this:
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: ""
At this point, you’ve set up the database
custom resource definition and included the MySQL
database.
Let’s move on to see how you can programmatically access the database custom resource definition using Go with the help of Kubernetes go-client tool.
Interact with Kubernetes custom resources using go-client
You must initiate a go module environment and install the needed dependencies to build an app that interacts with the Kubernetes custom resources.
1. Install needed dependencies
Open the terminal and type the following go mod
command to initialize the go module environment.
$ go mod init k8s-resource.com/m
The go module will automatically create a go.mod
file. Add the following dependencies into your app’s go.mod
file to connect with the Kubernetes cluster.
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 )
NOTE:
The version of the go-client library should match the Kubernetes cluster version to prevent incompatible issues. Check out this guide for compatibility matrix details.
Then run go mod tidy
to install these dependencies:
$ go mod tidy
Now that you’ve installed the dependencies, let’s write code to interact with the Kubernetes database
custom resources.
2. Write the code to interact with the Kubernetes custom resources
Let’s write the code that allows the app to:
- Create a new custom resource
- Remove an existing one
- Get all the current custom resources
- Get the custom resource by the resource name
To do it, you use several built-in methods from 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 }
You use the Post
method to create a new resource, Get
to retrieve all the resources or a specific resource by its name, and Delete
to remove an existing resource.
2.1 Implemented Database structs and methods to interact with Kubernetes runtime
- Create
Database
structs
You must create structs forDatabaseSpec
,Database
, andDatabaseList
to interact with the existingdatabase
custom resource definition. Run the following commands to create a newdatabase.go
file.
$ mkdir api $ cd api $ nano database.go
Copy the following codes into the database.go
file:
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"` }
The DatabaseSpec
have fields that match with the current spec database
resource definition are dbName
, description
, total
, available
,dbType
, and tags
. Similarly, the Database
and DatabaseList
structs consist of fields that match with database
resource definition metadata information.
- Creating DeepCopy Methods
To enable deep copying of custom resources, create a deepcopy.go
file and define methods so your application can interact with the Kubernetes runtime.
Create the deepcopy.go File
$ nano deepcopy.go
Copy and paste the following code into deepcopy.go
:
package api import "k8s.io/apimachinery/pkg/runtime" // DeepCopyInto copies the receiver into the provided object. 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, } } // DeepCopyObject creates a new instance of Database and copies the data. func (in *Database) DeepCopyObject() runtime.Object { out := Database{} in.DeepCopyInto(&out) return &out } // DeepCopyObject creates a new instance of DatabaseList and copies the data. 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 }
This code defines the DeepCopyInto
method for the Database
struct and DeepCopyObject
methods for both Database
and DatabaseList
structs, ensuring proper interaction with the Kubernetes runtime.
- Adding Schema Types for Kubernetes Runtime
To register custom resources with the Kubernetes API, create a register.go
file.
Create the register.go
File
$ nano register.go
Copy and paste the following code into 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" GroupVersion = "v1" ) var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: GroupVersion} var ( SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) AddToScheme = SchemeBuilder.AddToScheme ) // addKnownTypes registers custom resource types with the Kubernetes runtime. func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes(SchemeGroupVersion, &Database{}, &DatabaseList{}, ) metav1.AddToGroupVersion(scheme, SchemeGroupVersion) return nil }
This code:
– Defines GroupName
and GroupVersion
to match the custom resource definition (CRD).
– Implements addKnownTypes
to register Database
and DatabaseList
with the Kubernetes runtime.
At this stage, you have successfully implemented the Go structs, functions, and methods required to interact with the Kubernetes runtime. The next section will focus on defining the Kubernetes client and methods to manage the custom resources.
In this section, we will implement a Kubernetes client and define methods for managing custom resources. Specifically, we will:
- Create a new resource
- Retrieve existing resources
- Delete an existing resource
2.2 Implementing Kubernetes Client and Methods
To interact with Kubernetes custom resources, we need to define the configuration for the Kubernetes REST client. Follow the steps below to set up the client.
Step 1: Define the Kubernetes REST Client Configuration
First, create a new file named api.go
to configure the REST client. Run the following commands:
$ cd .. $ mkdir clientset $ cd clientset $ nano api.go
Step 2: Copy the Following Code into 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" ) // ExampleInterface defines the contract for interacting with Database custom resources type ExampleInterface interface { Databases(ctx context.Context) DatabaseInterface } // ExampleClient represents a Kubernetes client for handling custom resources type ExampleClient struct { restClient rest.Interface } // NewForConfig initializes a new Kubernetes client with the given configuration 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 } // Databases returns a client instance for interacting with Database resources func (c *ExampleClient) Databases(ctx context.Context) DatabaseInterface { return &databaseClient{ restClient: c.restClient, ctx: ctx, } }
Explanation of the Code
- The ExampleInterface defines the available database operations.
- The ExampleClient struct wraps the Kubernetes REST client.
- The NewForConfig function initializes the client by setting API paths, group versions, and serialization options.
- The Databases function provides an instance for interacting with Database resources.
Step 3: Add Methods for Managing Custom Resources
Next, you need to define methods for creating, retrieving, and deleting custom resources. For this, create a new file named databases.go
.
$ nano databases.go
Copy the following code into the databases.go
file.
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 }
Next, we define essential methods for interacting with Kubernetes custom resources. These methods include:
- Create: Adds a new resource.
- Get: Retrieves a resource by name.
- List: Fetches all available resources.
- Delete: Removes an existing resource that is no longer needed.
With these methods in place, the Kubernetes client is now fully equipped to interact with custom resources.
2.3 Creating main.go
file to Interact with Kubernetes Resources.
In your next software project, suppose you need to use MongoDB as a database for storing application data. To add a mongodb database into the Database Custom Resource Definition (CRD), follow these steps:
- Copy the
cke.yaml
configuration file into the current directory.
Proceed with setting up main.go to interact with the Kubernetes cluster and manage resources efficiently.
$ cd .. $ cp ~/cke.yaml .
- Create a
main.go
file.
$ cd .. $ nano main.go
- Add the following code to the
main.go
file:
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+"/cke.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) }
Here you call the Create
method to add mongodb
database to the database
custom resource definition.
- Execute the action. Run the
main.go
file.
$ go run main.go
After running this command, you should see a similar output below:
2022/11/18 02:14:55 using configuration from '/home/example/Projects/Personal/cantech/k8s-crd/k8s-crd-full- demo/cke.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}}
You just added the “mongodb” database. Let’s try to get detailed information about the “mongodb” database using the Get
method.
- Get detailed information for “mongodb” database. To do this, replace the
main.go
code with the below code.
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) }
Then run the command:
$ go run main.go
You should see a similar output
as below:
2022/11/18 02:18:20 using configuration from '/home/example/Projects/Personal/cantech/k8s-crd/k8s-crd-full-demo/cke.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}}
If the MySQL database is no longer needed in the Kubernetes cluster, you can remove it by updating the main.go file with the appropriate deletion logic.
- Steps to Remove MySQL Resource:
Open the main.go
file in your project directory. Replace its content with the following code, which ensures the MySQL
database resource is deleted from the cluster. Run the updated code to execute the deletion process. By following these steps, you will successfully remove the MySQL
database resource from the Kubernetes cluster.
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) } }
Then run:
$ go run main.go
- Check if the “mysql” database is actually removed. Now, let’s try to get all the current custom resources to see whether you successfully removed the “mysql” database. Replace the existing code in the
main.go
file with the following content:
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) } }
Let’s run the main.go
file:
$ go run main.go
You should only see the mongodb
database displayed in the output
.
2022/11/18 02:24:08 using configuration from '/home/example/Projects/Personal/cantech/k8s-crd/k8s-crd-full- demo/cke.yaml' mongodb
And that’s how you can interact with Kubernetes custom resources using Kubernetes go-client tool.
Conclusion
This article covered the concept of Kubernetes CRD, its benefits for your projects, and how to use the Kubernetes Go client to interact with CRDs programmatically. Working with Kubernetes can be both exciting and challenging, so be ready to tackle new obstacles along the way.