CCloudSuccessTechworld with Randy

SRE Fundamentals

SLI vs SLO vs SLA
SRE Fundamentals
R

Okay, warm-up. Explain SLI, SLO and SLA to me like I'm a new product manager who just joined the team.

A

Sure. An SLI is the thing you measure. A service level indicator. For checkout, that might be the percentage of payment requests that succeed in under five hundred milliseconds.

A

The SLO is the target we set for that number. Say, ninety-nine point nine percent of requests succeed, measured over thirty days. That's internal. It's the line the engineering team holds itself to.

A

And the SLA is the promise we make to customers, usually with money attached. If we break it, we pay credits. So the SLA is always looser than the SLO. You want to find out you're in trouble long before the lawyers do.

99.9% over 30 days = ?
SRE Fundamentals
R

I like that last line. Okay. Ninety-nine point nine percent over thirty days. How much downtime is that?

A

Thirty days is forty-three thousand two hundred minutes. Point one percent of that is forty-three point two minutes. So roughly forty-three minutes of total failure a month. That's your error budget.

R

And what do you do with an error budget?

A

You spend it. That's the part people miss. If we've barely touched it, we can ship faster, run riskier experiments, do that migration. If we've burned through it, we slow down. Feature releases pause, and the team spends its time on reliability until the budget recovers.

R

Who decides that? Who actually stops the releases?

A

It should be agreed before anything breaks. An error budget policy, signed off by engineering and product. Otherwise every freeze turns into an argument at the worst possible moment.

R

That's a strong answer. The policy point is what separates someone who read about SRE from someone who's lived it.

What is toil?
SRE Fundamentals
R

Next. What's toil? And give me an example from a real team.

A

Toil is work that's manual, repetitive, can be automated, and doesn't make the system better over time. And it grows as the service grows. The classic one is a person restarting a stuck job every morning because it leaks memory.

A

Google's SRE book suggests keeping toil under fifty percent of an SRE's time. If you're above that, you're an operator, not an engineer. My move is to track it. Tickets tagged as toil, so you can show the trend and justify the automation work.

R

Good. Measuring it is the part most candidates skip.

3 a.m. · CPU at 95% · wake up?
SRE Fundamentals
R

Last one in this round, and it's a trap. It's three a.m. An alert fires. CPU on one node is at ninety-five percent. Do you wake up?

A

Honestly? That alert shouldn't wake anyone up. CPU at ninety-five percent is a cause, not a symptom. Customers don't feel CPU. They feel errors and slow pages.

A

So I'd page on symptoms. Error rate, latency, the SLO burning too fast. And keep CPU as a dashboard signal or a ticket for the morning. If high CPU actually hurts users, the symptom alert will catch it.

R

You dodged the trap. A lot of people say, yes, of course I'd wake up, it's ninety-five percent!

A

I've been that person. You get paged for a batch job that's supposed to use all the CPU. Twice. Then you stop trusting the pager.

R

And a pager nobody trusts is worse than no pager. Five out of five.

Live Incident

Why exit code 137?
Live Incident
R

Why one thirty-seven? Interviewers love that one.

A

One twenty-eight plus nine. Nine is SIGKILL. When a process dies from a signal, the exit code is one twenty-eight plus the signal number. And SIGKILL can't be caught, so the app never gets to log anything. It just disappears.

R

Nice. Let's see what it said before it died.

A

It's warming an eighty megabyte product cache, loads forty, and then... nothing. And the memory limit on this deployment is sixty-four megabytes. So version two can never start. It's not flaky. It's mathematically dead.

R

Mathematically dead. I'm stealing that.

R

Okay. Customers are still failing. What do you do?

A

Roll back now, fix forward later. Undo the deployment to the previous revision.

R

Rolled back. Successfully rolled out.

A

Three version-one pods running, and the crashing pod is terminating. Let's run the test again.

A

Wait. Still forty out of forty failing.

R

Yeah. This is my favourite part of the interview.

R

The rollback worked. The pods are healthy. Customers are still down. Talk to me.

A

Okay. Healthy pods but failing requests means the traffic isn't reaching them. So I stop looking at the pods and follow the request. Storefront calls the checkout service. Does the service have any endpoints?

A

None. The service is pointing at nothing. So the selector doesn't match the pods. Show me the service with its selector.

A

The selector is app checkout, version two. And we just rolled every pod back to version one.

A

Yep. Every pod is labelled version one. So the release pipeline didn't just change the deployment. It also patched the service to point at version two. When we rolled back the deployment, the service didn't roll back with it.

R

That's it. That's the bug. A rollback only rolls back the thing you rolled back.

A

So the fix is to stop the service caring about version at all. It should select app checkout. Versioning belongs to the deployment, not the service.

A

Three endpoints. Now the test.

R

Forty for forty.

A

Okay. We're back.

R

Before the score, one thing you didn't do. The second you saw every request failing, who did you tell?

A

...No one. I went straight into the terminal.

R

And that's the difference between mid-level and senior. In a real incident someone declares it, someone runs comms, and someone fixes. Even if that's all you, you post a status update first. Customer support is getting yelled at right now and they have no idea why.

A

That's fair. Declare, post a status, then debug. And update every fifteen to thirty minutes even if the update is, still investigating.

R

Four out of five on triage. The debugging was excellent. Following the request after the rollback is exactly right. You lose a point on comms.

Kubernetes Rapid Fire

Requests vs limits
Kubernetes Rapid Fire
R

Requests versus limits. Go.

A

Requests are what the scheduler reserves for you. Limits are the ceiling. Go over the memory limit, you get OOMKilled, like we just saw. Go over a CPU limit, you don't die, you get throttled. Which is sneaky, because the pod looks healthy and it's just slow.

R

And QoS classes?

A

Three of them. Guaranteed, when requests equal limits for everything. Burstable, when you set requests but they're not equal to limits. BestEffort, when you set nothing. When a node runs out of memory, BestEffort pods get evicted first, then Burstable. Our checkout pods should be Burstable right now.

A

Burstable. Memory request forty-eight, limit one sixty. If checkout was critical enough, I'd make it Guaranteed.

How does service DNS work?
Kubernetes Rapid Fire
R

Next. A pod calls checkout dot shop. How does that name become an IP?

A

CoreDNS. Every service gets a DNS name, service dot namespace dot svc dot cluster dot local, and it resolves to the service's cluster IP. Then kube-proxy rules on the node send that traffic to one of the healthy pod endpoints. Let's look from inside the storefront pod.

A

