使用controller-runtime开发简单的controller
kubebuilder和operator-sdk都是在controller-runtime基础上做了一层封装,如果不需要自定义crd资源,只是使用k8s现有的resource做一些自定义的开发,可以直接使用controller-runtime快速开发。这里我们实现一个对namespace打上label就创建对应的service功能。首先先初始化一个manager,manager的作用是用来管理co
·
kubebuilder和operator-sdk都是在controller-runtime基础上做了一层封装,如果不需要自定义crd资源,只是使用k8s现有的resource做一些自定义的开发,可以直接使用controller-runtime快速开发。这里我们实现一个对namespace打上label就创建对应的service功能。
首先先初始化一个manager,manager的作用是用来管理controller
var namespace string
var metricsAddr string
var syncPeriod int64
var enableLeaderElection bool
//
flag.StringVar(&namespace, "namespace", "", "Namespace within which CRD controller is running.")
flag.StringVar(&metricsAddr, "metrics-addr", ":8080", "The address the metric endpoint binds to.")
flag.Int64Var(&syncPeriod, "sync-period", 0, "Sync every sync-period seconds.")
flag.BoolVar(&enableLeaderElection, "enable-leader-election", false,
"Enable leader election for controller lk-ns-controller. Enabling this will ensure there is only one active controller lk-ns-controller.")
flag.Parse()
ctrl.SetLogger(zap.New(func(o *zap.Options) {
o.Development = true
}))
syncPeriodD := time.Duration(int64(time.Second) * syncPeriod)
manager,err := ctrl.NewManager(ctrl.GetConfigOrDie(),ctrl.Options{
Scheme: scheme,
MetricsBindAddress: metricsAddr,
LeaderElection: enableLeaderElection,
LeaderElectionID: "service-controller",
SyncPeriod: &syncPeriodD,
LeaderElectionNamespace: namespace,
Namespace: namespace,
})
if err != nil {
log.Error(err, "unable to start service-controller")
os.Exit(1)
}
然后创建controller并添加到manager中
err = ctrl.NewControllerManagedBy(manager).For(&v1.Namespace{}).WithEventFilter(&controller.ResourceChangePredicate{}).
Complete(&controller.NamespaceReconciler{
Client:manager.GetClient(),
Log: ctrl.Log.WithName("controllers").WithName("service-controller"),
Scheme: manager.GetScheme(),
})
if err !=nil{
log.Error(err,"unable to create service-controller")
os.Exit(1)
}
注意这里的NamespaceReconciler是自定义的结构体,用来继承Reconciler接口,并实现自定义的业务逻辑。
type NamespaceReconciler struct {
client.Client
Log logr.Logger
Scheme *runtime.Scheme
}
func (r *NamespaceReconciler) Reconcile(ctx context.Context,req ctrl.Request) (ctrl.Result, error) {
namespace :=&v1.Namespace{}
err :=r.Get(ctx,req.NamespacedName,namespace)
if err!=nil{
return err
}
label :=make(map[string]string)
label["jvm"]="prometheus"
jvmService := &v1.Service{
ObjectMeta: metaV1.ObjectMeta{
Name:"jvm-prometheus",
Labels: label,
Namespace:req.Name,
},
Spec: v1.ServiceSpec{
Ports: []v1.ServicePort{
v1.ServicePort{
Name: "jvm",
Protocol: "TCP",
Port: 65533,
TargetPort: intstr.IntOrString{IntVal:65533},
},
},
Selector: label,
Type: v1.ServiceTypeClusterIP,
},
}
jvmLabel :=make(map[string]string)
jvmLabel["jvm-enabled"]="true"
if enabled,exist :=namespace.Labels["jvm-enabled"];exist && enabled=="true"{
err :=r.Create(ctx,jvmService)
if err!=nil{
return err
}
fmt.Printf("create service in namespace: %v\n",req.Name)
}
return ctrl.Result{},nil
}
我们在Reconcile方法中实现自己的业务逻辑,如果namespace存在jvm-enabled=true这个label,就创建对应的service。是不是用法和kubebuilder一模一样。
最后我们启动controller所在的manager
log.Info("starting service-controller")
if err :=manager.Start(ctrl.SetupSignalHandler());err!=nil{
log.Error(err,"cloud not start manager")
os.Exit(1)
}
更多推荐
已为社区贡献4条内容
所有评论(0)