-
Notifications
You must be signed in to change notification settings - Fork 185
Background
When running Texera on Kubernetes, computing units (CUs) remain alive even after they become idle. Although keeping idle CUs can reduce startup latency for subsequent workflow executions, they continue consuming cluster resources unnecessarily when they remain unused for an extended period.
As a result, clusters may gradually accumulate idle computing units, reducing the amount of resources available for active workloads.
Proposal
Issue #5362 proposes introducing an automatic cleanup mechanism for idle computing units.
The basic idea is to periodically check the status of running CUs and terminate those that have been idle for longer than a configurable timeout. This allows inactive resources to be reclaimed automatically while still giving users the benefit of reusing recently active computing units.
The timeout should be configurable so that different deployments can choose an appropriate balance between resource utilization and startup latency.
Initial Scope
For this proposal, the implementation focuses on:
- adding a configurable idle timeout;
- periodically checking whether a computing unit has been idle beyond the configured threshold;
- automatically terminating eligible idle computing units;
- ensuring active computing units are unaffected.
This proposal intentionally focuses on basic idle cleanup. More advanced policies (for example, different timeout strategies or discussions based on frontend heartbeat signals) can be discussed separately if needed.
Questions for Discussion
- Does periodically terminating idle computing units align with the intended Kubernetes resource management strategy?
- Is a single configurable timeout sufficient, or should different types of computing units have different timeout policies?
- Are there scenarios where idle computing units should intentionally remain alive and therefore be excluded from automatic cleanup?
I have prepared an implementation of this proposal for reference in PR #6046.
All reactions
Replies: 10 comments 16 replies
@yrenat Thanks for creating the discussion. Before we dive into the details, I wonder whether this problem is common in Kubernetes. If so, are there any existing solutions to this problem? Please do some research and report your findings.
All reactions
@chenlica
Based on my findings, this resource-waste problem is common. There are several generic solutions on "system" level, where they have a global control of what/how many resources are needed, but they can seldom address our specific problem where we need to control a specific pod/CU. The following are some of my findings, regarding garbage resource collection.
- HPA / custom metrics
This is the native idea from Kubernetes. It automatically changes the replica count of a scalable Kubernetes workload, such as a Deployment, ReplicaSet, ReplicationController, or StatefulSet, based on metrics like CPU, memory, or custom/external metrics. In simpler words, it can automatically scale up/down the number of pods/resources invovled. However, a Texera CU is a pod-specific per-user application resource with a DB record, access control, resource settings, and a corresponding runtime Pod (not just a pod). Also, "idle" is another Texera-specific, idea, which cannot be natively well-described by Kubernetes. Besides, HPA cannot fully shutdown the system. It has to have at least one pod running to keep track of all the computation resources. - KEDA
KEDA (Kubernetes Event-driven Autoscaling) is designed for event-driven autoscaling and can scale workloads down to zero when event sources become inactive. This is a good solution for queue/event-driven services. However, using KEDA directly would require Texera to expose CU activity as an external/custom metric or event source, which will create multi layers of interference with Texera. It also would not automatically update Texera’s CU database state unless Texera adds extra integration. - Knative Serving
Knative supports scale-to-zero for HTTP request/traffic-driven services. This is useful for serverless HTTP workloads, but a lot of Texera resources/commands are not handled in HTTP format. Adopting Knative would be a larger architectural change and still may not capture Texera’s definition of CU idleness. Besides, Knative also does not focus on pod/CU level logistics.
To sum up, for the current issue, I think the most suitable first solution is to implement our tailored idle detection inside Texera’s Computing Unit Managing Service or a Texera-side scheduled cleanup component. The cleanup should use Texera’s own CU termination logic rather than directly deleting Pods, so that both the Kubernetes Pod and the Texera DB state remain consistent.
All reactions
Hi @yrenat We need this feature and thank you for working on this task! I did some research before and concluded that Kubernetes does not natively support this feature. I agree we need to have our own way mechanism to terminate idle CUs.
What's missing in both this discussion post and your PR is how you defined what "idle" CU means and the architectural design of how computing unit manager monitors all the CUs. Can you be more specific on those parts? Please include some visual diagrams if you can. We need to agree on the design before reviewing the PR.
All reactions
Yes, the result retrieval path is currently tied to the original live CU (results are fetched through the workflow websocket handled inside the CU), so once the CU is gone the UI can't reach them even if the data is still in storage. I documented this in #5363, we haven't planned to work on it yet. I agree with @kunwp1 that a separate CU-independent retrieval path would be a fairly large change.
@kunwp1 On the retention idea — I remember we already have two related mechanisms: (1) a result-retention parameter result-cleanup.ttl-in-seconds (env RESULT_CLEANUP_TTL_IN_SECONDS, default 24h) with a periodic cleanup in ComputingUnitMaster; (2) a ~30s cleanup (web-server.workflow-state-cleanup-in-seconds) that clears the latest execution's results once the last user disconnects and the workflow is no longer running. Since you have more context on this part, does that match your understanding?
All reactions
Yes. The definition of "idle" I am proposing is "no execution in the CU for a certain amount of time && no workflow result in the CU". Wonder whether this condition makes sense.
All reactions
@chenlica @kunwp1 Please correct me if I am wrong but I think the qualified "idle" CUs in your definition would be
- those that have never been executed, and
- those whose results have been automatically cleaned
I have already covered case 1 in the PR. And for case 2, I think I should then focus on using the internal time intervals, rather than using a set of new env variables.
All reactions
Aligns with my suggestion.
All reactions
-
👍 1
@yrenat Thanks for reporting the findings. I am wondering: do other systems have something similar to "CU"? If not, what do they use? If the "Computing Unit (CU)" concept in Texera unique, we want to know its pros and cons compared to other systems.
All reactions
|
@chenlica I have done some researches and my current understanding is that other systems have related concepts, but not exactly the same idea. In Texera, a CU is kept with information such as owner A CU also has access control and sharing through Therefore, the CU combines several concepts:
Other systems usually split these responsibilities across lower-level concepts:
So I would say that technically Texera's CU is not completely unique. However, it does sound unique because it is integrated directly into the workflow system and treated as a user-visible, shareable, routable, and persistent resource. Pros:
Cons:
Therefore, for this idle-cleanup feature, I think cleanup should happen through Texera's CU manager rather than directly through Kubernetes. Only Texera knows whether a CU is idle according to workflow state and can update both the runtime resource and Texera's DB state consistently (see the first Con listed above). |
All reactions
I think this is a natural idea, you don't want to allocate more resources in the cluster than you need. I think the concept in k8s that would let you handle this best would be an Operator (https://kubernetes.io/docs/concepts/extend-kubernetes/operator/). Then, Texera itself could through its operator tell Kubernetes it no longer needs some set of pods. I assume Texera currently doesn't have an operator? I took a cursory look and didn't find an implementation of one.
All reactions
@yrenat Thanks for the nice summary. Currently a Texera CU is implemented as a Kubernetes pod. For the long term we do want to keep the abstraction of a CU, and choose other implementations such as a cluster of nodes to run the parallel Amber engine.
For other systems you have investigated, did you find any of them using a K8S pod as a basic computing unit?
All reactions
@chenlica
Ray: According to the Ray Kubernetes documentation, a Ray node is implemented as a Kubernetes pod: the head node runs in one pod, and each worker node also runs in a pod. The Ray autoscaler scales the cluster by adding or removing worker pods.
Dask: Dask is also similar at the implementation level. A Dask cluster contains a scheduler pod and a set of worker pods.
Spark/Flink: Spark and Flink also map their runtime components to Kubernetes pods. Spark uses driver and executor pods, while Flink uses JobManager and TaskManager pods.
From my understanding, I think the main difference from Texera is that Texera exposes the CU (which sits on top of a k8s pod) as a user-controllable and reusable resource with its own ownership and access control, resource configuration, lifecycle state, runtime endpoint, and workflow-execution association.However, Ray and Dask generally expose the cluster as the higher-level abstraction, while individual pods represent nodes or workers inside the cluster. Normal users do not directly manage or select these pods.
Personally, based on my recent research, I also feel that our current CU abstraction is sort of "bulky". A CU currently combines several responsibilities, including access control, resource configuration, runtime location, lifecycle management, and workflow association. My concern is that mixing all of these responsibilities directly to the CU may make CU creation, removal, and future on-the-go changes more complicated.
I am also thinking about whether we could separate the logical CU abstraction from some of these lower-level details. For example, a CU could reference or be linked to separate resource, runtime, and access-control information, rather than directly owning these attributes.
All reactions
I support the idea of separating a "logical CU" from a "physical CU." In this discussion of the lifecycle of a "CU," it refers to a physical CU, which is currently a k8s pod.
I wonder for other systems that also use a k8s pod:
- Do they have the need to kill an idle k8s pod?
- If so, how do they kill such a pod?
- How does the termination of a pod affect the "logical CU"?
All reactions
Hi all, after investigating current solutions and several discussions with @chenlica, we concluded that our current CU implementation with Kubernetes is a reasonable/common approach. Kubernetes itself also does not seem to provide a convenient built-in way to handle the garbage collection we need.
@chenlica agrees with my current garbage-collection implementation, but pointed out one issue: users cannot decide how long a CU can stay idle before being removed. Right now, this timeout is fixed by developers and is the same for all CUs/users.
We agreed that users should be able to set this value themselves. However, this may require passing the user input from the frontend to the backend and using it dynamically for each CU, which I assume is not very straightforward.
I would like to hear from anyone who has worked on similar frontend-to-backend parameter passing in this module, or knows something that I can refer to. Thanks
All reactions
@xuang7 @aglinxinyuan : Can you share some thoughts?
All reactions
I don’t have enough knowledge about Kubernetes and CU-related topics.
All reactions
If you are talking about inputs for frontend-to-backend parameter passing, @yrenat, you can check the admin settings where we pass some config from the frontend to the backend, but that's at the system level. Besides that, we have some workflow settings that are part of the workflow JSON. Other than that, what's left are probably the parameters we input in the frontend during the CU creation.
All reactions
-
👍 1
Hi All, a brief update about the topic:
- To provide a better picture of my PR that is related to this discussion, I think I should explain one of the key variables that I was using. One of the main functional variable to decide which CU has been idle is
last_active, which is first introduced in this PR. This PR aims to clean garbage workflow execution results after a configured TTL. It starts a recurring cleanup task that periodically finds expired executions and removes it. I uselast_activein my code because a CU is considered occupied only if there is at least one workflow running in this CU. So, if all workflow inside the given CU is inactive, it is safe to say the whole CU is inactive. We can then clean it. - As for on-the-fly update of the CU parameters (
CU_idle_time_before_removalin my PR, to be specific), I have tried the methods mentioned above, but it turns out that they don't fit my use case well. What we really need is a pathway at CU level, after the CU is created. Sadly I didn't find a corresponding pathway, and I guess it would be a moderate level task to build such a thing. So, for now, I think it's better to keep the PR as it is (i.e., provide a globalCU_idle_time_before_removalthat fits into all CUs)
All reactions
-
👍 1