Operator3-设计一个operator二-owns的使用

网友投稿 296 2022-09-08

Operator3-设计一个operator二-owns的使用

背景:

[zhangpeng@zhangpeng jan]$ kubectl delete deployment jan-sample deployment.apps "jan-sample" deleted [zhangpeng@zhangpeng jan]$ kubectl get deployment No resources found in default namespace.

Deployment Ingress Service关于Owns的使用

Deployment

func (r *JanReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). For(&janv1.Jan{}). Owns(&appsv1.Deployment{}). Complete(r) }

Deployment delete尝试

make run develop-operator项目,并尝试delete deployment jan-sample查看是否重建:

[zhangpeng@zhangpeng develop-operator]$ kubectl get Jan [zhangpeng@zhangpeng develop-operator]$ kubectl get all

[zhangpeng@zhangpeng develop-operator]$ kubectl delete deployment jan-sample [zhangpeng@zhangpeng develop-operator]$ kubectl get deployment

Ingress and Service资源

简单添加一下Owns?

but其他资源是否可以呢?是不是也偷懒一下添加Owns?

func (r *JanReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). For(&janv1.Jan{}). Owns(&appsv1.Deployment{}). Owns(&corev1.Service{}). Owns(&v1.Ingress{}). Complete(r) }

拆分改造代码

