Certifications · PCA · Mock Exam · Set 2

PCA Mock Exam · Set 2

The second of two PCA papers on this course, sitting on the exact same forty-five-question, five-domain split as Set 1 — thirteen PromQL, nine Prometheus Fundamentals, eight each on Observability Concepts and Alerting & Dashboarding, seven on Instrumentation and Exporters — so your two scores are directly comparable. The difference is shape, not size. Set 1 tested whether you could name a definition or read one function cold; this set drops you into a scenario — an engineer's query, a dashboard behaving oddly, two proposed configs — and asks you to reason through two or three clues layered together before picking an answer, the way the real associate exam tends to phrase its harder items. Sit this one after Set 1 is solid, not before: it assumes the vocabulary and reaches straight for how it gets misapplied in practice.

☺ Explain it like I'm 10

Set 1 asked "what's this called?" This set asks "here's a small story about something going wrong — now figure out why." Both are still just picking the best of four answers and reading the explanation right after, but this time the question usually gives you two or three clues stitched together, and you have to notice which clue actually matters. It's harder in the way a word problem is harder than a times-table question, even though it's testing the exact same math underneath.

🐘🐰Your hosts for this topic: Ellie the Elephant & Remy the Rabbit — Ellie is here again for the same reason as Set 1, the metrics store and PromQL, but this time she's watching for the layered traps: a query that's syntactically fine but structurally wrong. Remy keeps the pace honest, because a scenario question read too fast is where most of this set's marks get lost.

How this paper is weighted

☺ Like you're 10: Same five topics, same number of questions per topic as last time — only the questions themselves got trickier.

Set 2 keeps Set 1's exact domain split — 13 · 9 · 8 · 8 · 7 across PromQL, Prometheus Fundamentals, Observability Concepts, Alerting & Dashboarding, and Instrumentation and Exporters — because the whole point of a second paper is a clean, apples-to-apples comparison against your first score. What changes is how each question is built. Instead of "what does this one function do," expect "an engineer wrote this query/config/alert for this reason — which of these explanations of what actually happens is correct." Several questions present two superficially similar approaches side by side and ask you to spot the one genuine difference between them, which is exactly the skill a knowledge-only, no-terminal exam has to lean on to test whether you can really use PromQL rather than recognize it.

DomainOfficial weightQuestions hereWhere to revise
🐘 PromQL28%13PCA — the exam · Prometheus
🦉 Prometheus Fundamentals20%9Prometheus · PCA — the exam
🐿️ Observability Concepts18%8The OpenTelemetry data model
🐢 Alerting & Dashboarding18%8Grafana · PCA — the exam
🦫 Instrumentation and Exporters16%7OpenTelemetry Collector
60-minute pace · 45 questions · 75% to pass Block 1 Q1–15 · ~20m Block 2 Q16–30 · ~20m Block 3 Q31–45 · ~20m 0 40 60 min Same weighting as Set 1 — the questions are what changed PromQL 28% Fundamentals 20% Observability 18% Alerting 18% Instrumentation 16% Most questions layer two or three clues, not one A scenario, a config or query, and sometimes a second near-identical config to compare against it. Read the whole stem before choosing — the trap is usually in the clue you skimmed, not the one you read twice.
◆ Key idea

On a scenario-heavy paper, wrong answers usually aren't false in isolation — they're true statements that answer a slightly different question than the one asked. Before picking, ask yourself what specific claim each option is actually making, not just whether it sounds like something you've read before. That habit is worth more on this set than on Set 1.

Sit it like the real thing

☺ Like you're 10: Same rules as last time — no notes, one sitting, answer every question even the ones you're unsure of.

Nothing about exam conditions changes for a second paper. The PCA is delivered online and remote-proctored, closed-book, with no cluster and no documentation allowance — sit this the same way you sat Set 1: one uninterrupted block, every other tab closed, an answer committed to every item before you check it. If you're taking both papers back to back, take a real break between them; a scenario-heavy set read while tired is where careless misreads happen, and those misreads teach you the wrong lesson about what you actually know.

⚠ Exam details change — the official page is the authority

