DEV Community

Cover image for Day 48: Nobody Replaces a Bare Pod, and a Stack Knows How to Take Itself Apart
Nnamdi Felix Ibe
Nnamdi Felix Ibe

Posted on AI-assisted

Day 48: Nobody Replaces a Bare Pod, and a Stack Knows How to Take Itself Apart

Kubernetes starts today, and it starts with the one object that has nobody looking after it. On the other side, the same Lambda I built by hand on Day 33, rebuilt as a template that knows how to create itself and how to tear itself down.

Both are about who is responsible for a thing once it exists.

One Kubernetes task, one AWS task. Deploy a pod, then deploy a Lambda through CloudFormation. The tasks come from the KodeKloud Engineer platform.

Two routes to a pod manifest

The fast route generates the YAML:

kubectl run pod-httpd --image=httpd:latest --labels="app=httpd_app" \
  --dry-run=client -o yaml > pod.yaml
Enter fullscreen mode Exit fullscreen mode

--dry-run=client -o yaml prints the object kubectl would send without sending it. The Kubernetes quick reference uses exactly this pattern to generate a spec file, and it saves typing all the boilerplate.

The careful route writes it by hand:

apiVersion: v1
kind: Pod
metadata:
  name: pod-httpd
  labels:
    app: httpd_app
spec:
  containers:
  - name: httpd-container
    image: httpd:latest
Enter fullscreen mode Exit fullscreen mode

They do not produce the same file, and that caught me. kubectl run names the container after the pod, so the generated manifest has a container called pod-httpd. The task wanted httpd-container. The generated file is a starting point to edit, not a finished answer.

kubectl apply -f pod.yaml
kubectl describe pod pod-httpd
Enter fullscreen mode Exit fullscreen mode

Two small things worth having. kubectl validates manifests strictly by default: --validate defaults to strict, which fails the request on unknown fields rather than silently dropping them, so a misspelled key is an error you see. And when a pod will not start, the reason is in the Events section at the bottom of describe, not in the one-word status from get.

Nobody is watching this pod

Here is the part that matters. Delete pod-httpd, or lose the node it runs on, and it is gone. Nothing brings it back.

Kubernetes documents this directly: a ReplicaSet replaces pods that are deleted or terminated for any reason, such as node failure, unlike pods a user created directly. It goes as far as recommending a ReplicaSet even when you only need one pod.

So a bare pod is useful for exactly what I did with it, which is learn what a pod is. Anything that should still be running tomorrow needs something above it whose job is to notice when it is not. That is tomorrow's task.

The same Lambda, declared instead of commanded

On Day 33 this Lambda was six CLI calls and a retry loop, the loop because create-function failed when the IAM role had been created seconds earlier and had not propagated yet. Today it is one template and one create-stack, and it deployed first time with no retry anywhere.

I want to be careful about what that proves. CloudFormation documents that in its default mode it waits for each resource to reach a fully stabilised state before reporting it complete, which fits what happened. It does not document anything specific to IAM propagation for a role a Lambda uses in the same stack. So "no retry loop needed" is what I saw, not something I can point to as a promise. That distinction matters the day it fails.

What the template genuinely removes is the ordering:

Role: !GetAtt LambdaExecutionRole.Arn
Enter fullscreen mode Exit fullscreen mode

AWS's rule is that when one resource refers to another with !Ref, !GetAtt or !Sub, the referenced one is created first and deleted last. That single reference is the whole dependency graph. DependsOn is for the cases where a real dependency exists that nothing in the template points at.

And one detail that looks arbitrary until you read why:

Handler: index.lambda_handler
Enter fullscreen mode Exit fullscreen mode

When code is supplied inline, CloudFormation places it in a file named index, so the handler's module part has to be index. Only the function name after the dot is yours.

Two more habits carried in from yesterday. The template uses managed policies only, because Day 47's account refused inline ones. And before deploying, one aws iam get-role to make sure no role called lambda_execution_role already existed, since the template names it explicitly and a collision would leave the stack in ROLLBACK_COMPLETE, which only a delete gets you out of.

Taking it apart

Day 33's teardown was to delete the function, detach the policy, delete the role, in that order, and get it wrong at each step.

aws cloudformation delete-stack --stack-name datacenter-lambda-app
Enter fullscreen mode Exit fullscreen mode

The same references that ordered the build order the teardown, in reverse. The stack knows what it made and how to unmake it.

Who is responsible once it exists

A bare pod has nobody. A CloudFormation stack is its own record of what exists and how it fits together. Most of the difference between a lab and a system is whether something is in that role.

So here is the Day 48 question. For the thing you deployed most recently, if it disappeared tonight, what would you notice, and what would put it back?

Day 48 down. Fifty-two to go.

Top comments (0)