/* Copyright 2022 zhang peng. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package jan import ( "context" "encoding/json" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" v1 "k8s.io/api/networking/v1" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "reflect" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/reconcile" janv1 "develop-operator/apis/jan/v1" ) // JanReconciler reconciles a Jan object type JanReconciler struct { client.Client Scheme *runtime.Scheme } //+kubebuilder:rbac:groups=mar.zhangpeng.com,resources=jan,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups=mar.zhangpeng.com,resources=jan/status,verbs=get;update;patch //+kubebuilder:rbac:groups=mar.zhangpeng.com,resources=jan/finalizers,verbs=update //+kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups=apps,resources=deployments/status,verbs=get;update;patch //+kubebuilder:rbac:groups=core,resources=services,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups=networking,resources=ingresses,verbs=get;list;watch;create;update;patch;delete // Reconcile is part of the main kubernetes reconciliation loop which aims to // move the current state of the cluster closer to the desired state. // TODO(user): Modify the Reconcile function to compare the state specified by // the Jan object against the actual cluster state, and then // perform operations to make the cluster state reflect the state specified by // the user. // // For more details, check Reconcile and its Result here: // - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.11.2/pkg/reconcile func (r *JanReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { defer utilruntime.HandleCrash() _ = log.FromContext(ctx) instance := &janv1.Jan{} err := r.Client.Get(context.TODO(), req.NamespacedName, instance) 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 return reconcile.Result{}, nil } // Error reading the object - requeue the request. return reconcile.Result{}, err } if instance.DeletionTimestamp != nil { return reconcile.Result{}, err } // 如果不存在,则创建关联资源 // 如果存在,判断是否需要更新 // 如果需要更新,则直接更新 // 如果不需要更新,则正常返回 deploy := &appsv1.Deployment{} if err := r.Client.Get(context.TODO(), req.NamespacedName, deploy); err != nil && errors.IsNotFound(err) { // 创建关联资源 // 1. 创建 Deploy deploy := NewJan(instance) if err := r.Client.Create(context.TODO(), deploy); err != nil { return reconcile.Result{}, err } // 4. 关联 Annotations data, _ := json.Marshal(instance.Spec) if instance.Annotations != nil { instance.Annotations["spec"] = string(data) } else { instance.Annotations = map[string]string{"spec": string(data)} } if err := r.Client.Update(context.TODO(), instance); err != nil { return reconcile.Result{}, nil } return reconcile.Result{}, nil } Service := &corev1.Service{} if err := r.Client.Get(context.TODO(), req.NamespacedName, Service); err != nil && errors.IsNotFound(err) { // 2. 创建 Service service := NewService(instance) if err := r.Client.Create(context.TODO(), service); err != nil { return reconcile.Result{}, err } // 4. 关联 Annotations data, _ := json.Marshal(service.Spec) if service.Annotations != nil { service.Annotations["spec"] = string(data) } else { service.Annotations = map[string]string{"spec": string(data)} } if err := r.Client.Update(context.TODO(), service); err != nil { return reconcile.Result{}, nil } return reconcile.Result{}, nil } Ingress := &v1.Ingress{} if err := r.Client.Get(context.TODO(), req.NamespacedName, Ingress); err != nil && errors.IsNotFound(err) { // 2. 创建 Service ingress := NewIngress(instance) if err := r.Client.Create(context.TODO(), ingress); err != nil { return reconcile.Result{}, err } // 4. 关联 Annotations data, _ := json.Marshal(ingress.Spec) if ingress.Annotations != nil { ingress.Annotations["spec"] = string(data) } else { ingress.Annotations = map[string]string{"spec": string(data)} } if err := r.Client.Update(context.TODO(), ingress); err != nil { return reconcile.Result{}, nil } return reconcile.Result{}, nil } oldspec := janv1.JanSpec{} if err := json.Unmarshal([]byte(instance.Annotations["spec"]), &oldspec); err != nil { return reconcile.Result{}, err } if !reflect.DeepEqual(instance.Spec, oldspec) { data, _ := json.Marshal(instance.Spec) if instance.Annotations != nil { instance.Annotations["spec"] = string(data) } else { instance.Annotations = map[string]string{"spec": string(data)} } if err := r.Client.Update(context.TODO(), instance); err != nil { return reconcile.Result{}, nil } // 更新关联资源 newDeploy := NewJan(instance) oldDeploy := &appsv1.Deployment{} if err := r.Client.Get(context.TODO(), req.NamespacedName, oldDeploy); err != nil { return reconcile.Result{}, err } oldDeploy.Spec = newDeploy.Spec if err := r.Client.Update(context.TODO(), oldDeploy); err != nil { return reconcile.Result{}, err } newService := NewService(instance) oldService := &corev1.Service{} if err := r.Client.Get(context.TODO(), req.NamespacedName, oldService); err != nil { return reconcile.Result{}, err } oldService.Spec = newService.Spec if err := r.Client.Update(context.TODO(), oldService); err != nil { return reconcile.Result{}, err } return reconcile.Result{}, nil } newStatus := janv1.JanStatus{ Replicas: *instance.Spec.Replicas, ReadyReplicas: instance.Status.Replicas, } if newStatus.Replicas == newStatus.ReadyReplicas { newStatus.Phase = janv1.Running } else { newStatus.Phase = janv1.NotReady } if !reflect.DeepEqual(instance.Status, newStatus) { instance.Status = newStatus log.FromContext(ctx).Info("update game status", "name", instance.Name) err = r.Client.Status().Update(ctx, instance) if err != nil { return reconcile.Result{}, err } } return reconcile.Result{}, nil } // SetupWithManager sets up the controller with the Manager. func (r *JanReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). For(&janv1.Jan{}). Owns(&appsv1.Deployment{}). Owns(&corev1.Service{}). Owns(&v1.Ingress{}). Complete(r) }

[zhangpeng@zhangpeng develop-operator]$ kubectl delete svc jan-sample [zhangpeng@zhangpeng develop-operator]$ kubectl get svc

[zhangpeng@zhangpeng develop-operator]$ kubectl get ingress [zhangpeng@zhangpeng develop-operator]$ kubectl delete ingress jan-sample [zhangpeng@zhangpeng develop-operator]$ kubectl get ingress

最终代码:

jan_controller.go

/* Copyright 2022 zhang peng. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package jan import ( "context" "encoding/json" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" v1 "k8s.io/api/networking/v1" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "reflect" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/reconcile" janv1 "develop-operator/apis/jan/v1" ) // JanReconciler reconciles a Jan object type JanReconciler struct { client.Client Scheme *runtime.Scheme } //+kubebuilder:rbac:groups=mar.zhangpeng.com,resources=jan,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups=mar.zhangpeng.com,resources=jan/status,verbs=get;update;patch //+kubebuilder:rbac:groups=mar.zhangpeng.com,resources=jan/finalizers,verbs=update //+kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups=apps,resources=deployments/status,verbs=get;update;patch //+kubebuilder:rbac:groups=core,resources=services,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups=networking,resources=ingresses,verbs=get;list;watch;create;update;patch;delete // Reconcile is part of the main kubernetes reconciliation loop which aims to // move the current state of the cluster closer to the desired state. // TODO(user): Modify the Reconcile function to compare the state specified by // the Jan object against the actual cluster state, and then // perform operations to make the cluster state reflect the state specified by // the user. // // For more details, check Reconcile and its Result here: // - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.11.2/pkg/reconcile func (r *JanReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { defer utilruntime.HandleCrash() _ = log.FromContext(ctx) instance := &janv1.Jan{} err := r.Client.Get(context.TODO(), req.NamespacedName, instance) 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 return reconcile.Result{}, nil } // Error reading the object - requeue the request. return reconcile.Result{}, err } if instance.DeletionTimestamp != nil { return reconcile.Result{}, err } // 如果不存在,则创建关联资源 // 如果存在,判断是否需要更新 // 如果需要更新,则直接更新 // 如果不需要更新,则正常返回 deploy := &appsv1.Deployment{} if err := r.Client.Get(context.TODO(), req.NamespacedName, deploy); err != nil && errors.IsNotFound(err) { // 创建关联资源 // 1. 创建 Deploy deploy := NewJan(instance) if err := r.Client.Create(context.TODO(), deploy); err != nil { return reconcile.Result{}, err } // 4. 关联 Annotations data, _ := json.Marshal(instance.Spec) if instance.Annotations != nil { instance.Annotations["spec"] = string(data) } else { instance.Annotations = map[string]string{"spec": string(data)} } if err := r.Client.Update(context.TODO(), instance); err != nil { return reconcile.Result{}, nil } return reconcile.Result{}, nil } Service := &corev1.Service{} if err := r.Client.Get(context.TODO(), req.NamespacedName, Service); err != nil && errors.IsNotFound(err) { // 2. 创建 Service service := NewService(instance) if err := r.Client.Create(context.TODO(), service); err != nil { return reconcile.Result{}, err } // 4. 关联 Annotations data, _ := json.Marshal(service.Spec) if service.Annotations != nil { service.Annotations["spec"] = string(data) } else { service.Annotations = map[string]string{"spec": string(data)} } if err := r.Client.Update(context.TODO(), service); err != nil { return reconcile.Result{}, nil } return reconcile.Result{}, nil } Ingress := &v1.Ingress{} if err := r.Client.Get(context.TODO(), req.NamespacedName, Ingress); err != nil && errors.IsNotFound(err) { // 2. 创建 Ingress ingress := NewIngress(instance) if err := r.Client.Create(context.TODO(), ingress); err != nil { return reconcile.Result{}, err } // 4. 关联 Annotations data, _ := json.Marshal(ingress.Spec) if ingress.Annotations != nil { ingress.Annotations["spec"] = string(data) } else { ingress.Annotations = map[string]string{"spec": string(data)} } if err := r.Client.Update(context.TODO(), ingress); err != nil { return reconcile.Result{}, nil } return reconcile.Result{}, nil } oldspec := janv1.JanSpec{} if err := json.Unmarshal([]byte(instance.Annotations["spec"]), &oldspec); err != nil { return reconcile.Result{}, err } if !reflect.DeepEqual(instance.Spec, oldspec) { data, _ := json.Marshal(instance.Spec) if instance.Annotations != nil { instance.Annotations["spec"] = string(data) } else { instance.Annotations = map[string]string{"spec": string(data)} } if err := r.Client.Update(context.TODO(), instance); err != nil { return reconcile.Result{}, nil } // 更新关联资源 newDeploy := NewJan(instance) oldDeploy := &appsv1.Deployment{} if err := r.Client.Get(context.TODO(), req.NamespacedName, oldDeploy); err != nil { return reconcile.Result{}, err } oldDeploy.Spec = newDeploy.Spec if err := r.Client.Update(context.TODO(), oldDeploy); err != nil { return reconcile.Result{}, err } newService := NewService(instance) oldService := &corev1.Service{} if err := r.Client.Get(context.TODO(), req.NamespacedName, oldService); err != nil { return reconcile.Result{}, err } oldService.Spec = newService.Spec if err := r.Client.Update(context.TODO(), oldService); err != nil { return reconcile.Result{}, err } newIngress := NewIngress(instance) oldIngress := &v1.Ingress{} if err := r.Client.Get(context.TODO(), req.NamespacedName, oldIngress); err != nil { return reconcile.Result{}, err } oldIngress.Spec = newIngress.Spec if err := r.Client.Update(context.TODO(), oldIngress); err != nil { return reconcile.Result{}, err } return reconcile.Result{}, nil } newStatus := janv1.JanStatus{ Replicas: *instance.Spec.Replicas, ReadyReplicas: instance.Status.Replicas, } if newStatus.Replicas == newStatus.ReadyReplicas { newStatus.Phase = janv1.Running } else { newStatus.Phase = janv1.NotReady } if !reflect.DeepEqual(instance.Status, newStatus) { instance.Status = newStatus log.FromContext(ctx).Info("update game status", "name", instance.Name) err = r.Client.Status().Update(ctx, instance) if err != nil { return reconcile.Result{}, err } } return reconcile.Result{}, nil } // SetupWithManager sets up the controller with the Manager. func (r *JanReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). For(&janv1.Jan{}). Owns(&appsv1.Deployment{}). Owns(&corev1.Service{}). Owns(&v1.Ingress{}). Complete(r) }

总结

owns的一般使用 将 deployment service ingress或者其他资源作为operator应用的子资源,进行生命周期管理 下一步想处理一下 make run 控制台的输出,输出一些有用的信息

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Nocalhost - 让云原生时代的开发更高效
下一篇:苹果更新应用审核规则 严禁操纵审核、误导性营销等行为!
相关文章

 发表评论

暂时没有评论,来抢沙发吧~