What's safe to state structurally: the PCA is a CNCF/Linux Foundation associate-level, knowledge-based multiple-choice exam — not hands-on like the five core Kubernetes exams in the Kubernetes course or a performance-based exam like the CNPE — delivered online under remote proctoring, with no formal prerequisite. Two numbers the Linux Foundation does publish and this paper is calibrated against: a 90-minute duration, and 75% or above to pass (the Linux Foundation's Multiple Choice Exam FAQ states this pass mark applies to every LF multiple-choice exam). The real question count is not published, and this paper's size of forty-five exists only to match Set 1 for comparability, not to claim a real number. Price, retake terms, eligibility window and certification validity are all revised over time too. Confirm everything on the official Linux Foundation PCA page and the CNCF certification page before you register or pay — this page is a study aid, not a substitute for reading them.

The paper — 45 questions across three blocks

☺ Like you're 10: Same three blocks as before — read the whole little story in each question before you pick, because the important detail is rarely the first thing mentioned.

Each question names its domain in parentheses; a couple are marked (Select TWO) and need both correct letters for full credit. Where a question compares two approaches, read both all the way through before deciding — several of the wrong options here are correct-sounding statements about the wrong one of the two.

Block 1 — Q1–15

Q1 (PromQL). A platform team wants to attach the owning team's name to every raw per-pod request-rate series, without first collapsing pods down to one series per namespace. They write:
rate(http_requests_total{namespace!=""}[5m]) * on(namespace) group_left(team) kube_namespace_labels
Every namespace has anywhere from one to dozens of pods, but exactly one kube_namespace_labels series. Why does this query need group_left, rather than just on(namespace) alone?

Check the answer

A. Without group_left, PromQL raises "many-to-one matching must be explicit" precisely because many left-hand series sharing a namespace would otherwise silently collapse onto one right-hand row. group_left(team) both grants that permission and pulls the extra team label from the "one" side onto every matched result.

Q2 (Prometheus Fundamentals). A team sets scrape_interval: 10s and scrape_timeout: 15s for a slow legacy endpoint in one scrape config, and Prometheus refuses to start with a configuration error. What's wrong?

Check the answer

B. Prometheus validates that scrape_timeout cannot exceed scrape_interval, because a scrape permitted to run longer than the interval between scrapes would routinely overlap the next one. The fix here is either raising scrape_interval or lowering scrape_timeout, not removing either setting.

Q3 (Observability Concepts). A checkout-service dashboard shows four panels: requests per second, an error-rate percentage, p50/p95/p99 latency, and CPU/memory/queue-depth against capacity. Which mapping to the four "golden signals" is correct?

Check the answer

A. The four golden signals map cleanly here: traffic is volume (requests/sec), latency is how long requests take (the percentiles), errors is the failure rate, and saturation is how full the system's resources are (CPU/memory/queue depth against their limits) — four genuinely distinct questions, not restatements of each other.

Q4 (Alerting & Dashboarding). A team's Alertmanager route sends everything to a default "platform-oncall" receiver, with a child route sending severity="page" alerts to PagerDuty. They also want every page-severity alert to land in a shared "#incidents" Slack channel in addition to PagerDuty, not instead of it. What config detail makes that happen?

Check the answer

B. Routing normally stops at the first matching route. continue: true is the specific setting that tells Alertmanager to keep walking the tree after a match, which is how one alert ends up notifying more than one receiver — here, both PagerDuty and Slack.

Q5 (Instrumentation and Exporters). A team needs metrics from a 15-year-old commercial database with no source access and no way to embed a Prometheus client library inside it. What's the correct category of tool, and how does it conceptually differ from instrumenting a service you own?

Check the answer

A. This is precisely what an exporter is for — a small, separate translator process, not code linked into the target system. The Pushgateway is a narrow exception for short-lived batch jobs pushing their own results in, not a general adapter for long-running external systems like a database.

Q6 (PromQL). An engineer wants to compare this Friday's error rate to the same time last Friday, for anomaly detection:
sum(rate(http_requests_total{code=~"5.."}[5m])) / sum(rate(http_requests_total{code=~"5.."}[5m] offset 7d))
What does offset 7d achieve here, and is it placed correctly?

Check the answer

B. offset attaches directly to a vector selector — instant or range — and shifts when that selector is evaluated. Placed right after [5m], it correctly pulls the same 5-minute window from 7 days earlier, which is exactly the shape a week-over-week comparison needs.

Q7 (Prometheus Fundamentals). A target exposes its own instance label in its metrics payload, meaningful to the application and distinct from the automatic instance label Prometheus derives from the scrape target's address. The team is confused why their custom value keeps getting overwritten. Which setting controls this, and what's the default?

Check the answer

