a custom K8s controller example to watch for the creation, update, deletion of user defined custom resources.
- The API group name
nokube.xyz - The Version
v1 - Resource name
customresource
mkdir -p pkg/apis/customresource/v1touch pkg/apis/customresource/register.gopackage has the same name as the custom resource
package customresource
// GroupName for customresource
const GroupName = "nokube.xyz"touch pkg/apis/customresource/v1/types.go
// +<tag_name>[=value]are indicators for code generator
+genclient— generate a client for the package
+genclient:noStatus— when generating the client, there is no status stored for the package
+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object— generate deepcopy logic (required) implementing the runtime.Object interface (for bothCustomResourceandCustomResourceList)
touch pkg/apis/customresource/v1/doc.go// +k8s:deepcopy-gen=package
// +groupName=nokube.xyz
package v1
// +groupName=nokube.xyzinform the generator what the API group name is
// +k8s:deepcopy-gen=packagedeepcopy should be generated for all types in the package
touch pkg/apis/customresource/v1/register.gorun code-gen.sh shell script to do all the heavy lifting via k8s.io/code-generator package
// retrieve the Kubernetes cluster client from outside of the cluster.
func getKubeClient() (kubernetes.Interface, resourceclientset.Interface) {
var kubeConfigPath string
if !inCluster {
// resolve path to `$HOME/.kube/config`
kubeConfigPath = path.Join(userHomeDir(), "/.kube/config")
}
config, err := clientcmd.BuildConfigFromFlags("", kubeConfigPath)
if err != nil {
logger.Fatalf("BuildConfigFromFlags: %v", err)
}
client, err := kubernetes.NewForConfig(config)
if err != nil {
logger.Fatalf("client NewForConfig: %v", err)
}
resourceClient, err := resourceclientset.NewForConfig(config)
if err != nil {
logger.Fatalf("resourceClient NewForConfig: %v", err)
}
logger.Println("Successfully get k8s client")
return client, resourceClient
}// New creates a Controller instance.
func New(client kubernetes.Interface, resourceClient resourceclientset.Interface) *Controller {
informer := resourceinformerV1.NewCustomResourceInformer(
resourceClient,
nameSpace,
0,
cache.Indexers{},
)
// ...
}mkdir crd
# touch crd/customresource.yml
kubectl apply -f crd/customresource.yml
kubectl get customresourcedefinitiongo run main.go
# touch customresource-deploy.yml
kubectl apply -f customresource-deploy.yml
kubectl get CustomResourcekubectl delete CustomResource example-customresource
kubectl delete -f crd/customresource.yml