Blog: Inside Kueue : How Kubernetes decide what runs next - #266
Blog: Inside Kueue : How Kubernetes decide what runs next#266ekam-walia wants to merge 1 commit into
Conversation
|
cc @saiyam1814 |
saiyam1814
left a comment
There was a problem hiding this comment.
Hey @ekam-walia, thanks for sending this in. I read the whole thing properly and also got a preview build up so I could see it rendered rather than just reading the diff.
Quick note on that: Cloudflare doesn't build previews for PRs that come from forks, so I pushed your commits to a branch on our repo to get one. You can see the post live here:
https://blog-inside-kueue.website-dab.pages.dev/inside-kueue-how-kubernetes-decides-what-runs-next
Worth opening that yourself before you start editing, because a few things read fine in the markdown but fall apart on the page.
The good part first, and I mean it. Your instinct for explaining things is the strongest thing about this post. The "four team members, one still waiting for a computer" framing of gang scheduling is the clearest version of that idea I have read anywhere, and Demo 1 has a real story to it: job A takes the room, job B waits, A leaves, B gets in. That is exactly the shape a good hands-on post has. The microservices vs batch comparison table is useful too.
So this is worth finishing. But I can't merge it as it stands, and I would rather be straight with you about why than send it back with vague notes.
What's blocking merge
minimumReservedResources is not a real Kueue field. Strategy 2 is built entirely on it, and it doesn't exist in the API. A ClusterQueue resource entry takes nominalQuota, borrowingLimit, and lendingLimit, and that's it (see the ClusterQueue concepts page). The API server would reject that YAML. If part of this came out of an AI draft, no judgment at all, that is a fine way to get a first draft, but everything has to get applied to a real cluster before it ships. The genuine answers to "job B is starving" are workload priorities with preemption, or cohorts with borrowingLimit so one queue can lend spare capacity without giving up its floor. Either one makes a better Strategy 2 than what's there now.
Strategy 1 would break admission rather than prevent deadlock. Both demo jobs request CPU and memory. A ClusterQueue whose coveredResources only lists cpu can't admit a workload that also asks for memory, it gets marked inadmissible. So splitting into a cpu-only queue and a memory-only queue doesn't route jobs by their dominant resource, it just stops both jobs from ever being admitted. If the point is isolation between job types, that's separate ClusterQueues each covering both resources, optionally in a cohort.
The version is about two years stale. You're pinning v0.6.1 and current is v0.19.2. Please re-run on a current release and update the URL in both places it appears (install step and the Resources list at the end).
The command output looks reconstructed rather than pasted. A few tells: kubectl get workloads shows the generated workload name, so it would be something like job-job-a-big-2f4c1, not job-a-big. The QUEUE column shows the LocalQueue the job went through, which in your setup is default, not demo-queue. And kubectl describe workload job-b-small wouldn't resolve, since that's the Job's name and not the workload's. Same thing in Demo 2. "Real commands, real output" is honestly the main thing we ask for (it's the first bullet under "What we look for" in WRITING-A-BLOG.md), and it's also the thing readers can smell instantly. Please paste what your terminal actually printed, hashes and odd column widths and all.
Demo 2 isn't really a deadlock. Job B waiting for job A to finish its sleep 600 is queuing, or starvation if you want to be dramatic about it. It resolves on its own, which the post half admits when it says "when Job A finishes, resources are released". The actual deadlock is the one you describe correctly up in the gang scheduling section: a distributed job gets 3 of its 4 pods placed, those 3 hold resources, and nothing progresses. That's the thing worth demoing. Either rename Demo 2 to what it is, or build the real one with two gang jobs competing.
Render issues
All of these are visible on the preview link:
- Eight
<h1>s on the page. Body headings need to start at##, since the frontmatter title is already the H1. Right now seven of your section headings compete with the title and clutter the table of contents. - Prose stuck inside a code block. Under Strategy 2 the "How it works" explanation renders as YAML, because the fence never gets closed before it. Close the fence after the last YAML line.
- A stray
**renders literally in "Strategy 2: Use minimumReservedResources**". - The arrow flowcharts collapse into run-on paragraphs. Markdown eats single newlines, so "Pod lands → Scheduler checks if it fits on any node." and the two lines under it become one blob. Same problem hits the "What Just Happened" recap, the Pod 1 through Pod 4 dependency chain, the car analogy, and the three links at the end. Make those bullet lists, or wrap them in a ```text block if you want the arrow-diagram look.
- Unfenced output in Demo 1 Step 8: the
Conditions:block runs together as a paragraph while every other output block is fenced. - Headings used as emphasis. "##### Kueue checks: Can I fit all 4?" and "##### Queue is stuck" are sentence fragments sitting in the heading hierarchy and the TOC. Bold text does that job.
- Missing space: "Which job gets them?Jobs from all namespaces compete here" (and the quote before it never closes).
Style, small stuff
- No em dashes on the blog. Two here: the
seoDescription("workloads—with a hands on demo") and "someone deploys a Batch Job—maybe it's...". A comma or a period does the job. While you're in that line, "hands on" wants a hyphen: hands-on. - Tags should be lowercase, hyphenated, 2 to 5 of them, no slashes.
"AI/ML"breaks the tag page URL because of the slash. I'd go with["kubernetes", "kueue", "scheduling", "batch-workloads"]. - Images are heavy: cover is 1.2MB, and the two diagrams are 1.6MB and 1.8MB. Please get them under ~300KB each, WebP if you can.
- Typos worth a pass: "schedular" should be scheduler, "Core principal" should be principle, "it's fix" should be its fix, and "until desired resources don't get vacant" reads oddly (try "until resources free up"). The heading "Now Lets jump on to how Fix this DEADLOCK" needs a rewrite, and "Now let's first understand what Batch Jobs are and the concept of Gang Scheduling, also how they create a DEADLOCK Issue through an example" is a whole sentence doing a heading's job. Curly quotes have crept in from a word processor in a few spots, straight quotes please.
- The post opens directly on a heading and ends on a bare link dump. Two or three sentences up top saying who this is for, and a short wrap-up at the end, would round it off.
One process thing
None of the four commits have a DCO sign-off, which we do require. Easiest fix is to squash them into one:
git reset --soft origin/main
git commit -s -m "Add blog post: Inside Kueue: How Kubernetes Decides What Runs Next"
git push --forceThat also cleans up the commit messages, which are currently "..", "...", and "Is this reqd".
I know that's a long list. It isn't a rejection, and none of it is about your voice, which is fine. It comes down to: fix the two strategies so they use mechanisms Kueue actually has, re-run the demos on a current version and paste what you really saw, and clean up the heading levels. Do that and this is a solid post that I'll be glad to publish with your byline on it.
Ping me here when you've pushed and I'll refresh the preview and take another look. If you get stuck on the priorities/preemption or cohort setup, ask, that part of Kueue is genuinely fiddly.
32a4d31 to
c829c59
Compare
|
Hi @saiyam1814, I have made all the suggested changes, I have added a new block |
saiyam1814
left a comment
There was a problem hiding this comment.
Thanks @ekam-walia, this is a big step up and I can see the work that went into it. Most of what I flagged is genuinely fixed, so let me confirm that first and then give you the short list that's still open.
Fixed and verified:
minimumReservedResourcesis gone, and so is the Strategy 1 section that would have broken admission. EverycoveredResourcesblock now lists both cpu and memory.- You're on v0.19.2 instead of v0.6.1.
- The workload names in the output are real now (
job-job-a-big-cb1a1,job-job-b-small-c8c54), the QUEUE column shows the LocalQueue with RESERVED IN alongside it, anddescribetargets the workload rather than the job. That reads like an actual terminal, which is exactly what I was after. Thecouldn't assign flavors to pod set main: insufficient unused quota for cpu in flavor default, 3 more neededmessage is a nice touch. - All eight H1s are gone, the fences are balanced, the stray
**is gone. - Tags are down to four, lowercase and hyphenated.
- Images are WebP and all under 105KB, down from 1.6MB and 1.8MB.
- schedular, principal, "it's fix" and "don't get vacant" are all cleaned up.
- Commits squashed to one with a proper DCO sign-off and a real message.
That's most of the list. Here's what's left, and unfortunately the first two are the kind that have to be right before it goes out.
The install command is broken
Line 219 currently reads:
kubectl apply -f kubectl apply --server-side -f https://github.com/kubernetes-sigs/kueue/releases/download/v0.19.2/manifests.yamlThe kubectl apply -f prefix got duplicated, so the shell would treat the literal string kubectl as a filename. This is the very first command anyone runs, so the tutorial stops there. The version in your Resources section at the bottom is correct, just copy that one up:
kubectl apply --server-side -f https://github.com/kubernetes-sigs/kueue/releases/download/v0.19.2/manifests.yamlThe closing takeaway isn't right
The wrap-up ends on this:
The best part? One line fixes it:
suspend: true. That's it.
That's not what does the work, and I'd hate for the last thing a reader takes away to be the one wrong thing. What enrolls a Job with Kueue is the kueue.x-k8s.io/queue-name label. Kueue's webhook then sets spec.suspend itself when it admits or holds the job. You can confirm it from Kueue's own sample job, which has the queue-name label and no suspend field anywhere:
https://github.com/kubernetes-sigs/kueue/blob/main/site/static/examples/jobs/sample-job.yaml
This also affects your "Before Kueue" and "After Kueue" pair, because both of those YAMLs already carry the queue-name label. As written, Kueue would manage both of them identically, so the only difference you're showing isn't the thing doing the work. Rewriting that section around the label (and mentioning that Kueue handles suspension for you) would land the point properly, and it's honestly a better ending: you add one label and Kueue takes over admission.
Worth a look while you're in there: job-b-needs-6-gets-3 has completions: 1 with parallelism: 2, which is an odd combination. I think you want both set to 2, the way your "Before Kueue" example has it.
The deadlock section is a good explanation but still isn't a demo
The new "The Real Deadlock Demo (Gang Scheduling)" block explains partial admission much better than the old Demo 2 did, and the reasoning is correct. But everything in it is narrative and YAML, with no captured output showing the deadlock actually happening. Right now it's labelled a demo and reads as a description.
Two ways to fix it, either is fine. Rename it to something like "Understanding the Deadlock" so it doesn't promise a run. Or, better, actually run those two jobs and paste what kubectl get workloads and kubectl get pods show while it's stuck. Given you clearly have a working cluster (your Demo output proves it), the second option would make this the strongest section in the post.
Smaller things
- Both em dashes are still there. Line 11 ("works great for microservices—until someone") and line 43 ("someone deploys a Batch Job—maybe it's"). Line 43 is the exact one I flagged last time. We don't use em dashes on the blog, a comma or a full stop is fine.
- Arrow lines still collapse into paragraphs. You fixed several by wrapping them in ```text blocks, which is exactly right, but these are still bare and will render as run-on paragraphs: the Pod 1 through Pod 4 dependency chain, the "Result / Status / Wasted resources" block, the "What happens?" recap, the "Kubernetes scheduler doesn't understand gang scheduling" list, the "What Just Happened" recap after Step 9, and the three links under Resources. Same fix as the ones you already did.
them?Jobsin the ClusterQueue explainer still has no space, and the quote before it doesn't close.- Mixed API versions. ClusterQueue appears as
v1beta1in the demo andv1beta2in the deadlock section. Both are served in v0.19.2 so nothing breaks, but pick one, and I'd usev1beta2since that's the storage version now. Your LocalQueue is still v1beta1 too. - Heading levels jump around. You go from
##straight to####and#####, and in one spot######. Since the levels feed the table of contents, keeping to##and###will make the sidebar readable. - The heading at line 49 is still a full sentence ("Now let's first understand what Batch Jobs are and the concept of Gang Scheduling, also how they create a DEADLOCK Issue through an example."). Something like "Batch Jobs and Gang Scheduling" would do the same job.
- Your bio in authors.json is still the placeholder "Writing some cool stuff ... ". Worth a real sentence, it shows on your author page.
Fix the install command and the suspend: true ending, decide what to do about the deadlock section, and do a pass on the arrow blocks and em dashes, and I'm happy to publish this. The demo section is in good shape now, which was the hard part.
Signed-off-by: ekam-walia <164983405+ekam-walia@users.noreply.github.com>
c829c59 to
dba21c2
Compare
|
Hi @saiyam1814, I have made all the changes that were suggested by you, I have made the whole deadlock block again |
|
Thanks @ekam-walia. The deadlock section is the real thing now: actual https://blog-inside-kueue.website-dab.pages.dev/inside-kueue-how-kubernetes-decides-what-runs-next Confirmed fixed from last round: the install command (line 228), the One genuinely interesting thing came out of verifying this round, and it's the main thing left to fix. The label isn't where you think it is, and your own demo proves itI went to check why your outputs worked, because the YAMLs say they shouldn't have:
So why did it all work on your cluster? Because both of your LocalQueues are named That matters because the post ends on "The magic? One label", and a reader who copies your YAMLs into a namespace whose LocalQueue is named anything else will watch Kueue ignore their jobs completely, with no idea why. The fix is small: put Output pastes that don't match the commands next to themSame class of issue as round one, four spots:
The two demos collide if someone runs the post top to bottomDemo 1 creates LocalQueue The abstract deadlock story contradicts its own numbersThe "Real Problem (Without Kueue)" block runs on 12 CPUs, Job A takes 8, Job B needs 6 as 2 pods. But then "Pod 1 starts with 4 CPUs" (a pod requests a fixed amount, it can't soak up whatever is free; 2 pods needing 6 total is 3 each) and "Pod 2 is waiting for 3 CPUs" while the setup says only 4 of 6 were available. It also says "Kubernetes admits it anyway" with Pod 2 Pending, but your actual demo blocks pod creation via ResourceQuota, so Pod 2 never exists at all. Simplest fix: rewrite that block using the demo's real numbers (1500m quota, A takes 800m, B is 2 x 400m, pod 2 forbidden because 1200m + 400m > 1500m) so the story and the terminal output match. Render and style pass
That's the whole list, and none of it is structural this time. Fix the label placement (the one that changes what readers learn), align the four pastes, add the cleanup step, and do the render pass, and this merges. I'll bump The instinct to verify why something works, not just that it works, is what separates this post from most Kueue content out there. You're one pass away. |
Fixes Issue
NONE
Changes proposed
Added a Blog
Screenshots
NONE
Note to reviewers
This PR covers the blog Inside Kueue: How Kubernetes decide what runs next