A. With the default honor_labels: false, Prometheus's own target labels take precedence and any conflicting label from the target is preserved under an exported_ prefix instead of being dropped. Setting honor_labels: true flips that precedence so the scraped value wins outright.

Q8 (Observability Concepts). A team writes their SLI as sum(rate(http_requests_total{code!~"5.."}[5m])) / sum(rate(http_requests_total[5m])), sets an internal SLO of 99.5% over a rolling 30-day window, and separately signs a customer contract at 99.0% with financial penalties for any shortfall. Which of the three is the SLI, precisely?

Check the answer

C. The SLI is the indicator — the measurement mechanism itself, here the success-ratio query. The 99.5% is the SLO (the internal target set against that indicator) and the 99.0% is the SLA (the external, contractual promise). Neither percentage is the SLI; they're targets applied to it.

Q9 (Alerting & Dashboarding). A route has group_wait: 30s, group_interval: 5m, repeat_interval: 4h. Three related alerts fire in the same new group: at T+0, T+10s, and T+35s. Roughly what happens?

Check the answer

A. group_wait governs the initial batching delay for a brand-new group; group_interval governs how often a still-active group's later-arriving members get flushed; repeat_interval governs how often an unchanged, still-firing group gets re-notified. All three do genuinely different jobs.

Q10 (Instrumentation and Exporters). Two label designs for an HTTP metric are proposed: raw numeric status codes (200, 201, 301, 404, 500, 503…) versus a collapsed class (2xx, 3xx, 4xx, 5xx). Both are technically bounded — HTTP codes are a small, finite set either way. Which is the more common safe default, and why?

Check the answer

C. Both designs are cardinality-safe in principle, so this isn't really a cardinality question — it's a "what does the consumer actually need" question, and the class-level label wins by default because success/client-error/server-error covers most decisions without the churn of tracking every individual code.

Q11 (PromQL). A nightly backup job pushes a success counter through the Pushgateway only when it completes; if it crashes early, nothing is pushed at all — the series is entirely absent, not zero. The team wants to page if the expected metric hasn't appeared in the last 25 hours. Which expression correctly captures "this metric produced no series at all in the last 25 hours"?

Check the answer

B. absent_over_time() is purpose-built for exactly this: it returns a 1 when its range vector had no samples at all in the window, and no result otherwise. Options C and D fail the same way — increase() and rate() on a range with zero samples return no data, not 0, so neither ever crosses the stated threshold.

Q12 (Prometheus Fundamentals). A Prometheus pod is OOM-killed mid-write. On restart, the operator worries the last few minutes of samples — held in memory but not yet flushed to a persisted block — were lost. What protects against this, and what exactly does it protect?

Check the answer

A. The WAL is exactly this safety net: samples are durably appended to it before they're only-in-memory, so a crash before the next block persists doesn't lose them — Prometheus replays the WAL on startup to rebuild what was lost from memory.

Q13 (Observability Concepts). A request enters through a gateway, then calls three downstream services in turn. Each service logs its own span, but engineers can't stitch one request's spans together in their tracing UI. What's the most likely missing mechanism?

Check the answer

B. Without a propagated trace ID, there's nothing linking the three services' spans together — each one is a valid, complete trace of exactly one hop, with no shared identifier for a tracing backend to stitch them into a single end-to-end view.

Q14 (Alerting & Dashboarding). When a cluster's ClusterDown alert fires, the team wants every ServiceUnreachable alert sharing the same cluster label suppressed entirely — not merely grouped, but not sent at all — for as long as ClusterDown is firing. Which config implements this, and what does it match on?

Check the answer

B. This is specifically what inhibit_rules is for: a source alert (the parent, ClusterDown) suppresses a target alert (the downstream symptom, ServiceUnreachable) once equal confirms they're the same incident. Grouping only bundles notifications together; it doesn't stop a group member from being sent.

Q15 (Instrumentation and Exporters). A histogram is named api_response_time_ms with bucket boundaries [10, 50, 100, 500, 1000], and observations are recorded in milliseconds. What convention does this violate, and what's the concrete downside beyond style?

Check the answer

A. The scrape itself works fine — this is a consumption problem, not a validity problem. Naming conventions exist so a query or dashboard written once, generically, behaves correctly against any metric that follows them; a deviation like this quietly breaks that assumption for whoever borrows a "seconds" query against it later.

Block 2 — Q16–30

Q16 (PromQL). An engineer wants the peak 5-minute request rate observed at any point over the last hour, sampled internally every 30 seconds:
max_over_time(rate(http_requests_total[5m])[1h:30s])
What is this subquery doing, and what does 1h:30s specifically mean?

