Published Feb 16, 2021 (Updated Feb 16, 2021) by Girish Talekar • Pinned ⭐
#Operator SDK
#Kubernetes operator
#k8sResourceCloner
When i started writing the k8s operator first time it took me couple of hours to figure out how to write an operator. After doing some reading and searching i found that it is quit simple and easy to write an operator in k8s.
You can find this operator in my github repo
Installation of and configuration of operator-sdk :
$ mkdir -p $GOPATH/src/github.com/operator-framework
$ cd $GOPATH/src/github.com/operator-framework
$ git clone https://github.com/operator-framework/operator-sdk
$ cd operator-sdk
$ git checkout master
$ make dep
$ make install
$ operator-sdk -h
Steps to create the operator :
$ operator-sdk init --domain=example.com --repo=github.com/example-inc/k8sResourceCloner
$ operator-sdk create api --group=cache --version=v1alpha1 --kind=K8sResourceCloner
// K8sResourceClonerSpec defines the desired state of K8sResourceCloner
type K8sResourceClonerSpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
// Important: Run "make" to regenerate code after modifying this file
// Foo is an example field of K8sResourceCloner. Edit K8sResourceCloner_types.go to remove/update
FromNamespace string `json:"fromNamespace"`
ToNamespaces []string `json:"toNamespaces"`
ResourceNames []string `json:"resourceNames"`
}
// K8sResourceClonerStatus defines the observed state of K8sResourceCloner
type K8sResourceClonerStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
// Important: Run "make" to regenerate code after modifying this file
Nodes []string `json:"nodes"`
}
$ make generate
$ make manifests
Implement the controller
// Fetch the K8sResourceCloner instance
k8sResoureCloner := &cachev1alpha1.K8sResourceCloner{}
err := r.Get(ctx, req.NamespacedName, k8sResoureCloner)
if err != nil {
if errors.IsNotFound(err) {
// Request object not found, could have been deleted after reconcile request.
// Owned objects are automatically garbage collected. For additional cleanup logic use finalizers.
// Return and don't requeue
log.Info("K8sResourceCloner resource not found. Ignoring since object must be deleted")
return ctrl.Result{}, nil
}
// Error reading the object - requeue the request.
log.Error(err, "Failed to get K8sResourceCloner")
return ctrl.Result{}, err
}
configMapInstance := &corev1.ConfigMap{}
for j := 0; j < len(k8sResoureCloner.Spec.ResourceNames); j++ {
err = r.Get(ctx, types.NamespacedName{Name: k8sResoureCloner.Spec.ResourceNames[j],
Namespace: k8sResoureCloner.Spec.FromNamespace}, configMapInstance)
if err == nil {
for i := 0; i < len(k8sResoureCloner.Spec.ToNamespaces); i++ {
if err == nil {
newConfigMap := newConfigMap(configMapInstance, k8sResoureCloner.Spec.ToNamespaces[i])
err = r.Create(ctx, newConfigMap)
if err != nil {
return ctrl.Result{}, err
}
}
}
break
}
}
func newConfigMap(cm *corev1.ConfigMap, ns string) *corev1.ConfigMap {
labels := map[string]string{
"app": cm.Name,
}
data := make(map[string]string)
for k, v := range cm.Data {
data[k] = v
}
return &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: cm.Name,
Namespace: ns,
Labels: labels,
},
Data: data,
}
}
func (r *K8sResourceClonerReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&cachev1alpha1.K8sResourceCloner{}).
Owns(&corev1.ConfigMap{}).
Complete(r)
}
Run locally outside the cluster
$ make install run
Update config/samples/cache_v1alpha1_k8sresourcecloner.yaml
fromNamespace : from which the resources need to be cloned
toNamespaces: in which namespace it need to be cloned, multiple namespaces are allowed
resourceNames: the resource name which need to be copied, multiple resource name are allowed
apiVersion: cache.example.org/v1alpha1
kind: K8sResourceCloner
metadata:
name: k8sresourcecloner-sample
spec:
fromNamespace : default
toNamespaces:
- test
- demo
resourceNames:
- test-configMap
Create a K8sResourceCloner CR
kubectl apply -f config/samples/cache_v1alpha1_k8sresourcecloner.yaml
https://sdk.operatorframework.io/docs/building-operators/golang/tutorial/