Wait. Those aren't cluster IPs. That's the public internet. Dot shop is a real top-level domain, and this nslookup sent the name exactly as typed. Our app still works because the normal resolver tries the search domains first. Let's look at them.

A

Search domains, starting with shop dot svc dot cluster dot local. And ndots five. That ndots line is a famous performance trap. Any name with fewer than five dots gets tried against every search domain first. So calling an external API like api dot stripe dot com can fire off several DNS lookups before the real one.

R

Ooh. Bonus point for ndots. Most people have never looked at that file.

Draining a node: what can go wrong?
Kubernetes Rapid Fire
R

Okay. I need to patch a worker node tonight. I'm going to drain it. Anything that could go wrong?

A

A PodDisruptionBudget can block it. That's the point of a PDB. It says how many pods of an app are allowed to be down during voluntary disruptions, like drains and upgrades. If someone sets max unavailable to zero, the drain can never finish.

R

Funny you say that.

A

There it is. Cannot evict pod, as it would violate the pod's disruption budget. The drain is stuck, and the node's already cordoned, so nothing new lands on it either.

R

So what do you do? It's two a.m. and the patch window is closing.

A

I don't delete the PDB on my own. It's there for a reason. I'd talk to the owning team, and the fix is a sane budget, like max unavailable one, with enough replicas that losing one is fine. Max unavailable zero isn't safety. It just means you can never patch.

R

Correct. Last rapid fire. A pod's stuck in ImagePullBackOff.

A

Failed to pull image. It can't even resolve docker dot io, library, P-Y-H-T-O-N. Look at the name. It's a typo. Otherwise I'd check registry credentials, the image pull secret, and whether the tag exists. But first, always read the event. It usually tells you.

R

Pyhton. I have done that in production. Four out of five for the round. I'd have liked QoS tied to eviction order without me asking, but ndots saved you.

Linux On-Call

Deleted file still using space?
Linux On-Call
R

Why would a deleted file still use space?

A

Because deleting a file only removes its name. The space isn't freed until the last process closes it. Classic cause: someone runs rm on a big log file, but the app is still writing to it. The file's gone from ls, but not from the disk. lsof plus L one lists open files with zero links.

A

There it is. A python process holding app dot log, marked deleted. Around four hundred and seventy megabytes.

R

Restart the process?

A

That works, but it's checkout. I don't want a restart if I can avoid it. You can truncate the file through the process's file descriptor in proc. That frees the space instantly and the process keeps running.

A

Back to almost nothing used. Then the real fix: proper log rotation, with copytruncate or a signal so the app reopens its log, and an alert at eighty percent disk instead of a hundred.

R

Five out of five. You'd be amazed how many people say, I'd just reboot it.

Observability

First 4 things to monitor?
Observability
R

Round three. You've got a brand-new service and zero monitoring. What are the first four things you measure?

A

The four golden signals. Latency, traffic, errors, and saturation.

A

Latency, but split by success and failure, because failed requests are often fast and they make your averages look great. Traffic, so you know the load. Errors, both explicit five hundreds and wrong answers. And saturation, how full the most constrained resource is.

R

You said averages. Why not just use the average latency?

A

Because averages hide pain. If ninety-nine requests take a hundred milliseconds and one takes ten seconds, the average looks fine. But that one user is having a terrible day. I'd look at the ninety-ninth percentile. And the users stuck in p99 are often your biggest customers, the ones with the most data.

What is burn rate?
Observability
R

Good. Now alerting on an SLO. What's a burn rate?

A

Burn rate is how fast you're spending the error budget compared to the steady pace. A burn rate of one means you'll use exactly the whole budget in thirty days. A burn rate of fourteen point four means you'd use the whole month's budget in about two days.

A

The approach from Google's SRE workbook is multi-window alerts. Page if you're burning at fourteen point four times over the last hour, and still burning over the last five minutes. That second window stops the alert from paging after the problem's already gone.

R

Can you write it? Roughly. In PromQL.

A

Roughly, the error ratio is the rate of five hundreds over the rate of all requests. Then you compare it to fourteen point four times the allowed error, which is point one percent. And you do the same for the five-minute window and require both.

R

That's a solid four. You'd want recording rules in real life so that query isn't recalculated every evaluation, but the idea is right.

Logs vs metrics vs traces
Observability
R

Quick one. Logs, metrics, traces. When do you reach for each?

A

Metrics tell you something's wrong. Traces tell you where. Logs tell you why. In the incident we just did, the error rate told us something was wrong, following the request found the broken hop, and the pod logs showed the cache warm-up dying.

R

I like that you tied it back to the incident. That's what a senior does.

System Design

Design checkout for 99.99%
System Design
R

System design. Product wants checkout at ninety-nine point nine nine percent. Four nines. Design it. And start with whether that's even possible.

A

First, four nines is about four minutes and twenty seconds of downtime a month. That's less than one bad deploy. So it changes how you ship, not just how you build.

A

Second, the math of dependencies. Checkout calls the payment provider, inventory, and the database. If each one is ninety-nine point nine, and checkout needs all of them, you multiply. Point nine nine nine cubed is about ninety-nine point seven. You can't be more reliable than the things you hard-depend on.

R

So how do you get around that?

A

You stop hard-depending on them. Inventory: if it's slow, take the order and reconcile after. The payment provider: two providers, with failover. And put the order on a durable queue, so if a downstream service is down, the order waits instead of failing.

A

Then redundancy. At least three availability zones, with enough capacity that losing one zone doesn't overload the other two. Database with synchronous replication across zones and automatic failover.

A

And every network call gets a timeout, retries with exponential backoff and jitter, and a circuit breaker. Without jitter, every client retries at the same moment and you get a thundering herd that keeps the service down.

Retrying a payment: the danger?
System Design
R

Retries on a payment. What's the danger?

A

Charging someone twice. If the request times out, you don't know if the charge happened. So every payment request carries an idempotency key. The provider sees the same key twice and returns the first result instead of charging again.

R

That's the answer that gets people hired at payment companies. Last thing. How do you deploy to a four-nines service?

A

Small and slow. Canary to one percent, watch the SLO burn rate automatically, then ramp. Auto-rollback if the burn rate spikes. Feature flags so you can turn off code without a deploy. And everything we learned today: no version in service selectors, and test the image under real limits.

R

Four out of five. I'd have wanted you to push back on product a little. Does checkout really need four nines, or does payment authorisation? Not every part of the flow needs the same target. That's a senior move.

On-Call & Behavioural

40 pages a week. Your first month?
On-Call & Behavioural
R

Last round. Your team is getting paged forty times a week. People are exhausted. You're the new SRE. What do you do in your first month?

A

First, I don't fix anything. I measure. Every page for the last month, grouped by alert. Usually it's five alerts causing eighty percent of the noise.

A

Then for each noisy alert, one of three things. Delete it if nobody acts on it. Turn it into a ticket if it can wait until morning. Or fix the real problem if it's a genuine symptom. And I'd make a rule: every page needs a runbook link, or it doesn't page.

R

And the humans?

A

A healthy rotation. At least six to eight people so you're not on call every other week. Time off after a bad night. And a weekly on-call handoff where we look at what paged and why. Burnout is a reliability problem too. Tired people make the three a.m. mistakes.

Tell me about a time you pushed back
On-Call & Behavioural
R

Last question. Tell me about a time you pushed back on a release.

A

We had a launch date fixed by marketing, and the load test showed the database falling over at about sixty percent of the expected traffic. I didn't just say no. I brought the graph, the error budget, and two options: launch to ten percent of users with a feature flag, or slip two days. They picked the flag. We fixed the query during the ramp, and nobody outside the team ever knew.

R

Data, options, and no drama. That's the answer. Four out of five. A senior answer would also say what you learned or changed afterwards, so it doesn't happen again.

Platform Fundamentals

Platform engineering vs DevOps?
Platform Fundamentals
R

Let's start with the one everyone gets. What is platform engineering, and how is it different from DevOps?

A

DevOps is a culture. Developers and operations owning software together, all the way to production. Platform engineering is one way to make that work at scale.

A

Instead of every team learning Kubernetes, Terraform, CI, secrets and monitoring from scratch, a platform team builds an internal product. Golden paths. A developer runs one command or fills one form, and gets a service with CI, deploys, dashboards and alerts already wired in. Done the right way by default.

R

You said product. Who's the customer?

A

The developers. And that changes everything. You do user research, you have a roadmap, you measure adoption. If nobody uses your platform, it doesn't matter how clever it is.

Mandatory platform?
Platform Fundamentals
R

Should it be mandatory? Force every team onto it?

A

I'd make it optional but obviously better. Paved road, not a cage. If teams are routing around the platform, that's feedback. Something in it is slower or harder than doing it yourself. The exceptions are guardrails, like security policies, which apply to everyone.

How do you measure a platform?
Platform Fundamentals
R

How do you know your platform is actually working? Give me numbers.

A

The four DORA metrics are a good start. Deployment frequency, lead time for changes, change failure rate, and time to restore. Then platform-specific ones. Time for a new engineer to get their first change into production. Time to create a new service. And adoption, what percentage of services are on the golden path.

A

And I'd ask developers directly, every quarter. A short survey. Numbers tell you what, people tell you why.

Does the platform need an SLO?
Platform Fundamentals
R

The platform itself. Does it need an SLO?

A

Yes. The platform is production for every team on it. If the CI system or Argo is down, nobody can ship, and during an incident nobody can ship the fix. So I'd set SLOs on the things developers feel. Pipeline success rate, time from merge to running in production, and cluster API availability. And the platform team goes on call for them, like any other—

R

Hold on. On call for CI? At three a.m.?

A

Not for everything. For the paths that block a production fix. If the deploy pipeline is down during an outage, that's a page. If a nightly report job fails, that's a ticket. Same rule as any service. Page on what hurts users, and here the users are engineers trying to fix production.

6 platform engineers, 80 requests
Platform Fundamentals
R

Good. Now here's a harder one. Your platform team is six people, and you've got eighty product engineers asking for things. Everyone's request is urgent. How do you decide what to build?

A

I'd look for the thing that's blocking the most people the most often. Usually it's not the shiny request. It's something boring, like environments taking two days to create, or every team writing its own CI pipeline. Fix the paved road for the common case first, and give the rare cases a documented way out. And say no out loud, with a reason, so people aren't waiting on a ticket that's never going to happen.

R

Five out of five. Saying no out loud is underrated. A platform team that says yes to everything ends up building nothing well.

Kubernetes Deep Dive

What happens on kubectl apply?
Kubernetes Deep Dive
R

Kubernetes. Classic question, but I want the deep version. What actually happens when I run kubectl apply on a deployment?

A

Kubectl reads the YAML, and talks to the API server over HTTPS. The API server authenticates you, checks RBAC, runs admission controllers, validates the object, and stores it in etcd.

R

Show me. I'll turn on verbose logging and you narrate.

A

Okay. First it fetches the OpenAPI schema, so kubectl knows what a deployment looks like. Then a GET for the deployment called hello. Four oh four, it doesn't exist yet. So it sends a POST, and gets two oh one, created. That's client-side apply. Check if it exists, then create or patch.

R

And after the two oh one? Nothing's running yet.

A

Right. At that point it's just a record in etcd. Then the controllers take over. The deployment controller sees a new deployment and creates a ReplicaSet. The ReplicaSet controller creates pods. The scheduler sees pods with no node and picks one. Then the kubelet on that node—

How does the controller find out?
Kubernetes Deep Dive
R

Stop there. How does the deployment controller know? Does the API server call it?

A

No. Nothing calls the controllers. They watch. Each controller has a long-running watch on the API server for the objects it cares about, and keeps a local cache. When something changes, it compares desired state with actual state and acts on the difference. That's the reconcile loop. And it's level-based, not event-based, so if a controller misses an event, the next resync still catches the difference.

How does the scheduler pick a node?
Kubernetes Deep Dive
R

Good. That reconcile loop is going to come up again. What does the scheduler actually do when it picks a node?

A

Two phases. Filtering, then scoring. Filtering removes nodes that can't run the pod. Not enough CPU or memory requested, a taint the pod doesn't tolerate, a node selector or affinity that doesn't match, a volume in a different zone. Then scoring ranks what's left, like spreading pods or packing them, depending on config. Highest score wins, and it writes the node name onto the pod. That's called binding.

R

You said requested. Not used?

A

Requested. The scheduler only looks at requests, never at real usage. A node can be at five percent real CPU and still be full, if the requests add up. That's why bad requests waste so much money.

A node runs out of real memory
Kubernetes Deep Dive
R

So if the scheduler only looks at requests, what happens when real usage runs out on a node? Memory, say.

A

Two different things can happen. If a container goes over its own memory limit, the kernel kills it. That's OOMKilled, exit code one three seven. But if the whole node runs low, the kubelet starts evicting pods before the kernel has to step in. It picks by quality of service. Best effort pods first, the ones with no requests at all. Then burstable pods using more than they asked for. Guaranteed pods last.

R

And how do I make a pod guaranteed?

A