Check the answer

B. The subquery syntax <instant_query>[<range>:<resolution>] re-runs the inner instant query repeatedly at the given resolution across the given range, turning it into a range vector an outer function like max_over_time can then reduce — exactly how "the peak of a smoothed rate" gets computed.

Q17 (Prometheus Fundamentals). An engineer notices Prometheus's data directory contains many small subdirectories with roughly 2-hour time ranges, which later merge into fewer, larger directories. What's happening?

Check the answer

A. Fresh data lands in small, immutable 2-hour blocks; compaction later merges neighboring blocks into larger ones on a schedule, which both shrinks the number of files a query has to touch and is the mechanism that eventually drops data older than the retention window.

Q18 (Observability Concepts). A latency histogram's p99 spikes on a dashboard, and the on-call engineer wants to jump directly from that specific spiky bucket to one slow trace that landed in it, instead of guessing which trace among thousands was the culprit. What's the purpose-built mechanism for this?

Check the answer

B. Exemplars are exactly this bridge between a metric and a trace: a sampled data point riding alongside an ordinary observation, carrying enough context (usually a trace ID) that a UI can link straight from a spike on a graph to the individual trace behind it.

Q19 (Alerting & Dashboarding). Alongside a fast, short-window burn-rate alert that pages immediately on a severe spike, a team also configures a second rule: a lower burn-rate threshold evaluated over a much longer window, routed to a ticket instead of a page. Why pair the two instead of relying on the fast one alone?

Check the answer

A. This is the multi-window, multi-burn-rate pattern: a fast window catches the incident that would blow the whole budget quickly and deserves a page now, while a slow window catches the quiet leak a fast window can't see, routed more gently since it isn't yet an emergency.

Q20 (Instrumentation and Exporters). A fixed fleet of exactly 3 payment-gateway instances has a contractual, per-instance latency SLA requiring an exact client-computed quantile, with no need to ever combine or compare quantiles across the 3 instances. Is a Summary metric type actually appropriate here, or always the wrong choice compared to a Histogram?

Check the answer

B. The exam's usual guidance to prefer Histogram is really a warning about the aggregation trade-off, not a blanket ban on Summary. When the scenario was never going to aggregate across instances — a small, fixed, individually-tracked fleet with a per-instance contractual number — that specific downside doesn't apply.

Q21 (PromQL). A disk-usage gauge is trending upward. The team wants to know if it will breach 90% within the next 4 hours, based on the last 6 hours of trend, so they can page before it's full rather than after:
predict_linear(node_filesystem_avail_bytes{mountpoint="/data"}[6h], 4*3600) < 0
What does predict_linear(v, t) compute, and why does this expression correctly predict a disk-full event?

Check the answer

A. predict_linear fits a linear regression to the range vector and projects it forward by t seconds. It's the standard tool for gauges specifically — disk space, queue depth, anything trending — and predicting a negative available-bytes value is exactly how you phrase "this will run out."

Q22 (Prometheus Fundamentals). Two independent Prometheus servers, one per data center, both scrape a service named "checkout" and both remote_write into the same long-term storage backend. Why does setting external_labels: { region: "us-east" } and { region: "eu-west" } respectively matter here?

Check the answer

A. Locally, each server's own data doesn't need external_labels to make sense of itself. The moment that data leaves the server — federated out or remote-written into a shared backend alongside another server's identically-named series — external_labels is what keeps the two data centers from being indistinguishable downstream.

Q23 (Observability Concepts). Two proposed label designs for the same metric are debated: Design 1 adds region and env (a handful of fixed values each); Design 2 adds session_id (effectively unique per user session). Which correctly distinguishes dimensionality from cardinality and applies it to both designs?

Check the answer

A. This is exactly the distinction the cardinality-explosion warnings are getting at: counting label names tells you nothing about the danger, because the danger lives in how many distinct values a label can actually take — bounded and small for Design 1, effectively unbounded for Design 2.

Q24 (Alerting & Dashboarding). A dashboard has a $namespace template variable driving a $pod variable's own query, label_values(kube_pod_info{namespace="$namespace"}, pod), so picking a namespace narrows the pod dropdown to just that namespace's pods. What's this pattern called, and what does it enable?

Check the answer

