Closed naveensrinivasan closed 1 week ago
Hey @naveensrinivasan maybe i'm misunderstanding, but i dont think we ever want any tasks to ever be executed concurrently unless there is a mechanism in the task file's syntax explicitly indicating that should be the behavior or multiple tasks are called in a uds run
command execution.
That being said, i had created a related [issue](https://github.com/defenseunicorns/uds-cli/issues/187)
around when the task runner got added to this project where concurrent task execution would come into play.
The only other scenarios i can think of would again require another keyword to indicate that a task can run out of order of the other tasks (i think this might get convoluted in terms of the yaml syntax and we dont want that) or to allow multiple tasks to be executed by uds run
like uds run lint test build
and have a defined, documented behavior that running things like this will execute concurrently.
Outside of those scenarios and the use case described in the linked issue i think we'd want to be careful about how we approach that.
I'll definitely defer to @UncleGedd here if he has more specific thoughts, but just wanted to make you aware of that other issue that had been created. Thanks for the thorough issue definition here!
Given the concerns raised about concurrent tasks in Kubernetes, it's crucial to understand how Kubernetes' architecture and its principle of eventual consistency effectively manage such scenarios. Kubernetes is designed to handle many operations concurrently, ensuring system stability and reliability. Here's a detailed explanation:
Kubernetes employs an eventual consistency model through its controllers and control loops. Each controller watches for changes to specific resources, analyzing the current state against the desired state and acting to reconcile any discrepancies. This continuous process allows Kubernetes to adapt to changes and maintain the desired system state over time.
The lifecycle of a Kubernetes controller can be summarized in a continuous loop of observing changes, analyzing the current versus desired state, and acting to reconcile. This loop ensures that Kubernetes can handle concurrent tasks without leading to system instability. Here's a simplified diagram illustrating this process:
graph TD;
A[Start] --> B{Observe Changes};
B --> C[Analyze Current vs. Desired State];
C --> D{Is Reconciliation Needed?};
D -->|Yes| E[Act to Reconcile];
E --> B;
D -->|No| F[Wait for Next Change];
F --> B;
Despite the robustness of Kubernetes' design, certain scenarios require careful management of task sequences and dependencies to avoid issues:
For these scenarios, incorporating retry logic, readiness checks, and careful planning of task sequences can mitigate issues by ensuring that dependent resources are fully ready before proceeding with subsequent operations.
While Kubernetes' architecture and eventual consistency model provide a solid foundation for managing concurrent tasks, awareness of and planning for specific dependency scenarios are crucial. By understanding these caveats and employing strategic task management, we can leverage Kubernetes' strengths while mitigating potential issues related to resource dependencies and operation orders.
Thanks for the conversation, concurrency isn't a priority atm but I'm sure it will be valuable in the future. I think for now we can table this issue while the runner code gets migrated to its own repo, and I'll transfer this issue to the new repo
I'll be honest I'm kind of confused by this discussion there is a lot of talk about kubernetes, but this function under uds run
has nothing to do with kubernetes. Apologies if I'm missing something here but this is my reasoning:
It (uds run
) is a task runner that essentially executes shell commands for use in CI and locally similar to what you would use make or Taskfile for. Also similar to say job execution in CI systems such as gitlab ci or GitHub workflows.
You might use a task to run a command that does something in kubernetes (like kubectl) but that is the tool this is executing doing that, not the tasks themselves and therefore assumptions based on how kubernetes works should not be built into the way we handle execution in uds run
tasks.
I'll be honest I'm kind of confused by this discussion there is a lot of talk about kubernetes, but this function under
uds run
has nothing to do with kubernetes. Apologies if I'm missing something here but this is my reasoning:It (
uds run
) is a task runner that essentially executes shell commands for use in CI and locally similar to what you would use make or Taskfile for. Also similar to say job execution in CI systems such as gitlab ci or GitHub workflows.You might use a task to run a command that does something in kubernetes (like kubectl) but that is the tool this is executing doing that, not the tasks themselves and therefore assumptions based on how kubernetes works should not be built into the way we handle execution in
uds run
tasks.
My ignorance! Thanks for the clarification! I appreciate it! My k8s post was me being a noob
I'll be honest I'm kind of confused by this discussion there is a lot of talk about kubernetes, but this function under
uds run
has nothing to do with kubernetes. Apologies if I'm missing something here but this is my reasoning:It (
uds run
) is a task runner that essentially executes shell commands for use in CI and locally similar to what you would use make or Taskfile for. Also similar to say job execution in CI systems such as gitlab ci or GitHub workflows.You might use a task to run a command that does something in kubernetes (like kubectl) but that is the tool this is executing doing that, not the tasks themselves and therefore assumptions based on how kubernetes works should not be built into the way we handle execution in
uds run
tasks.My ignorance! Thanks for the clarification! I appreciate it! My k8s post was me being a noob
No worries. Totally understandable... it's a lot to try to digest all at once!
@naveensrinivasan just to close out this thread. We definitely would still want to retain the ability in bundle deployments (ie uds deploy
) to explicitly control ordering of package deployments, but this issue is targeted at trying to find a way to sanely implement concurrency for certain packages to complement the sequential ordering that exists today.
https://github.com/defenseunicorns/uds-cli/issues/30
If there are no objections though, I think this specific issue can be closed.
We can keep this issue, I'll migrate it over to the new runner repo once that is all set up. FWIW I could see a use case for concurrent tasks when doing things like building multiple, independent Zarf pkgs
We can keep this issue, I'll migrate it over to the new runner repo once that is all set up. FWIW I could see a use case for concurrent tasks when doing things like building multiple, independent Zarf pkgs
Sounds good. Thanks!
closing in favor of #138 #131 and #164 since these focus on some of the more specific changes
Body:
Summary
The current implementation of the executeTask method in
runner.go
executes each action within a task sequentially. This approach ensures simplicity and straightforward execution flow but may not efficiently utilize system resources, especially when actions are independent and could be executed concurrently. This proposal suggests enhancing the executeTask method to support concurrent execution of actions, potentially improving performance and reducing task completion time.Motivation
Tasks that contain multiple independent actions can benefit significantly from concurrent execution. In the current sequential execution model, the total execution time is the sum of all actions' execution times. By executing actions concurrently, we can reduce the total execution time to the duration of the longest-running action, assuming sufficient system resources. This improvement is particularly beneficial for tasks with many independent actions or tasks where actions are I/O bound and spend significant time waiting.
This should reduce the wait time to bootstrap an
env
Proposed Changes
task.EnvPath
) is thread-safe and correctly applied to each action executed concurrently.Implementation Details
sync.WaitGroup
to wait for all goroutines (actions) to complete.Risks and Mitigations
Prototype
not tested or compiled
Conclusion
Adopting concurrent action execution in the
executeTask
method has the potential to significantly improve performance for tasks with multiple independent actions. By carefully managing the risks associated with concurrency, we can make the task execution process more efficient and responsive to user needs.