Requests equal to limits, for both CPU and memory, on every container in the pod. That's why critical system pods often look like that.

6 replicas across 3 zones, evenly
Kubernetes Deep Dive
R

Okay. Spreading. I want six replicas of a cart service across three zones, evenly. How?

A

Topology spread constraints. Topology key is the zone label, max skew one, and when unsatisfiable, do not schedule. Max skew one means the difference between the busiest zone and the emptiest zone can't be more than one pod.

R

Let's try it. This cluster has three workers labeled as three zones.

A

Two, two and two. Perfect.

R

Why did you pick do not schedule over schedule anyway? What's the trade-off?

A

Do not schedule is strict. If a zone is down, new pods stay pending rather than piling into the surviving zones. That protects your spread, but it can block a rollout. Schedule anyway is a preference. For most stateless services I'd actually use schedule anyway, plus enough replicas, so losing a zone degrades you but doesn't block you.

R

I like that you changed your mind out loud. That's what a senior does.

Cluster full. Checkout needs room.
Kubernetes Deep Dive
R

Now the cluster is full. Checkout needs to start a pod right now, but batch jobs are using all the CPU. What happens?

A

By default, nothing. The checkout pod sits in pending until something frees up. Unless you've set up priority. Give checkout a high priority class and the batch jobs a low one, and the scheduler is allowed to preempt. It evicts lower-priority pods to make room.

R

Let's see it. Six batch pods, each asking for three CPUs. Low priority.

R

Now a critical checkout pod, also asking for three CPUs.

A

Pending for a moment, with no node. And there it is. The scheduler preempted one of the batch pods. That's the event, preempted by the checkout pod, on the first worker.

R

What's the danger with priority?

A

Two big ones. If everyone marks their service as critical, priority means nothing. So the platform team owns the priority classes, and teams can't create their own. And preemption ignores some of your safety. It tries to respect pod disruption budgets, but it won't wait forever. So a low-priority service can lose pods suddenly. That's acceptable for batch, not for anything stateful.

R

Five for the whole Kubernetes section. The point about owning the priority classes is exactly what I wanted.

CRD vs operator
Kubernetes Deep Dive
R

Quick one before we move on. What's a CRD and what's an operator?

A

A CRD, a custom resource definition, teaches the API server a new kind of object. Like an Argo CD application, or a Postgres cluster. Just the data. An operator is a controller that watches those objects and does the work. The same reconcile loop we talked about, but for your own kind of thing.

R

Every tool we use today is one of those. Hold on to that.

Kubernetes Networking

Pod to pod across nodes
Kubernetes Networking
R

Networking. A pod in one node talks to a pod on another node. What makes that work?

A

Kubernetes has one rule. Every pod gets its own IP, and every pod can reach every other pod without NAT. How that happens is the CNI plugin's job. On EKS, the default is the VPC CNI, which gives pods real IP addresses from the VPC subnet. So to the network, a pod looks like any other machine.

R

What's the catch with real VPC IPs?

A

You run out. Every pod uses an IP from the subnet, and each instance type can only hold a limited number of network interfaces and addresses. Small subnets fill up fast. The fixes are bigger subnets, prefix delegation so each interface gets blocks of addresses, or a secondary CIDR range just for pods.

Where does a ClusterIP live?
Kubernetes Networking
R

Now a service. The ClusterIP. Where does that IP actually live?

A

Nowhere. That's the trick. No interface has that IP. Kube-proxy on every node watches services and their endpoints, and writes rules, iptables or IPVS, or eBPF if you use something like Cilium. When a packet goes to the ClusterIP, the node rewrites the destination to one of the healthy pod IPs.

R

So if I ping a ClusterIP?

A

Usually nothing. The rules match the service port and protocol, not ICMP. People see the ping fail and think the service is broken. Test it with curl on the actual port instead.

Default deny does nothing. Why?
Kubernetes Networking
R

Network policies. You apply a default deny policy and nothing changes. Traffic still flows. Why?

A

Because network policies are just objects. Something has to enforce them, and that's the CNI. If your CNI doesn't support network policies, they're ignored silently. On EKS you have to turn on network policy support in the VPC CNI, or use something like Calico or Cilium.

R

And once it's enforced, what usually breaks first?

A

DNS. People deny all egress, then forget to allow traffic to CoreDNS on port fifty-three, UDP and TCP. Suddenly nothing resolves and every service looks down.

Internet → pod on EKS
Kubernetes Networking
R

How does traffic from the internet reach a pod on EKS?

A

Usually through the AWS Load Balancer Controller. An ingress or a gateway creates an Application Load Balancer. In IP mode, the load balancer sends traffic straight to pod IPs, skipping the extra hop through the node. And for TLS, certificates from ACM on the load balancer, or cert-manager inside the cluster.

R

Four. Solid. I'd have liked you to mention that a service with no ready endpoints is the most common reason traffic goes nowhere. But the CNI points were exactly right.

Autoscaling & Karpenter

HPA vs VPA vs CA vs Karpenter
Autoscaling & Karpenter
R

Autoscaling. Explain the difference between HPA, VPA, the cluster autoscaler and Karpenter.

A

HPA changes the number of pods. More replicas when CPU or a custom metric goes up. VPA changes the size of pods, their requests. Those two scale the workload. The cluster autoscaler and Karpenter scale the nodes. When pods can't be scheduled, they add machines, and when machines are empty, they remove them.

R

So why would I use Karpenter instead of the cluster autoscaler?

A

The cluster autoscaler works through node groups. On AWS that's auto scaling groups, each with a fixed instance type. It decides which group to grow, and the group launches a node. Karpenter skips the node groups. It looks at the pending pods, works out what they need, and launches the right instance directly from a wide range of types. So it's usually faster, it can pick a bigger or cheaper machine for the actual workload, and you're not managing dozens of node groups.

R

Show me. This is a real EKS cluster with Karpenter installed. Two small nodes from a managed node group.

R

Here's my NodePool. Walk me through it.

A

The NodePool says what Karpenter is allowed to launch. AMD64, on-demand only, from the C, M or R families, with fewer than nine CPUs. The node class points at the EC2 settings, the AMI, subnets and security groups, found by tag. Then limits, CPU eight, so it can never buy more than eight CPUs in total. And the disruption block, consolidate when empty or underutilized, after one minute.

R

Why does that limit matter so much?

A

Because without it, a bug that creates ten thousand pods becomes ten thousand dollars. The limit is your blast radius for cost. Every NodePool should have one.

R

Okay. Apply it, and scale a deployment to five pods. Each one asks for one CPU.

A

All five pending. The existing nodes can't fit them.

A

And Karpenter has already created a NodeClaim. That's Karpenter's record of a machine it's launching.

R

Let's read the controller logs.

A

Found provisionable pods. Computed a new NodeClaim. Created it, launched it, then registered and initialized. Thirty seconds from pending pods to a ready node. And it picked one c6a two x large for all five pods, instead of five small machines. That's bin-packing.

R

Five running, all on the new node.

R

Now the part you mentioned at the start. I'm scaling down to two, then deleting the deployment.

A

That's consolidation. Karpenter noticed the node was empty, tainted it so nothing new lands there, and about thirty seconds later the node and the NodeClaim were gone. The instance is terminated, so you stop paying for it.

R

Back to the two original nodes. No NodeClaims left.

Consolidation is restarting my pods
Autoscaling & Karpenter
R

Okay. Now the follow-ups. Consolidation is moving my pods around all day. A team complains their service restarts too often. What do you do?

A

A few things. First, pod disruption budgets on every service, so Karpenter can only take down a limited number at once. Second, disruption budgets on the NodePool itself, like at most ten percent of nodes at a time, or no disruption during business hours. Third, for something that truly can't be interrupted, like a long batch job, the do-not-disrupt annotation on the pod.

R

And if I set do-not-disrupt on everything?

A

Then you've turned off consolidation and you're paying for empty machines. It's an exception, not a default.

Karpenter + topology spread
Autoscaling & Karpenter
R

Remember the topology spread from earlier? Does Karpenter respect it?

A

Yes. It runs a scheduling simulation that understands spread constraints, affinity and taints. If your pods must spread across three zones, it can launch nodes in three zones. That's one of its advantages over node groups that are tied to one zone. But it can only use the zones your subnets allow, so if the node class only finds subnets in two zones, a three-zone hard spread will leave pods pending.

R

expireAfter. Seven hundred and twenty hours in my NodePool. Why would I want nodes to expire?

A

To keep nodes fresh. After thirty days, Karpenter replaces the node, so you pick up patched AMIs and you never have a server that's been running for two years that nobody dares to touch. It forces your workloads to survive node replacement all the time, which is exactly what you want to find out before an incident, not during one.

Spot interruption with Karpenter
Autoscaling & Karpenter
R

Spot instances. You want to run on spot to save money. What happens when AWS takes a spot node back?

A

AWS gives a two-minute warning. Karpenter listens for those through an SQS queue fed by EventBridge. That's the interruption queue setting in the Helm chart. When the warning comes, it cordons the node, launches a replacement, and drains the pods, inside those two minutes.

A

And I'd only put workloads on spot that can handle it. Stateless, multiple replicas, spread across zones and across many instance types. The more types you allow, the less likely they're all reclaimed at once.

Where does Karpenter itself run?
Autoscaling & Karpenter
R

Should every workload run on Karpenter nodes? What about Karpenter itself?

A

Not on nodes it manages. If Karpenter is running on a node it decides to remove, you can end up with nothing left to launch capacity. That's why this cluster has a small managed node group, the two original nodes, just for Karpenter and other critical system pods. Or you run it on Fargate. Everything else can go on Karpenter nodes.

Pods pending. Karpenter does nothing.
Autoscaling & Karpenter
R

Last one in this round. You deploy, and your pods sit in pending forever. Karpenter isn't launching anything. Where do you look?

A

The pod events first. Then the Karpenter logs, because it will usually say why. The common causes are: the NodePool requirements don't match what the pod asks for, like the pod wants ARM and the pool only allows AMD64. The NodePool limit is already reached. The pod has a taint toleration or node selector no pool satisfies. Or on the AWS side, there's no capacity for those instance types, or the account hit its vCPU quota.

R

The vCPU quota one is real. I hit it setting up this video.

A

Everyone hits it once.

R

Five out of five. You knew the moving parts, the cost risk, and the failure modes.

GitOps & Delivery

What is GitOps?
GitOps & Delivery
R

GitOps. What is it, in one sentence, and why would I want it?

A

Git is the source of truth for what should be running, and a controller in the cluster continuously makes the cluster match Git. You get history, review and rollback for free, and nobody needs admin credentials to the cluster to deploy.

R

Push versus pull. Explain.

A

Push is your CI pipeline running kubectl apply against the cluster. That means CI needs cluster credentials, and if someone changes the cluster by hand, nothing notices. Pull is an agent inside the cluster, like Argo CD or Flux, pulling from Git. The credentials stay inside, and it keeps checking for drift.

R

Let's test the drift part. Here's an Argo CD application. Synced and healthy, one replica.

R

Now I'm going to do the thing everyone does at two a.m. Scale it by hand to five.

A

Argo noticed. The app is out of sync, and the diff shows exactly which resource. The deployment. The service is still fine.

R

But it didn't fix it. Why not?

A

Because self-heal is off. Auto-sync only applies new commits from Git. Self-heal is what reverts manual changes. Turn it on and Argo puts it back.

Self-heal: always on?
GitOps & Delivery
R

One replica, synced again. So should self-heal always be on?

A

In production, I'd say yes, with one exception. During an incident, someone might scale up by hand to survive, and self-heal would fight them. So you either make the emergency change through Git, which can be fast if your pipeline is fast, or you have a documented way to pause sync for that app. What you don't want is a cluster that quietly drifts away from Git for months.

HPA vs replicas in Git
GitOps & Delivery
R

Here's the tricky one. HPA is scaling this deployment between three and twenty replicas. And replicas is set to three in Git. What happens?

A

They fight. The HPA scales to ten, Argo sees ten instead of three, and puts it back. So you remove replicas from the manifest when an HPA owns it, or tell Argo to ignore that field.

Secrets in GitOps?
GitOps & Delivery
R

Secrets. Where do they live in GitOps?

A

Never as plain text in Git. Two common patterns. Encrypt them, like Sealed Secrets or SOPS, so only the cluster can decrypt. Or better at scale, keep them in a secret manager like AWS Secrets Manager or Vault, and use the External Secrets Operator to sync them in. Git only holds a reference to the secret, not the value.

Promoting dev → staging → prod
GitOps & Delivery
R

Promotion. How does a change get from dev to staging to production?

A

I prefer one folder per environment, not one branch per environment. Branches drift and merges get scary. The pipeline builds the image once, then promotes the same image tag by opening a pull request that bumps the version in the staging folder, then production. Production needs an approval. And the image is never rebuilt between environments, so what you tested is what you ship.

R

And rollback?

A

Git revert. The controller applies the old version. And for risky changes, I'd add progressive delivery, like Argo Rollouts, so a canary takes a small slice of traffic first and rolls back automatically if error rates go up.

R

Five. The HPA conflict catches a lot of people in real life, not just in interviews.

Infrastructure as Code

What is Terraform state?
Infrastructure as Code
R

Terraform. What's state, and why do people get nervous about it?

A

State is Terraform's memory. It maps every resource in your code to the real thing it created, with its ID and attributes. Terraform compares three things: your code, the state, and what's really there. People get nervous because if state is lost or corrupted, Terraform forgets it owns things, and might try to create them again.

R

So where should it live?

A

Remote. An S3 bucket with versioning and encryption, with locking so two people can't apply at the same time. Newer Terraform versions can lock with S3 itself, older setups use a DynamoDB table. Never in Git, because it can contain secrets.

R

Let's watch a real plan. This creates a namespace for the payments team and a resource quota.

A

Two resources added, and both are in state now.

R

Now someone deletes the quota by hand. And I run plan again.

A

Terraform refreshed, saw the quota is gone, and plans to create it again. That's drift detection. The plan is the most important review step in Terraform. You read it before every apply.

R

How would you catch drift without waiting for someone to run plan?

A

Run plan on a schedule in CI, every night, with detailed exit codes. Exit code two means there are changes, so you alert the team. And the long-term fix is cultural. Remove write access in the console, so changes go through code.

One state, 2,000 resources
Infrastructure as Code
R

Your Terraform has grown. One state file with two thousand resources. Plans take twenty minutes. What do you do?

A

Split it. By layer and by blast radius. Networking in one state, clusters in another, each team's app infrastructure in its own. Things that change together live together. Smaller states mean faster plans, and a mistake in one can't destroy everything.

R

And how do the layers talk to each other?

A

Outputs. Read them with a remote state data source, or better, look things up by tag or from a parameter store, so the layers aren't tightly coupled. Then modules for anything repeated, versioned, so a change to the module doesn't hit every team on the same day.

Bring a hand-made bucket into Terraform
Infrastructure as Code
R

Last one. Someone created an S3 bucket by hand two years ago. Now you want Terraform to own it. How?

A

Import. Write the resource block, then an import block with the bucket's ID, and run plan. The goal is a plan that shows no changes. If it wants to change things, adjust the code until it matches reality, then apply. Never just apply an import plan that modifies the resource you don't fully understand yet.

R

Four out of five. Strong. I'd want you to mention policy checks on the plan, like OPA or Sentinel, and running plan on every pull request. That's how a platform team reviews infrastructure at scale.

CI/CD & Supply Chain

How does CI authenticate to AWS?
CI/CD & Supply Chain
R

CI. Your pipeline needs to push images and deploy to AWS. How does it authenticate?

A

With OIDC. GitHub Actions or GitLab gets a short-lived token, and AWS trusts it for one specific role, limited to one repository and branch. No access keys stored anywhere. Long-lived keys in CI secrets are one of the most common ways companies get breached.

Compromised dependency. Now what?
CI/CD & Supply Chain
R

Someone pushes a compromised dependency. How does your platform protect you?

A

Layers again. Pin dependencies with lock files, so builds are repeatable. Scan images for known vulnerabilities in the pipeline, and fail on critical ones with a fix available. Generate an SBOM, a software bill of materials, for every image, so when the next big vulnerability lands, you can answer which services are affected in minutes, not weeks.

R

And how do you know the image running in production is the one your pipeline built?

A

Sign it. The pipeline signs every image with something like cosign, using keyless signing tied to the pipeline's identity. Then an admission policy in the cluster only allows signed images from our registry. If someone pushes an image by hand, it can't run. And deploy by digest, not just by tag, because a tag can be moved.

CI takes 40 minutes
CI/CD & Supply Chain
R

Your CI takes forty minutes. Developers are angry. Where do you look?

A

Measure first. Which steps take the time. Usually it's the same few things. No caching of dependencies or Docker layers. Running every test for every change, instead of only what changed. Tests running one after another, instead of in parallel. And slow, shared runners. Fixing caching alone often cuts it in half. And I'd track CI duration as a platform metric, because slow feedback quietly kills productivity.

R

Five. Deploy by digest is a detail a lot of senior people miss.

Multi-tenancy & Policy

20 teams, one cluster
Multi-tenancy & Policy
R

Twenty teams share one cluster. How do you stop one team from hurting the others?

A

Layers. Each team gets its own namespace. Resource quotas, so one team can't take all the CPU. Limit ranges, so pods get default requests. RBAC, so a team can only touch its own namespace. Network policies, so traffic is denied by default between namespaces. And admission policies, for rules everyone has to follow.

R

Let's check that quota from the Terraform round. Two pods max. I deploy three replicas.

A

Two out of three ready. The third pod was rejected at admission. Exceeded quota. It's not pending, it was never created. That's an important difference when you debug. You won't find it with get pods. You find it in the ReplicaSet events.

R

Now RBAC. I give the payments developers the built-in edit role, only in their namespace.

A

Can create deployments in team payments, yes. In the guestbook namespace, no. And they can't create resource quotas, even in their own namespace. So they can't raise their own limits. That's what you want.

Stop the latest tag
Multi-tenancy & Policy
R

Policy. A team deploys an image tagged latest. Why is that bad, and how do you stop it?

A

Latest isn't a version. Two nodes can pull two different images under the same tag, and you can't roll back to latest. So you block it with an admission policy. Kyverno or Gatekeeper. Here, a Kyverno policy.

A

Denied at the door, with a message telling the developer exactly what to fix. And with a pinned version, it's allowed.

New policy broke every deploy
Multi-tenancy & Policy
R

You've just rolled out a new policy, and it's blocking deploys across the company. What did you do wrong?

A

I went straight to enforce. Every new policy should start in audit mode. Report violations, don't block. Then share the report with teams, give them time to fix, and only then switch to enforce. And test policies in CI against real manifests, so you know the blast radius before it's live.

R

When is one shared cluster not enough? When do teams get their own cluster?

A

When the isolation needs are hard. Regulated data, like payments under PCI. Very different Kubernetes versions or upgrade schedules. Untrusted code from customers. Or one team so large it's noisy for everyone. Namespaces are soft isolation. Separate clusters are hard isolation, but each one costs you upgrades, monitoring and money.

R

Five. Audit before enforce is the lesson every platform team learns the hard way once.

Databases on Kubernetes

Postgres on Kubernetes?
Databases on Kubernetes
R

Okay, Alex. Databases. Should you run Postgres on Kubernetes?

A

It depends on who's going to operate it. If you're on AWS and you don't have database expertise, a managed service like RDS or Aurora is usually the right answer. Backups, failover and patching are someone else's job.

A

But it can be done well now, with a good operator. CloudNativePG, for example. You get consistency with everything else on the platform, it can be cheaper, and it works the same on any cloud. The cost is you own the operations, including the scary night when it fails.

R

Let's make it fail. Three-instance Postgres cluster, managed by CloudNativePG.

A

One primary, two replicas. Each with its own persistent volume.

R

How do applications connect? Which pod do they talk to?

A

They shouldn't pick a pod. The operator creates services. R W always points at the primary, for writes. R O points at replicas, for read-only traffic. And R is any instance. When the primary changes, the service changes with it, so the app config never does.

R

I'm writing two orders into the database. Then I'm deleting the primary pod.

A

Instance two is the primary now. The operator promoted a replica. And instance one came back as a replica.

R

And the data?

A

Reading from the new primary. Keyboard and monitor. Both orders survived.

Would we always lose nothing?
Databases on Kubernetes
R

So we lost nothing. Would that always be true?

A

No. By default, replication is asynchronous. The primary confirms a write before the replicas have it. If the primary dies at the wrong moment, the last few transactions can be lost. You can turn on synchronous replication, so a write waits for at least one replica. Then you lose nothing, but every write is a bit slower, and if the replicas are down, writes can block.

R

That's RPO. Explain RPO and RTO properly.

A

RPO, recovery point objective, is how much data you can afford to lose, measured in time. RTO, recovery time objective, is how long you can be down. Synchronous replication gets your RPO close to zero for a single failure. Fast automatic failover gets your RTO down to seconds. And the business picks the targets, because each step costs money.

Why replication is not a backup
Databases on Kubernetes
R

Replication isn't a backup. Why not?

A

Because replication copies mistakes too. Someone runs delete without a where clause, and it's deleted on every replica within a second. A backup is a copy from the past. So you need base backups plus the write-ahead log archived to object storage, like S3. That gives you point-in-time recovery. Restore to two forty-nine, one minute before the bad delete.

R

And when did you last test a restore?

A

That's the right question. A backup you've never restored is just a hope. I'd automate a restore every week into a separate cluster, check the data, and alert if it fails.

Postgres major upgrade
Databases on Kubernetes
R

Major version upgrade. Postgres sixteen to seventeen. How?

A

Carefully, and rehearsed. The safest pattern is a new cluster on the new version, kept in sync with logical replication, then a short cut-over. Point the read-write service at the new primary, and keep the old cluster around for a quick rollback. An in-place upgrade can be faster, but it's harder to undo. Either way, test it against a restored copy of production first, because extensions and query plans can change between versions.

DB pod stuck pending after a zone failure
Databases on Kubernetes
R

Stateful sets and zones. Your Postgres pod's node dies in zone A. The pod reschedules to zone B. And it's stuck pending. Why?

A

Because the volume is in zone A. An EBS volume only lives in one zone, so the pod can only attach it in that zone. That's why you don't rely on moving a database volume between zones. You run replicas in each zone and fail over to one that already has its data. And the storage class should use wait for first consumer, so volumes get created in the zone where the pod is actually scheduled.

200 pods × 20 connections
Databases on Kubernetes
R

Connections. Your app scales to two hundred pods, each with a pool of twenty connections. Postgres falls over. Why?

A

That's four thousand connections. Each Postgres connection is a process with its own memory. Most databases are tuned for a few hundred. You need a connection pooler in between, like PgBouncer, in transaction mode, so thousands of app connections share a small number of real database connections. CloudNativePG can run one for you, called a pooler.

Rename a column, zero downtime
Databases on Kubernetes
R

Last database question. You need to rename a column on a table that's being written to all day. No downtime. How?

A

Never in one step. Expand and contract. First, add the new column. Then deploy code that writes to both columns. Backfill the old rows in small batches. Then switch reads to the new column. And only when nothing uses the old column anymore, drop it. Each step is safe to roll back. A single rename would break every running pod that still uses the old name.

R

Five out of five. And you said you were worried about databases.

Troubleshooting Scenarios

Deploy stuck on "progressing"
Troubleshooting Scenarios
R

Troubleshooting. I'll describe what I see, you tell me what you'd do. No terminal this time, just your thinking. Scenario one. A team says their deploy has been stuck for twenty minutes. Argo says progressing. What do you check?

A

Progressing usually means the new pods never became ready. So I'd look at the rollout status, then the new ReplicaSet's pods. Three common answers. The pods are pending, so it's capacity or scheduling, and the events will say why. The pods are running but not ready, so the readiness probe is failing, often a wrong port or path. Or they're crash looping, so it's the logs from the previous container.

R

They're running, not ready. Readiness probe says connection refused.

A

Then the app isn't listening where the probe is looking. Either the port changed in the new version, or the app listens on localhost only, so nothing outside the container can reach it. I'd exec in and check what it's actually listening on. And the fix goes in Git, not in the cluster, or Argo will just revert it.

Every new image pull is failing
Troubleshooting Scenarios
R

Scenario two. Monday morning. Every pod in the cluster that pulls a new image is failing. Existing pods are fine.

A

Something shared changed. The registry, or the path to it. I'd look at one pod's events for the exact error. If it's unauthorized, the pull credentials expired or a token rotated. On EKS pulling from ECR, it's the node role's permissions. If it's a timeout, it's network. A NAT gateway, a VPC endpoint, or a firewall rule. And if it's too many requests, it's Docker Hub rate limits, which is why a platform should run a pull-through cache.

R

It's too many requests.

A

Then short term, the pods already running are fine, so I'd pause non-urgent deploys. Then point images at a mirror or pull-through cache, like ECR pull-through cache for Docker Hub. And afterwards, a policy that images must come from our own registry, so this can't happen again.

The API server is slow
Troubleshooting Scenarios
R

Scenario three. The API server is slow. Kubectl takes ten seconds for everything. Nothing else looks wrong.

A

Something is hammering it. The usual suspect is a controller or an operator listing everything, over and over, without a cache. Or a script in a loop. I'd look at API server metrics by user agent and by resource, to find who's making the most requests. And on EKS, the control plane logs and audit logs show it. Then there's API priority and fairness, which can stop one noisy client from starving everyone else.

R

And if it's not requests, but etcd?

A

Then it's usually too many objects or very large ones. Thousands of old ReplicaSets, completed jobs that never get cleaned up, or huge config maps. Set revision history limits, set a time to live on finished jobs, and keep big data out of etcd.

R

Five. Every answer started with finding the evidence before guessing. That's the habit.

Design an Internal Platform

Design a platform for 200 engineers
Design an Internal Platform
R

Design round. Two hundred engineers, forty teams, one hundred and fifty microservices, all on AWS. Leadership wants a platform. Design it. Start wherever you want.

A

I'd start with questions, not boxes. What hurts today? How long does it take to ship a change? How many incidents come from deploys? Which teams are happy and which are stuck? The platform should solve the top three problems, not everything.

R

Assume it's the usual. Slow environments, every team has its own pipeline, and nobody knows who owns what.

A

Okay. Then the layers. At the bottom, infrastructure. Terraform modules, one account per environment, EKS clusters per region and per environment, with Karpenter for nodes.

A

On top, the delivery layer. One standard CI template, image build and scan, and Argo CD for deploys, with promotion through pull requests.

A

Then shared services built in. Logging, metrics and tracing with OpenTelemetry. Secrets through External Secrets. Policy with Kyverno. Certificates and DNS automated.

A

And at the top, the developer portal. Something like Backstage, with a service catalog so every service has an owner, and templates. A team clicks new service, and gets a repo, a pipeline, a namespace, dashboards and alerts in about ten minutes.

Why start with Backstage?
Design an Internal Platform
R

Wait. Backstage. That's a big project. Why would you start there?

A

I wouldn't. Good catch. The portal is the last thing, not the first. It's just a front door. I'd start with the golden path itself. One working template for the most common service type, used by two friendly teams. Prove it saves time. The portal goes on top once there's something worth putting in it.

How many clusters?
Design an Internal Platform
R

Better. How many clusters?

A

As few as you can get away with. Production and non-production separated, at minimum. Per region if you serve multiple regions. Split further only for hard isolation, like the PCI case. Every extra cluster is another thing to upgrade three times a year.

A whole region goes down
Design an Internal Platform
R

A whole AWS region goes down. What happens to your platform?

A

That depends on what the business paid for, and I'd make them choose explicitly. The cheap option is backup and restore. Infrastructure as code and data backups copied to a second region, so we can rebuild in hours. The middle option is a pilot light. A small cluster already running in the second region, database replicas there, scale it up when needed. The expensive one is active-active, both regions serving traffic, which is hard mainly because of the data.

R

And the platform part specifically?

A

Everything to rebuild has to live outside the failed region. Terraform state, container images, Git, secrets. If your image registry only exists in the region that's down, you can't start anything anywhere. I'd replicate the registry and the secrets, and practice the failover once a quarter. A disaster plan you've never run is fiction.

Upgrade K8s without an outage
Design an Internal Platform
R

Upgrades. How do you upgrade Kubernetes across all of them without an outage?

A

Read the changelog for removed APIs, and scan the manifests with a tool like Pluto before you start. Upgrade non-production first and let it soak. Upgrade the control plane, then the add-ons, then the nodes. With Karpenter, you bump the AMI version in the node class, Karpenter sees the nodes have drifted, and replaces them gradually, respecting the disruption budgets and the pod disruption budgets. And never be more than one version behind, because skipping versions isn't allowed and the backlog only grows.

K8s bill doubled
Design an Internal Platform
R

Cost. The CFO says the Kubernetes bill doubled this year. First steps?

A

Make it visible first. Cost per team and per namespace, using labels and a tool like Kubecost or OpenCost. Then the usual wins. Right-size requests, because most are set way too high. Consolidation with Karpenter. Spot for stateless work. Savings plans for the steady baseline. And turn off non-production at night and on weekends. When teams see their own bill, behaviour changes fast.

R

Four. Starting with questions was great. Starting the build with Backstage would have cost you. You recovered well when I pushed, and that matters.

Rapid Fire

Rapid fire
Rapid Fire
R

Rapid fire. Short answers. Liveness versus readiness probe?

A

Liveness failing restarts the container. Readiness failing removes it from the service. Never point liveness at a database check, or a database blip restarts everything.

R

Requests versus limits on CPU?

A

Requests are for scheduling and fair share. A CPU limit throttles, even when the node is idle. Many teams set CPU requests, memory limits, and no CPU limit.

R

A pod is stuck in terminating. Why?

A

Usually a finalizer that never finished, or a node that's gone so the kubelet can't confirm. Check finalizers before force deleting.

R

Ingress versus Gateway API?

A

Gateway API is the newer standard. Split roles, so the platform owns the gateway and teams own their routes, and it supports more than HTTP.

R

Service mesh. Do you need one?

A

Not by default. If you need mutual TLS everywhere, fine-grained traffic shifting or deep traffic telemetry, maybe. Otherwise it's a lot of moving parts for problems you don't have yet.

R

How do pods get AWS permissions?

A

EKS Pod Identity or IRSA. A role per service account. Never node-wide credentials. That's how Karpenter itself gets its permissions in this cluster.

R

Helm or Kustomize?

A

Helm for packaging things you install from others. Kustomize for patching your own manifests per environment. Plenty of teams use both.

R

Last one. What's the most important thing a platform team ships?

A

Documentation that's actually up to date. A golden path nobody can find doesn't exist.

R

I wasn't expecting that one. No score for rapid fire, that was just for fun. But that's a good answer.

Behavioural

A migration that did not go to plan
Behavioural
R

Couple of behavioural questions to finish. Tell me about a platform migration you led that didn't go to plan.

A

We moved forty services from an old deploy system to Argo CD. I planned it team by team, and the first five went perfectly. Then we hit the team with the most traffic, and their deploys suddenly took twice as long. Turned out their old system skipped health checks, and Argo was correctly waiting for readiness probes that took ninety seconds.

A

The mistake was mine. I'd tested with easy teams. So we paused, fixed their probes together, and I changed the plan. For each team, a dry run in staging first, plus a checklist of what's different. The rest of the migration took three weeks longer than planned, but nobody had an outage.

R

What would you do differently?

A

Pick one hard team early, not last. The easy teams make you feel fast, but the hard team is where you learn what the migration really involves.

A developer refuses the platform
Behavioural
R

A senior developer refuses to use the platform. Says it's slower than what they built themselves. What do you do?

A

I'd sit with them and watch them deploy, their way and our way. Sometimes they're right, and that's free product research. If their way really is faster, I want to know why and copy it. If ours is better for the company, like security or cost, I explain the trade-off honestly. And I'd never escalate first. Forcing people onto a platform makes enemies. Making it better makes fans.

R

Five. Picking a hard team early is a lesson most people learn too late.

Want 100 more?

The SRE guide has 100 questions with complete answers.

Get the SRE guide