A. Chaining is the whole point of template variables at scale: rather than one flat, unfiltered dropdown, each variable's query can reference an already-selected variable, progressively narrowing the dashboard's scope exactly the way $namespace narrows $pod here.

Q25 (Instrumentation and Exporters). A service registers a Counter with labels ["method", "code"] that vary on every .inc() call, and also wants every metric it exposes to carry a fixed version="2.4.1" label representing the deployed build, set once at process startup and never changing for that process's lifetime. How should the fixed version label be implemented, as distinct from method/code?

Check the answer

A. A const label is set once at registration and never varies again, exactly matching a build-time version string. Repeating it on every .inc() call like method/code would technically work but is redundant and a maintenance risk if the string ever needs to be updated in more than one place.

Q26 (PromQL). An engineer tries kube_pod_info * on(namespace) kube_namespace_labels without group_left, and Prometheus errors with something like "multiple matches for labels: many-to-one matching must be explicit." What's actually going wrong?

Check the answer

A. This is the identical mechanism as Q1, from the other side: many per-pod series legitimately sharing one namespace value trying to match a single namespace-level row is many-to-one, and PromQL insists that be spelled out explicitly rather than guessed at.

Q27 (Prometheus Fundamentals). Within one rule group, a recording rule computing job:errors:ratio_rate5m is defined immediately before an alerting rule whose expr references that exact recording rule's output name. Is this safe, and why?

Check the answer

A. Sequential-within-a-group is exactly the guarantee that makes "recording rule feeds an alerting rule" a safe, common pattern — as long as they're in the same group and written in that order. It's across different groups that ordering isn't guaranteed, which is the real footgun to watch for.

Q28 (Observability Concepts). Team A logs "user 4471 checkout failed: card declined" as free text; Team B logs {"user_id": 4471, "event": "checkout_failed", "reason": "card_declined"} as JSON. What's the practical, observability-relevant advantage of Team B's approach?

Check the answer

B. The real payoff is queryability: a structured field like reason="card_declined" can be filtered, grouped and counted directly, where a free-text line needs a regex that breaks the moment the wording changes even slightly.

Q29 (Alerting & Dashboarding). An alerting rule with for: 1m against a noisy, spiky metric fires and resolves repeatedly every few minutes, and the on-call engineer starts ignoring the notifications. Which change most directly addresses the flapping itself, as opposed to just muting the noise?

Check the answer

B. A never-expiring silence and a different receiver both hide the symptom without touching the cause; repeat_interval only affects how often an already firing alert re-notifies. Only lengthening for: or smoothing the expression changes whether the alert flaps in the first place.

Q30 (Instrumentation and Exporters). A Python web app runs under gunicorn with 8 worker processes, each importing the same Prometheus client library and registering the same Counter. Scraping /metrics returns numbers far lower than expected, as if only one worker's data is ever reported. What's the most likely cause and the standard fix?

Check the answer

B. This is a well-known multiprocess gotcha specifically because each worker process gets its own registry by default. Multiprocess mode exists precisely to solve it, aggregating every worker's numbers rather than reporting whichever one happened to answer the scrape.

Block 3 — Q31–45

Q31 (PromQL). An engineer is debugging a feature-flag gauge that toggles between 0 and 1 whenever a flag is flipped (no reset semantics at all), and separately a counter that occasionally resets to 0 on pod restarts. They want to count how many times the flag flipped in the last day, and separately how many times the counter restarted in the last day. Which functions correctly pair with which metric?

Check the answer

B. changes() is the general-purpose one — any value change counts, on any series. resets() is narrower and specific to counters, counting only drops in value, which is exactly the restart signature the counter scenario needs.

Q32 (Prometheus Fundamentals). A platform wants a small, central "global" Prometheus that aggregates a handful of pre-computed, low-cardinality recording-rule results — one number per region — from a dozen regional servers, without ingesting all their raw, high-cardinality data. Which mechanism is purpose-built for this, and what's its key limitation compared to full remote-write/long-term storage?

Check the answer

A. Federation is a narrow, deliberate tool: pull a small, chosen slice of already-summarized data upward into a global view. It's the wrong tool for full-fidelity, whole-fleet long-term storage — that's what remote-write into Thanos, Mimir or Cortex is for.

Q33 (Observability Concepts). A service has a 99.9% monthly SLO — an error budget of roughly 43 minutes of allowed downtime for the month. At 2am, an alert fires because the current error rate, if sustained, would exhaust the entire monthly budget within the next hour. What alerting concept is this, and why is it usually paired with a second, slower-burning threshold?

Check the answer

A. The urgency of a fast burn-rate alert comes from the math, not the raw error rate: at this pace, the entire month's allowance is gone within the hour, which is exactly the kind of thing worth an immediate page — while the slow-window companion alert exists to catch a leak too gradual to ever trip this one.

Q34 (Alerting & Dashboarding). A planned 2-hour database maintenance window will predictably trip several latency and error-rate alerts on the affected service. The team wants those specific alerts muted for exactly that window, without disabling the alerting rules themselves, so the rules resume firing normally the moment the window ends if the underlying issue is still present. What's the correct mechanism, and how does it differ from commenting out the rule for two hours?

Check the answer

A. A silence mutes notifications without touching rule evaluation at all — the rule keeps running underneath, so state is preserved and nothing needs a config reload on either end of the window. Commenting the rule out requires exactly that reload twice and loses the rule's live state for the whole window.

Q35 (Instrumentation and Exporters). A nightly cron job runs a certificate-expiry check and needs its result (days until expiry, as a gauge) available to Prometheus, but it's a short one-shot script, not a long-running process that could expose its own /metrics endpoint. What's the standard node_exporter-based pattern for this, distinct from both a client-library integration and the Pushgateway?

Check the answer

A. The textfile collector is the standard node_exporter answer for host-level, cron-style facts specifically: drop a file, let node_exporter pick it up on its next scrape, no daemon or push endpoint needed. The Pushgateway is a plausible-sounding alternative but is aimed more at job-completion metrics from applications, not host facts like this.

Q36 (PromQL). A recording rule needs a clean 0-or-1 value for every instance's latency-over-threshold state — not a filtered vector that silently drops the healthy instances — so a dashboard heatmap can color every instance, including the healthy ones. Which comparison correctly produces a 0-or-1 value for every input series, rather than filtering some out?

Check the answer

B. Without bool, a comparison operator filters — keeping only series where the condition is true, with their original value, and dropping the rest. The bool modifier changes that behavior so every input series survives, its value replaced with a plain 1 or 0. clamp_max caps a value; it doesn't produce a boolean at all.

Q37 (Prometheus Fundamentals). A team using file-based service discovery notices every target in their SD file only carries custom meta-labels like __meta_filepath and a top-level targets: ["10.0.4.12:9100"] entry, with no explicit "address" field set anywhere in relabel_configs — yet Prometheus correctly scrapes 10.0.4.12:9100. What's actually determining the scrape address?

Check the answer

A. Every target's scrape address really is just the current value of the __address__ label, seeded by the discovery mechanism and freely rewritable through relabeling — a very common pattern is rewriting it to change the scraped port, which directly contradicts option C.

Q38 (Observability Concepts). A tracing pipeline is expensive at full volume, so a team samples 1% of traces. One engineer proposes deciding whether to keep a trace the moment its first span is created, before the outcome is known; another proposes buffering the whole trace and deciding after it completes, so error and slow traces can always be kept regardless of the sampling rate. Which is head-based and which is tail-based, and what's the trade-off?

Check the answer

A. The names describe exactly when the decision happens — at the "head" (the first span, no outcome known yet) or the "tail" (after the whole trace completes, outcome fully known). Tail-based costs more to buffer but is the only way to guarantee errors and slow traces aren't just as likely to be dropped as everything else.

Q39 (Alerting & Dashboarding). A Grafana stat panel for up{job="checkout"} shows "No data" during an incident. One engineer insists that must mean the value is 0 (down); another points out those aren't the same thing. Who's right, and why does the distinction matter operationally?

Check the answer

B. up==0 means Prometheus reached the target and the scrape itself failed — a target-side problem. "No data" means the series never existed for that query at all, which points somewhere entirely different: service discovery, Prometheus's own reachability, or the query's label matchers. Treating them as the same fact sends the responder to the wrong layer.

Q40 (PromQL). A team wants the top 5 CPU-heaviest pods, but only among pods already above a 0.5-core threshold — so if fewer than 5 pods clear the threshold, fewer than 5 should appear, with no padding from idle pods. Which expression is correct?

Check the answer

A. and keeps left-hand series that also have a matching series on the right, correctly filtering the true top-5 down to only the ones clearing 0.5 cores. Option B filters below-threshold pods out first, then ranks the survivors — which can silently promote a pod that was never in the real fleet-wide top 5. Option D multiplies every top-5 entry by 1 or 0 instead of removing it, so a sub-threshold pod stays in the result at a value of 0 rather than being dropped, which isn't what was asked for.

