Author: Donald Le
Last Updated: Thu, Dec 1, 2022Kubernetes is a popular container orchestration platform responsible for creating and managing containers that allow software applications to scale out to handle the growing workload of users. Besides built-in resources such as pods or deployments, Kubernetes provides Custom Resource Definition (CRD) support so that you can define your resources with the exact format you need. Kubernetes CRD provides you with the following benefits:
You can use the powerful command line utility kubectl
with a number of functionalities like creating or updating resources.
The custom resources are managed by Kubernetes directly so they can scale out or scale in when needed.
Kubernetes also provides a client tool that allows you to interact with Kubernetes resources programmatically.
Kubernetes supports several popular programming languages for client tools, such as Python, Java, Javascript, or Go.
This article will show you how to access and manipulate Kubernetes CRDS using the client-go.
Let's say your software department relies on Kubernetes to build applications and tools for both production and internal purposes. When implementing a new application, you wonder whether the existing Kubernetes cluster already provided the database you need to store data for the new app. To resolve that problem, you create a custom resource to manage databases inside the Kubernetes cluster. You can search for more information about the new database
resource, such as the currently supported database in Kubernetes, the total number of database instances, or the available database instances for each database.
To follow along with the article, you need:
A newly deployed Ubuntu 20.04 Vultr cloud server.
A Vultr Kubernetes Engine (VKE) cluster. This guide uses version 1.24.4.
A Go environment installed on your local workstation, used to build the tool using Kubernetes client-go to interact with the database
custom resource. This demo uses Go version 1.19.
The kubectl
tool installed on your local workstation, used to interact with the Kubernetes cluster from the command line.
After you deploy the VKE cluster, download the Kubernetes config file from the VKE overview page. You need that config file to access the Vultr Kubernetes cluster.
Navigate to the VKE section of the Vultr customer portal.
Click the name of your VKE cluster to open the overview page.
Click Download Configuration to download the config file.
The downloaded file will have a name like "vke-example-6b5a-4e5e-a92e-example.yaml". You should rename it to "vke.yaml" and move it to your home directory for convenience. Assuming that you downloaded the file to the ~/Downloads
directory, open up your terminal and type the following commands:
$ cd ~/Downloads
$ mv ${your_config_file.yaml} ~/vke.yaml
Export the config file as an environment variable for the kubectl
command line tool to access the Kubernetes cluster. Run the commands below:
$ cd ~
// Get your current home directory path
$ echo $HOME
$ export KUBECONFIG='${path_to_your_home_directory}/vke.yaml'
$ kubectl get node
You should be able to see the nodes that the Kubernetes cluster has, similar to the below:
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 can successfully access the Kubernetes cluster using kubectl
, let's move on to the next section to see how to create the database
custom resource definition using kubectl
.
Kubernetes use yaml
files as instructions to allow clients to interact with the Kubernetes server. The custom resource definition file (CRD file) is in yaml
format. The CRD file provides information such as apiVersion
, metadata
, spec
, and scope
of the resource. Check out Kubernetes guide for creating custom resource definitions for more details about how CRD file works.
First, add a new database
custom resource definition. Run the following commands to create the custom resource definition file:
$ mkdir k8s-crd-demo
$ cd k8s-crd-demo
$ nano dbs_crd.k8s.yaml
Then, copy the following yaml definitions into dbs_crd.k8s.yaml
and save the file.
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
You defined the apiVersion
for the custom resource with apiextensions.k8s.io/v1
, which is version 1 for API extensions of Kubernetes.
The name of the CRD is databases.resource.example.com
.
The name of the resource group is resource.example.com
. You need to use these names when interacting with the Kubernetes custom resources using the Kubernetes go-client tool.
The scope
of the custom resource by default is Cluster
, which means you can access the custom from anywhere inside the Kubernetes cluster.
You can also set the scope
value to Namespace
to restrict access to the custom resource inside a particular namespace.
The database
custom resource has information about dbName
, description
, total
, available
, dbType
, and tags
. The total
and available
fields you restrict to be integer
data types and have values in the range from 1 to 100 instances. The dbType
must be string
and can only be one of the values as sql
, noSQL
, timeSeries
, messageQueue
, or caching
.
To create this database
custom resource in the Kubernetes cluster, run the following command:
$ kubectl apply -f dbs_crd.k8s.yaml
Using the apply
option with kubectl
tells the Kubernetes cluster to create or update the target resource. The -f
option indicates that you are using a file to apply the action. You should be able to see similar output like:
customresourcedefinition.apiextensions.k8s.io/databases.resource.example.com created
Now you successfully created the custom resource definition. Let's move on to add a new database to database
custom resource definition.
Add a new database resource item into the database
custom resource definition. To do it, create mysql_resource_object.yaml
with your editor:
$ 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 value resource.example.com/v1
.
The apiVersion
must be in the format of resourceGroup.version
.
The kind
of resource is Database
and must match the kind
of the custom resource definition you already created earlier.
The name of the database
item is "mysql" with dbType
as "sql" and available
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 step, you successfully create the database
custom resource definition and added 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.
You must initiate a go module environment and install the needed dependencies to build an app that interacts with the Kubernetes custom resources.
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.
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.
Create Database
structs
You must create structs for DatabaseSpec
, Database
, and DatabaseList
to interact with the existing database
custom resource definition. Run the following commands to create a new database.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.
Create deepcopy
methods. You create a deepcopy.go
file to define methods so your app can interact with the Kubernetes runtime.
$ nano deepcopy.go
Copy the following code into the deepcopy.go
file.
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
}
Here you define the DeepCopyInto
method for the Database
struct, the DeepCopyObject
method for the Database
struct, and another DeepCopyObject
method for the DatabaseList
struct so that Kubernetes runtime can interact with these defined structs.
Adding schema types to work with Kubernetes runtime. Create the register.go
file for adding schema types to work with Kubernetes runtime.
$ nano register.go
Copy the following code into register.go
file:
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
}
You set the GroupName
and GroupVersion
that match the group name and group version of the database
custom resource definition. Then inside the addKnownTypes
function, you add the type for Database
and DatabaseList
to Kubernetes runtime.
You have just implemented the Go structs, functions, and methods to interact with Kubernetes runtime at this step. The next part of the article is about defining the Kubernetes client and methods to:
Create a new resource
Get existing resources
Delete an existing one.
Define the configuration for the Kubernetes Rest client. You need to define the configuration for the Kubernetes Rest client. Run the following commands to create a new api.go
file.
$ cd ..
$ mkdir clientset
$ cd clientset
$ nano api.go
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"
)
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,
}
}
Here you add the rest configuration for the Kubernetes client to connect with database
custom resources.
Add methods for creating, deleting, and getting custom resources. You need to 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
}
Here you define the Create
method to create a new resource, the Get
method to get a resource by name, the List
to get all current resources, and the Delete
to remove an existing resource no longer needed.
Now you've added the codes for defining the Kubernetes client and methods to interact with Kubernetes custom resources. Let's move on to create a main.go
file.
main.go
file to interact with the Kubernetes resources.Suppose that in your next software project, you need to use MongoDB to store data for your app. To add the "mongodb" database into the database
custom resource definition, you need to do the below steps:
Copy the vke.yaml
config file into the current directory.
$ cd ..
$ cp ~/vke.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+"/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)
}
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/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}}
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/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}}
Remove "mysql" database from Kubernetes cluster. Let's say you no longer need the mysql
database in the Kubernetes cluster. To remove the mysql
resource from the Kubernetes cluster, replace the code in main.go
with the following code:
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/vultr/k8s-crd/k8s-crd-full- demo/vke.yaml'
mongodb
And that's how you can interact with Kubernetes custom resources using Kubernetes go-client tool.
The article explained what Kubernetes CRD is, why you would want to use Kubernetes CRD in your current working project, and how to use the Kubernetes go-client tool to interact with Kubernetes CRD programmatically. Working with Kubernetes is fun and challenging, so prepare to face new obstacles when working with it. If you want to learn more about other use cases of using Kubernetes go-client, see: