Skip to content

Own immutable Tau workload lifecycle - #31

Open
Kevin Cho (chokevin) wants to merge 2 commits into
mainfrom
chokevin-own-workload-lifecycle
Open

Own immutable Tau workload lifecycle#31
Kevin Cho (chokevin) wants to merge 2 commits into
mainfrom
chokevin-own-workload-lifecycle

Conversation

@chokevin

Copy link
Copy Markdown
Contributor

Why

Completed Tau workloads with fixed Kubernetes names could block later submissions of the same logical run, forcing users to preserve evidence manually and use kubectl delete or replacement. Tau should own both immutable execution identity and safe workload lifecycle without overwriting prior runs.

What changed

  • Generate a fresh immutable run ID for each real submission and derive a run-qualified physical Job or RayJob name, while retaining the authored name as logical identity.
  • Keep uncertain-create recovery idempotent within one submission attempt; independent invocations intentionally create distinct runs.
  • Resolve lifecycle selectors consistently by exact physical name, exact run ID, or unique logical name, with explicit ambiguity errors.
  • Add Tau-native active-only cancel, terminal-only delete/remove, and terminal-only archive behavior.
  • Require Tau ownership labels, matching immutable run ID, and UID-preconditioned deletion before mutating workloads or associated Services and orphan RayClusters.
  • Make retry and resume create successor executions without deleting predecessors, including preserving metrics-session output continuity.
  • Document logical versus physical identity and lifecycle retention semantics.

Compatibility and safety

The existing config name remains the public logical run name. Physical names are capped at 47 characters for KubeRay compatibility. Client dry-run output remains deterministic, while server dry-run and real submissions use immutable identities. Cleanup never performs namespace-wide or label-only broad deletion and refuses foreign or ambiguous resources.

Validation

  • cd cli && go test ./... -count=1
  • cd core && go test ./runs ./workloadmeta -count=1
  • git diff --check

AI tools assisted with implementation and review; the resulting changes were independently reviewed and tested before submission.

Comment thread cli/internal/cli/run_lifecycle.go
Comment thread cli/internal/cli/run_lifecycle.go
Comment thread cli/internal/cli/run_workload_resolver.go Outdated
if !isRunWorkloadNotFound(err) {
return err
}
deleted, cleanupErr := deleteOwnedRunRayClusters(cmd.Context(), newKubernetesRunSubmissionRunner(r), ns, args[0])

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 This passes the original selector as a physical RayJob name, but orphan lookup filters ray.io/originated-from-cr-name. After the RayJob is gone, tau run delete <run-id> or a unique logical name therefore finds no RayCluster. Resolve orphan clusters by physical origin, run-ID, or logical name with the same ambiguity rules before deletion.

{resource: "jobs.batch", kind: "Job"},
{resource: "rayjobs.ray.io", kind: "RayJob"},
} {
out, err := runner.Raw(ctx, []string{

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Exact-name operations now require list permission for both Jobs and RayJobs before matching starts. A Job-only principal fails on the RayJob list (and vice versa), so it cannot operate on a workload it is authorized to read. Try exact named GETs first, and reserve cross-kind listing for run-ID or logical-name resolution.

return err
}
defer restore()
workloadRef, err := resolveRunWorkload(cmd.Context(), kube.New(resolvedContext), ns, name)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 This unconditional live-workload lookup breaks the documented recovery path after metadata deletion. Even with both --path and --pvc, a deleted Job or RayJob returns no-match before the supplied durable location is read. Skip workload resolution when both overrides are present.

service := runSubmission{Resource: "service", Name: run.Name + "-headless", Namespace: run.Namespace}
metadata, err := existingRunMetadata(ctx, runner, service)
if err == nil {
if metadata.Labels[workloadmeta.LabelManagedBy] != workloadmeta.ManagedByValue ||

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Pre-upgrade multi-node Jobs have a run-ID label on the Job, but their headless Service only has managed-by=tau; ownership was recorded by its controller ownerReference. This new check rejects that Service before deleting the Job, so cancel/delete cannot clean up existing runs after upgrade. Accept the legacy shape only when the controller ownerReference matches the resolved Job name and UID.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants