首页 > 解决方案 > 如何在协调循环中处理长时间运行的任务

问题描述

我正在编写一个 Kubernetes 运算符并处理从协调循环中处理长时间运行任务的特殊情况。

我有以下情况:

func (r *ProvMyAppReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
    // _ = context.Background()
    _ = r.Log.WithValues("Instance.Namespace", req.NamespacedName)

    // your logic here
    var i int32
    var j int32
    var yappMyAppSpex myAppingv1alpha1.MyAppSpec
    var result *ctrl.Result
    var msg string
    var requeueFlag bool
    runFlag = false


    <<<<< Instance prov logic>>>

    // =============================== Check Deletion TimeStamp========
    // Check if the MyAppOMyApp instance is marked to be deleted, which is
    // // indicated by the deletion timestamp being set.

    // <<<<<<<Deleteion and finalizer logic is here>>>>>>>>
    

    // ================================ MyApp Setup ===================
    if len(instance.Spec.MyApp) > 0 {
            for i = 0; i < int32(len(instance.Spec.MyApp)); i++ {
                    yappMyAppSpex = instance.Spec.MyApp[i]
                    if !yappMyAppSpex.setRemove {
                            result, err = r.provisionStatefulSet(instance, prepareStatefulSetForMyApp(instance, yappMyAppSpex), "TYPE=TELEAPP")
                            if err != nil {
                                    return *result, err
                            } else {
                                    _, err = r.addMyApp(yappMyAppSpex.Name)    <<< This takes lot of time and if I do any operation on a CR resource , it is not cptured by K8s as operator is busy in running this job in foreground.>>>>
                                    if err != nil {
                                            requeueFlag = true
                                    }
                            }
                    }
            }
    }


    if runFlag {
            return ctrl.Result{Requeue: true, RequeueAfter: 30 * time.Second}, nil
    }
    return ctrl.Result{}, nil

}

我试图了解处理上述情况的最佳方法是什么?我需要使用频道并在后台运行它们吗?这里的主要问题是我必须运行一些配置,这会花费大量时间并导致 K8s 操作员无法处理在 CR 上完成的其他更新。

标签: gokubernetes-operator

解决方案


我建议的第一件事是充分利用资源状态。运营商的消费者知道运营商已确认更改并正在采取行动,这一点很重要。

然后,我建议重新审视 API 定义——这是要使用的正确 API 吗?即你能把它分成多个控制器(或API)吗?

一个简单的例子:在餐厅里,厨师兼服务员不是一个好主意,因为你想让顾客知道他们正在被照顾,但烹饪可能需要很长时间。客户最好有一个服务员接单,相应地标记订单状态,然后将其交给厨师执行(这可能是另一个仅在厨师和服务员之间使用的 API)。

在上面的示例中,您可以为单个应用程序实例添加 API。主控制器只负责为顶级 API 中声明的每个实例应用该 API(这不会花费很长时间)。工作控制器将响应该单应用程序实例 API 的创建并在其上执行。这对工作人员来说仍然需要时间,但可见性和用户体验会有所改善。


推荐阅读