Q41 (Prometheus Fundamentals). A team wants their on-prem Prometheus servers to ship data into a centralized, long-term, horizontally-scalable backend without every downstream consumer needing to scrape each Prometheus individually. How does this fit with Prometheus's core pull model?

Check the answer

A. Prometheus's own scraping stays pull-based and unaffected; remote_write is a separate, additional pipe that pushes already-ingested samples onward. It answers a genuinely different question than the Pushgateway, which exists so short-lived jobs can get data into a pull-based Prometheus in the first place.

Q42 (PromQL, Select TWO). A target's process crashes at 10:00:00; its last successful scrape was at 09:59:45. A dashboard panel graphing that series keeps showing the last known value, unchanged, until roughly 10:04:45 — five minutes after the crash — then the line vanishes entirely rather than dropping to zero. Which TWO statements correctly explain this?

Check the answer

A and B. Both are genuine Prometheus mechanisms: the 5-minute staleness lookback explains why the last value keeps answering queries for a while, and the explicit stale marker explains why the series then disappears outright rather than reading as zero. C misattributes the behavior to Grafana; D and E both misdescribe how Prometheus actually treats a missing series — it's never silently zero, and nothing is deleted from the TSDB.

Q43 (PromQL). An exporter exposes container_name values like web-7f9c8d-4kxvz (a pod-suffixed name), and the team wants a clean app label by stripping the trailing random suffix so they can join against a deployment-level metric:
label_replace(container_cpu_usage_seconds_total, "app", "$1", "container_name", "(.+)-[a-z0-9]+-[a-z0-9]+")
What does label_replace(v, dst, replacement, src, regex) do, and is this call shaped correctly?

Check the answer

B. label_replace sets a destination label from a regex match against a source label — leaving the source untouched — and if dst and src happen to be the same name, it overwrites in place. It doesn't discard anything on the source side, and the regex is required, not optional.

Q44 (PromQL). An engineer wants to spot suspiciously many nodes reporting the exact same, possibly-stuck value for node_load1 across a large fleet:
count_values("load_value", node_load1)
What does this actually compute?

Check the answer

A. count_values aggregates by the sample value, not by a label — grouping series that currently report the same number together and counting how many there are. That's a genuinely different question from count(), which just counts series regardless of what value each one holds.

Q45 (PromQL). A junior engineer, trying to get p95 latency, writes quantile(0.95, http_request_duration_seconds) directly against a metric name — not histogram bucket series — and is confused why it doesn't behave like histogram_quantile(). What's the actual difference between the two?

Check the answer

B. This is the classic mix-up: quantile() aggregates across series at one moment, the same family as sum()/avg()/max(). histogram_quantile() is a completely different tool that interpolates a percentile within one histogram's _bucket series. Neither is a drop-in replacement for the other, and only histogram_quantile() cares about le at all.

Score yourself

☺ Like you're 10: Same scoring method as Set 1 — count correct answers out of forty-five, compare to 75%, then see which domain cost you the most.

The Linux Foundation's Multiple Choice Exam FAQ states that a score of 75% or above is required to pass any LF multiple-choice exam, and the PCA is one. Because this paper shares Set 1's exact domain split, put the two domain-by-domain scores side by side — a domain that dropped noticeably between the two papers is a real signal: you know the definitions, but the same idea slips under a layered scenario.

DomainQuestions in this paperYour scoreIf you're under two-thirds, go here
🐘 PromQLQ1, 6, 11, 16, 21, 26, 31, 36, 40, 42, 43, 44, 45/13PCA — the exam
🦉 Prometheus FundamentalsQ2, 7, 12, 17, 22, 27, 32, 37, 41/9Prometheus
🐿️ Observability ConceptsQ3, 8, 13, 18, 23, 28, 33, 38/8The OpenTelemetry data model
🐢 Alerting & DashboardingQ4, 9, 14, 19, 24, 29, 34, 39/8Grafana
🦫 Instrumentation and ExportersQ5, 10, 15, 20, 25, 30, 35/7OpenTelemetry Collector
Total45 questions/4575% (34/45) to clear comfortably

If Set 2 scored lower than Set 1 in the same domain, don't treat that as a worse result — treat it as more accurate information. Set 1 tells you what you can recall; Set 2 tells you what you can actually apply when a question doesn't hand you the concept by name. A domain that held steady between the two papers is genuinely solid. A domain that dropped is where a second read of the linked page, done slowly this time, pays off more than another timed rep.

Where each domain is taught

☺ Like you're 10: Same handful of pages as before — every scenario above still traces back to one of them.

Nothing in this paper reaches beyond what Set 1 already pointed you toward. The scenarios are new; the underlying material they're testing isn't.

The wider revision kit still applies: flashcards for the vocabulary, the self-check quiz for mixed recall, the glossary for anything a question assumed you already knew, and the PCA study plan for sequencing. For shorter, module-specific reps, the PCA practice bank splits the same ground into focused drills.

🎬 At Mission Control
🐰

Remy: Finished! Forty-one out of forty-five, and Set 1 was thirty-nine — I'm getting better!

🐘

Ellie: Better on the total, sure. Which domain still cost you, Remy — same one as last time, or a different one this time?

🐰

Remy: ...PromQL, actually. I picked the topk-then-filter version instead of the and version on the top-5-above-threshold question.

🦊

Foxy: Wait, aren't those the same five pods either way?

🐢

Timmy: Not always. Filter-then-rank can promote a pod that was never really in the fleet-wide top five, just because the real top five got trimmed down first. Order matters.

👺

Gizmo: Easy fix — skip group_left entirely and let Prometheus figure out the join on its own. Less typing!

🐘

Ellie: Prometheus won't figure it out, Gizmo — it'll throw a many-to-one matching error and refuse to run at all. That's not a shortcut, that's a query that never executes.

🐰

Remy: So Set 1 taught me the vocabulary, and Set 2 just taught me I don't actually know it as well as I thought I did.

🐘

Ellie: That's the whole reason there are two papers, Remy. Now go read the ordering explanation once more, slowly, and it'll stick.

🐢 Timmy's checkpoint

1. Why does kube_pod_info * on(namespace) kube_namespace_labels need group_left, structurally? 2. What's the difference between changes() and resets(), and which metric type is each meant for? 3. Why does an and-based top-5-above-threshold query behave differently from filtering inside topk()'s own argument? 4. What's the practical difference between a "No data" panel state and a literal up==0? 5. Why is a fast, short-window burn-rate alert usually paired with a slower, longer-window one rather than used alone? 6. What does honor_labels: true change, and what's the default behavior instead? 7. Structurally, why can a Summary metric type still be the right choice even though the exam generally favors Histogram for latency?

Check your answers
  1. The left side has many series sharing one namespace value, all trying to match the single right-side row for that namespace — a many-to-one match PromQL refuses to resolve implicitly. group_left both permits it and copies extra labels from the "one" side onto the result.
  2. changes() counts any value change on any series, gauge or counter — right for the flag. resets() counts counter-specific drops in value — right for the restarting counter.
  3. Filtering first (inside topk()) ranks only the already-filtered survivors, which can promote a pod that was never in the true fleet-wide top 5. Using and ranks the whole fleet first, then intersects with the threshold — a genuinely different result set.
  4. "No data" means the query returned no series at all — the target may have vanished from service discovery, or Prometheus can't be reached. up==0 means Prometheus DID reach the target and got an explicit scrape failure. They point to different layers of the stack.
  5. A fast window reacts quickly to a severe spike but can flap on noise and misses a slow, steady leak; a slow window smooths noise and catches the leak but reacts too slowly to justify paging alone. Together they cover both failure shapes.
  6. honor_labels: true lets a target's own scraped label win over Prometheus's automatically-added target label on conflict. The default, false, does the opposite — Prometheus's label wins and the conflicting scraped one is renamed with an exported_ prefix.
  7. Summary's real downside is that its client-side quantiles can't be aggregated across instances. In a scenario that was never going to aggregate across instances — a small, fixed fleet needing an exact per-instance number — that downside simply doesn't apply.

That's the full sitting. If a domain dropped compared to Set 1, that's the one worth a slow, deliberate reread rather than another timed run — this paper was built to surface exactly that gap.

⏱️ The two PCA papers

Set 1 · Set 2 (you are here). Both are forty-five questions on the same 13 · 9 · 8 · 8 · 7 domain split, so the scores are directly comparable — Set 1 leans on definitions and single-function PromQL reads, Set 2 leans harder into layered, multi-clue traps. See the PCA study plan for where each paper fits against your remaining prep time, the practice-question bank for shorter drills in between, and PCA — the exam for the full domain writeup and official logistics.