
Book review: Kubernetes in Action, Second Edition from Manning

๐ Introduction
Back to back to some of my initial technical interests, I think this book deserves a fine review. This book took very long to be published from MEAP to completion, and it was probably worth it!
When Marko Lukลกa released the first edition of Kubernetes in Action back in 2017, it rapidly established itself as the gold standard text for mastering container orchestration. However, over the past decade, the Kubernetes ecosystem has undergone significant evolution: legacy container engines yielded to OCI standards via containerd and CRI-O, standard Ingress resources expanded into the modular Gateway API, storage plugins consolidated around the Container Storage Interface (CSI), and sidecar helper patterns evolved into first-class native primitives.
Enter the Second Edition, co-authored by Marko Lukลกa alongside Red Hat engineering leader Kevin Conner. Spanning 18 chapters across 5 cohesive parts, this edition does not merely refresh code samples โ it completely rebuilds the narrative around modern development patterns on modern Kubernetes.
Quick Disclaimers:
No Sponsorship: Iโm not affiliated with Manning or the authors in any way โ just sharing a review.
Fun Note: Big fan of the original illustrations in the book โ always refreshing to see real artwork instead of AI-generated visuals!
Following the initial deep-dive analysis of the book per se, I tasked Bob with digesting the material, mapping out an architectural diagram of its structure, and building a full end-to-end demo application based on the code from the bookโs official GitHub repository (Image blow provided by Bob).

๐๏ธ Part 1-Chapter Analysis & Breakdown
Getting Started & Core Architecture (Chapters 1โ4)
What sets this book apart right from the opening pages is how the authors refuse to treat Kubernetes as a black box. Instead of just giving you commands to run, they take you back to Googleโs Borg origins and walk you through how the system is actually wired under the hood.
Chapter 1: Introducing Kubernetes โ The authors unpack cluster topology by showing how Kubernetes cleanly splits responsibilities. The Control Plane handles intelligence (
kube-apiserver,etcd,kube-scheduler, andkube-controller-manager), while the Workload Plane does the actual heavy lifting via worker nodes running kubelet, kube-proxy, and an OCI runtime.
+-----------------------------------+
| KUBERNETES CONTROL PLANE |
| +--------+ +-------------------+ |
| | etcd | | kube-apiserver | |
| +--------+ +-------------------+ |
| +-----------+ +----------------+ |
| | scheduler | | controllers | |
| +-----------+ +----------------+ |
+------------------+----------------+
| RESTful API
+-------------------------+-------------------------+
| |
+------------v------------+ +------------v------------+
| WORKER NODE 1 | | WORKER NODE 2 |
| +--------------------+ | | +--------------------+ |
| | Kubelet | | | | Kubelet | |
| +--------------------+ | | +--------------------+ |
| | kube-proxy | CRI | | | | kube-proxy | CRI | |
| +------------+-------+ | | +------------+-------+ |
| [ Pod A ] [ Pod B ] | | [ Pod C ] [ Pod D ] |
+-------------------------+-------------------------+-------------------------+
Enter fullscreen mode Exit fullscreen mode
Chapter 2: Containers & Linux Primitives โ I really appreciate that Chapter 2 doesnโt jump straight into Kubernetes abstractions. It grounds you in low-level Linux kernel primitives โ specifically Namespaces (for process, mount, and network isolation) and Control Groups (cgroups) (for CPU and memory limits). To make everything hands-on, the authors introduce Kiada (Kubernetes in Action Demo Application), a simple Node.js microservice used throughout the book:
# Chapter 2: Minimal Dockerfile for Kiada Demo ApplicationFROM node:23-alpineCOPY app.js /app.jsCOPY html/ /htmlENTRYPOINT ["node", "app.js"]Enter fullscreen mode Exit fullscreen mode
Chapter 3: First Deployments โ Here, you get your hands dirty spinning up local environments like Kind or Minikube before moving toward cloud clusters like GKE or EKS. You learn how
kubectlinteracts imperatively with the cluster before diving into declarative files (images from the book):

# Imperatively creating a Pod and exposing it via a Service
kubectl run kiada --image=luksa/kiada:0.1 --port=8080
kubectl expose pod kiada --type=NodePort --port=8080
Enter fullscreen mode Exit fullscreen mode

Chapter 4: API & Object Model โ This chapter hits on a fundamental mental model shift: understanding the REST API structure and the core distinction between the desired state (
spec) and the observed state (status).
# Chapter 4: Declarative Object Manifest StructureapiVersion: v1kind: Podmetadata:name: kiada-demolabels:
app: kiadaspec:containers:- name: kiada-container
image: luksa/kiada:0.1Enter fullscreen mode Exit fullscreen mode
Running Applications in Kubernetes (Chapters 5โ7)
Once you understand the API, Part 2 dives into the atom of Kubernetes: the Pod.
Chapter 5: Pods โ Instead of viewing containers as isolated units, the authors illustrate why containers inside the same Pod share the
netandipcnamespaces. This enables tight co-location, sharedlocalhostnetworking, and multi-container patterns like helper sidecars or init containers:
# Chapter 5: Multi-Container Pod with an Init Container and Main AppapiVersion: v1kind: Podmetadata:name: kiada-init-demospec:initContainers:- name: init-html
image: busybox:1.36
command: ['sh', '-c', 'echo "<h1>Welcome to Kiada</h1>" > /usr/share/nginx/html/index.html']
volumeMounts:
- name: html-vol
mountPath: /usr/share/nginx/htmlcontainers:- name: web-server
image: nginx:alpine
volumeMounts:
- name: html-vol
mountPath: /usr/share/nginx/htmlvolumes:- name: html-vol
emptyDir: {}Enter fullscreen mode Exit fullscreen mode
Chapter 6: Pod Lifecycle & Health โ This chapter is absolute gold for anyone who has ever debugged cascading failures in production. It covers the exact mechanics of Startup, Liveness, and Readiness probes, ensuring your app doesnโt receive traffic until itโs ready and gets restarted if it deadlocks:
# Chapter 6: Pod Manifest with Liveness, Readiness, and Startup ProbesapiVersion: v1kind: Podmetadata:name: kiada-healthylabels:
app: kiada
env: productionspec:containers:- name: kiada
image: luksa/kiada:0.2
ports:
- containerPort: 8080
startupProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
livenessProbe:
httpGet:
path: /healthz
port: 8080
periodSeconds: 10
readinessProbe:
httpGet:
path: /readiness
port: 8080
periodSeconds: 5Enter fullscreen mode Exit fullscreen mode
Chapter 7: Organization โ As the clusters grows, keeping things organized becomes critical. This chapter explains how to group objects logically using Namespaces and query them cleanly using key-value Labels and Selectors (image from the book):
# Querying pods dynamically using label selectors
kubectl get pods -l app=kiada,env=production --namespace=default
Enter fullscreen mode Exit fullscreen mode

Application Configuration & Storage (Chapters 8โ10)
Building cloud-native apps means keeping them stateless and configuration-agnostic. Part 3 walks through how Kubernetes lets you inject configuration and attach storage seamlessly.
Chapter 8: Configuration โ Here we learn how to decouple application logic from environment specifics using
ConfigMap, inject sensitive items with Secret, and expose runtime cluster metadata back to the container via the Downward API (images from the book):


# Chapter 8: Injecting ConfigMap and Secret values as Environment VariablesapiVersion: v1kind: Podmetadata:name: kiada-config-demospec:containers:- name: kiada
image: luksa/kiada:0.3
env:
- name: INITIAL_STATUS
valueFrom:
configMapKeyRef:
name: kiada-config
key: status.message
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: kiada-secret
key: passwordEnter fullscreen mode Exit fullscreen mode
Chapter 9: Volumes โ This chapter covers temporary volume types like
emptyDir, host filesystem access withhostPath, and mounting configuration maps directly as filesystem files (image from the book):

# Chapter 9: Mounting a ConfigMap as a VolumeapiVersion: v1kind: Podmetadata:name: kiada-volume-demospec:containers:- name: kiada
image: luksa/kiada:0.3
volumeMounts:
- name: config-volume
mountPath: /etc/kiadavolumes:- name: config-volume
configMap:
name: kiada-configEnter fullscreen mode Exit fullscreen mode
Chapter 10: Persistent Storage โ The authors unpack the separation between persistent storage requests (
PersistentVolumeClaim) and actual cluster storage backends (PersistentVolume) backed by CSI drivers:
[ Pod Spec ] โโ( PVC Reference )โโ> [ PersistentVolumeClaim ]
โ (Dynamic Provisioning)
โผ
[ PersistentVolume ] โโ> [ Physical / Cloud Storage (CSI) ]
Enter fullscreen mode Exit fullscreen mode
# Chapter 10: Dynamically Provisioned Storage via PVCapiVersion: v1kind: PersistentVolumeClaimmetadata:name: quiz-data-pvcspec:accessModes:
- ReadWriteOnceresources:
requests:
storage: 2GistorageClassName: standardEnter fullscreen mode Exit fullscreen mode
Connecting & Exposing Applications (Chapters 11โ13)
Part 4 is one of the most rewarding parts of the book, taking you step-by-step from internal pod communication all the way to modern traffic management.
Chapter 11: Services โ Pods are ephemeral, meaning their IP addresses change constantly. Services provide a stable virtual IP (
ClusterIP),NodePortbindings, or cloud LoadBalancers to front your workloads, powered by internal DNS:
# Chapter 11: Service Manifest for Internal Cluster RoutingapiVersion: v1kind: Servicemetadata:name: kiada-servicespec:type: ClusterIPselector:
app: kiadaports:- port: 80
targetPort: 8080Enter fullscreen mode Exit fullscreen mode
Chapter 12: Ingress โ When Layer 7 HTTP routing is needed, path matching, and SSL termination, standard Ingress steps in:
# Chapter 12: Classic Ingress Resource ManifestapiVersion: networking.k8s.io/v1kind: Ingressmetadata:name: kiada-ingressspec:rules:- host: kiada.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: kiada-service
port:
number: 80Enter fullscreen mode Exit fullscreen mode
Chapter 13: Gateway API โ This is a standout chapter! The authors provide an extensive, modern guide to the Gateway API (
GatewayClass,Gateway,HTTPRoute), explaining why it cleanly separates infrastructure owner roles from application developer routing needs:
[ External Client ]
โ
โผ
[ Gateway: prod-gateway ] โโโ (GatewayClass: istio / envoy)
โ
โโโโ (HTTPRoute: kiada-route) โโโบ [ Service: kiada-service ]
โ
โโโโ (HTTPRoute: quote-route) โโโบ [ Service: quote-service ]
Enter fullscreen mode Exit fullscreen mode
# Chapter 13: Modern Traffic Split using Gateway API (HTTPRoute)apiVersion: gateway.networking.k8s.io/v1kind: HTTPRoutemetadata:name: kiada-routenamespace: defaultspec:parentRefs:- name: prod-gatewayrules:- matches:
- path:
type: PathPrefix
value: /api/v1/quotes
backendRefs:
- name: quote-service-v1
port: 8080
weight: 80
- name: quote-service-v2
port: 8080
weight: 20Enter fullscreen mode Exit fullscreen mode
Managing Applications at Scale (Chapters 14โ18)
The final part transitions from running single pods to orchestrating complex, self-healing, scalable application stacks in production.
Chapter 14: ReplicaSets โ What is the core reconciliation loop โ how Kubernetes continuously compares desired replica counts against actual running pods and creates or deletes pods to match? Hereafter the path;
# Chapter 14: Declarative ReplicaSet ManifestapiVersion: apps/v1kind: ReplicaSetmetadata:name: kiada-rsspec:replicas: 3selector:
matchLabels:
app: kiadatemplate:
metadata:
labels:
app: kiada
spec:
containers:
- name: kiada
image: luksa/kiada:0.1Enter fullscreen mode Exit fullscreen mode
Chapter 15: Deployments โ Deployments build on top of
ReplicaSetsto offer zero-downtime rolling updates, canaryrollouts, quickrollbacks, and blue/green deployments:
# Chapter 15: Deployment Manifest with RollingUpdate StrategyapiVersion: apps/v1kind: Deploymentmetadata:name: kiada-deploymentspec:replicas: 4strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0selector:
matchLabels:
app: kiadatemplate:
metadata:
labels:
app: kiada
spec:
containers:
- name: kiada
image: luksa/kiada:0.2Enter fullscreen mode Exit fullscreen mode
Chapter 16: StatefulSets โ When dealing with databases or distributed stateful systems, pods need unique, predictable identities (
pod-0,pod-1) and dedicated persistent storage claims:
# Chapter 16: StatefulSet with VolumeClaimTemplatesapiVersion: apps/v1kind: StatefulSetmetadata:name: quiz-dbspec:serviceName: "quiz-db-headless"replicas: 3selector:
matchLabels:
app: quiz-dbtemplate:
metadata:
labels:
app: quiz-db
spec:
containers:
- name: mongo
image: mongo:7.0
ports:
- containerPort: 27017
volumeMounts:
- name: data
mountPath: /data/dbvolumeClaimTemplates:- metadata:
name: data
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 5GiEnter fullscreen mode Exit fullscreen mode
Chapter 17: DaemonSets โ Covering how to run exact per-node daemon copies across your cluster for log collection, node monitoring, or network plugin management:
# Chapter 17: DaemonSet for Cluster-Wide Log CollectorapiVersion: apps/v1kind: DaemonSetmetadata:name: fluentd-elasticsearchspec:selector:
matchLabels:
name: fluentd-elasticsearchtemplate:
metadata:
labels:
name: fluentd-elasticsearch
spec:
containers:
- name: fluentd-elasticsearch
image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2Enter fullscreen mode Exit fullscreen mode
Chapter 18: Batch Processing โ Finally, the authors cover short-lived, completable workloads via Job and scheduled periodic executions with
CronJob:
# Chapter 18: Scheduled Workload using CronJobapiVersion: batch/v1kind: CronJobmetadata:name: kiada-backup-jobspec:schedule: "0 2 * * *"jobTemplate:
spec:
template:
spec:
containers:
- name: backup
image: luksa/kiada-backup:1.0
restartPolicy: OnFailureEnter fullscreen mode Exit fullscreen mode
Throughout the chapters of the book, a demo application named Kiada is progressively built. In Part 2, IBM Bob takes those concepts a step further by implementing a brand-new โKiadaโ *application built entirely from scratch, using the original code excerpts from the book as a foundation (schema provided by Bob).
Part 2-Putting the bookโs knwoledge in Pactice
Beyond analyzing the theoretical concepts of Kubernetes in Action, 2nd Edition per se, I worked with Bob to translate those patterns into a tangible, production-ready implementation.
Instead of leaving the bookโs learnings as static code snippets, Bob built kiada-goโa complete Go re-implementation of the author's Node.js Kiada demo applicationโand deployed it to a local kind Kubernetes cluster following the exact architecture, health-probe, configuration, and networking patterns taught throughout the 18 chapters.
๐ ๏ธ Application Architecture & Deployment Flow
The target system is structured into a multi-tiered Kubernetes architecture running inside an isolated kiada namespace. It demonstrates external traffic ingress, service abstraction, dynamic scaling, and environmental metadata injection (schema provided by Bob).

๐๏ธ Key Components & Applied Patterns
Application Layer (kiada-go)

Minimalist Container Footprint: Compiled using a multi-stage Docker build (golang:1.21-alpine โ alpine:3.19) into a lightweight binary running as an unprivileged system user (appuser).โ
# - - - - - build stage - - - - -
FROM golang:1.21-alpine AS builderWORKDIR /buildCOPY go.mod ./RUN go mod download
COPY *.go ./RUN CGO_ENABLED=0 GOOS=linux go build -trimpath -o kiada-go .
โ
# - - - - - runtime stage - - - - -
FROM alpine:3.19RUN addgroup -S appgroup && adduser -S appuser -G appgroup
WORKDIR /appCOPY - from=builder /build/kiada-go /app/kiada-goUSER appuserEXPOSE 8080ENTRYPOINT ["/app/kiada-go"]Enter fullscreen mode Exit fullscreen mode
This dockerfile is optimized based on my own recommendations for image building to illustrate multi-stage images, and is nit based on the book.
Graceful Termination (Chapter 6): Implements explicit
SIGTERM/SIGINTsignal catching in Go, giving active HTTP requests a 10-second grace window to finalize during rolling updates or pod teardowns.Service Proxying (Chapter 11): Includes
/proxy/quoteand/proxy/quizendpoints that forward requests to internal cluster microservices viaDNSservice discovery.
// main.gopackage mainโimport ("context""fmt""log""net/http""os""os/signal""syscall""time")โconst appName = "kiada-go"const version = "1.0"โfunc main() {listenPort := getEnv("LISTEN_PORT", "8080")addr := fmt.Sprintf(":%s", listenPort)โlogStartup(addr)โsrv := &http.Server{
Addr: addr,
Handler: newRouter(),
ReadTimeout: 10 * time.Second,
WriteTimeout: 15 * time.Second,
IdleTimeout: 60 * time.Second,}โ// Run server in goroutine so shutdown handling worksgo func() {
log.Printf("%s v%s listening on %s", appName, version, addr)
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("ListenAndServe error: %v", err)
}}()โ// Graceful shutdown on SIGTERM / SIGINT (matches Ch 6 SIGTERM handler pattern)quit := make(chan os.Signal, 1)signal.Notify(quit, syscall.SIGTERM, syscall.SIGINT)<-quitโlog.Printf("Received shutdown signal. Shutting down %s...", appName)ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)defer cancel()โif err := srv.Shutdown(ctx); err != nil {
log.Fatalf("Server shutdown error: %v", err)}log.Printf("%s shut down cleanly.", appName)}โfunc logStartup(addr string) {hostname, _ := os.Hostname()log.Printf("-------------------------------------------")log.Printf("%s v%s โ Kubernetes in Action Demo (Go)", appName, version)log.Printf("-------------------------------------------")log.Printf("Pod name : %s", getEnv("POD_NAME", hostname))log.Printf("Pod IP : %s", getEnv("POD_IP", "0.0.0.0"))log.Printf("Node name : %s", getEnv("NODE_NAME", "unknown"))log.Printf("Node IP : %s", getEnv("NODE_IP", "0.0.0.0"))log.Printf("QUOTE_URL : %s", getEnv("QUOTE_URL", "(not set)"))log.Printf("QUIZ_URL : %s", getEnv("QUIZ_URL", "(not set)"))log.Printf("Listen addr: %s", addr)}Enter fullscreen mode Exit fullscreen mode
โ
Kubernetes Resource Mapping
The implementation translates key book chapters directly into declarative Kubernetes manifests:

| Manifest File | Book Chapter(s) | Architectural Function |
| -------------------- | -------------------------- | ------------------------------------------------------------ |
| `00-namespace.yaml` | **Chapter 7** | Creates an isolated `kiada` namespace boundary for resource allocation and security scoping. |
| `01-configmap.yaml` | **Chapter 8** | Decouples non-sensitive settings (port bindings, status messages) from container images. |
| `02-deployment.yaml` | **Chapters 6, 8, 14 & 15** | Manages 3 pod replicas with zero-downtime `RollingUpdate`, `liveness`/`readiness` probes, and **Downward API** field refs (`POD_NAME`, `POD_IP`, `NODE_NAME`). |
| `03-service.yaml` | **Chapter 11** | Exposes stable internal IP routing via `ClusterIP` on port 80 and direct developer access via `NodePort` on 30880. |
| `04-ingress.yaml` | **Chapter 12** | Provides Layer 7 domain-based HTTP routing to internal services. |
| `05-hpa.yaml` | **Chapters 14โ15** | Dynamically scales pod replicas between 2 and 10 based on CPU utilization metrics. |
Enter fullscreen mode Exit fullscreen mode
Downward API & Runtime Injection (Chapter 8)
To allow the application to remain self-aware of its placement in the cluster without depending on direct API server queries, the deployment injects runtime metadata directly through environment variables:
# โโ Deployment: kiada-go โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ# Implements patterns from Chapters 8, 11, 15:# - Downward API env vars (Ch 8)# - ConfigMap env injection (Ch 8)# - Readiness probe /healthz/ready (Ch 6/11)# - Rolling update strategy (Ch 15)# - 3 replicas (Ch 14)apiVersion: apps/v1kind: Deploymentmetadata:name: kiada-gonamespace: kiadalabels:
app: kiada-go
rel: stablespec:replicas: 3selector:
matchLabels:
app: kiada-go
rel: stablestrategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0template:
metadata:
labels:
app: kiada-go
rel: stable
ver: "1.0"
spec:
terminationGracePeriodSeconds: 30
containers:
- name: kiada-go
image: ${REGISTRY}/kiada-go:1.0
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 8080
protocol: TCP
env:
# Downward API โ injects pod/node metadata (Chapter 8)
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: NODE_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
# Service URLs injected via ConfigMap (Chapter 8)
- name: QUOTE_URL
value: "http://quote.kiada.svc.cluster.local/quote"
- name: QUIZ_URL
value: "http://quiz.kiada.svc.cluster.local"
# Status message from ConfigMap (Chapter 8)
- name: INITIAL_STATUS_MESSAGE
valueFrom:
configMapKeyRef:
name: kiada-go-config
key: INITIAL_STATUS_MESSAGE
# Liveness probe โ restart container if it stops responding (Chapter 6)
livenessProbe:
httpGet:
path: /healthz/ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
failureThreshold: 3
# Readiness probe โ only route traffic when ready (Chapter 6/11)
readinessProbe:
httpGet:
path: /healthz/ready
port: 8080
initialDelaySeconds: 3
periodSeconds: 5
failureThreshold: 1
resources:
requests:
cpu: "50m"
memory: "32Mi"
limits:
cpu: "200m"
memory: "64Mi"Enter fullscreen mode Exit fullscreen mode
โ
# โโ Ingress: kiada-go โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ# Routes external traffic to the kiada-go service (Chapter 12 Ingress pattern)# Requires an IngressController (e.g. nginx-ingress) to be installed.## Access via:# curl -H "Host: kiada-go.example.com" http://<node-ip>apiVersion: networking.k8s.io/v1kind: Ingressmetadata:name: kiada-gonamespace: kiadaannotations:
nginx.ingress.kubernetes.io/rewrite-target: /spec:ingressClassName: nginxrules:- host: kiada-go.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: kiada-go
port:
name: httpEnter fullscreen mode Exit fullscreen mode
โ
โก Quick Verification
Once launched locally, the implementation can be queried to confirm proper pod self-awareness and readiness checks:
Deploy the application
#!/usr/bin/env bash# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ# launch.sh โ Build and deploy kiada-go to a local kind cluster# Usage: ./scripts/launch.sh [REGISTRY] [IMAGE_TAG]# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโset -euo pipefail
REGISTRY="${1:-$(id -un)/kiada-go}"IMAGE_TAG="${2:-1.0}"IMAGE="${REGISTRY}:${IMAGE_TAG}"CLUSTER_NAME="kiada"PORT=30880
echo "==> Building kiada-go Docker image: ${IMAGE}"
docker build -t "${IMAGE}" ./kiada-go
echo "==> Loading image into kind cluster '${CLUSTER_NAME}'"if ! kind get clusters 2>/dev/null | grep -q "^${CLUSTER_NAME}$"; then
echo "==> Creating kind cluster '${CLUSTER_NAME}'"
kind create cluster --name "${CLUSTER_NAME}"fi
kind load docker-image "${IMAGE}" --name "${CLUSTER_NAME}"
echo "==> Patching deployment image reference"# Replace the ${REGISTRY}/kiada-go:1.0 placeholder with the real imagesed "s|\${REGISTRY}/kiada-go:1.0|${IMAGE}|g" \
kiada-go/k8s/02-deployment.yaml > /tmp/kiada-go-deploy-patched.yaml
echo "==> Applying Kubernetes manifests"
kubectl apply -f kiada-go/k8s/00-namespace.yaml
kubectl apply -f kiada-go/k8s/01-configmap.yaml
kubectl apply -f /tmp/kiada-go-deploy-patched.yaml
kubectl apply -f kiada-go/k8s/03-service.yaml
echo "==> Waiting for rollout to complete..."
kubectl rollout status deployment/kiada-go -n kiada --timeout=90s
URL="http://localhost:${PORT}"echo ""echo "โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ"echo " kiada-go is running!"echo " NodePort URL : ${URL}"echo " Health check : ${URL}/healthz/ready"echo " Pod info : ${URL}/info"echo "โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ"echo ""echo "To watch pods:"echo " kubectl get pods -n kiada -w"Enter fullscreen mode Exit fullscreen mode
# Check the application status endpoint$ curl http://localhost:30880/
โ
Hello from kiada-go v1.0!
Pod: kiada-go-7d84f89d97-x9z2l | Node: kind-worker
Pod IP: 10.244.0.5 | Node IP: 172.18.0.2
Status: Welcome to kiada-go on Kubernetes!
โ
# Verify health probes$ curl http://localhost:30880/healthz/ready
{"status":"ready","time":"2026-08-05T12:51:00Z"}Enter fullscreen mode Exit fullscreen mode
๐ Conclusion for the Book
For me, Kubernetes in Action, Second Edition is a triumph of technical writing. Marko Lukลกa and Kevin Conner have delivered a book that strikes an exquisite balance between low-level system engineering concepts and practical, developer-friendly paradigms.
By building out concepts sequentially โ starting from bare Linux namespaces up to the Gateway API, StatefulSets, and Custom Operators โ the authors ensure readers build a deep, intuitive mental model of Kubernetes rather than merely memorizing command-line syntax.
For developers, SREs, and platform architects looking to build resilient cloud-native software on modern Kubernetes, this second edition is essential reading and was undoubtedly worth every bit of the wait!
๐ฏ Conclusion for the Implementation: From Static Code to Executable Architecture with IBM Bob
What makes this project truly remarkable is that IBM Bob didnโt merely generate boilerplate code โ it absorbed the foundational knowledge of Kubernetes in Action, 2nd Edition directly from its text and repository code excerpts to engineer a fully realized, operational system. By ingesting the authorsโ original patterns across all 18 chapters, IBM Bob autonomously architected, refactored, and deployed kiada-goโcomplete with graceful signal handling, multi-stage OCI builds, Downward API metadata injection, and zero-downtime rolling updates. This hands-on implementation proves that when advanced developer assistants like IBM Bob are paired with high-quality, production-minded literature, theoretical cloud-native concepts can be instantly transformed into resilient, battle-tested software.
Thanks for reading ๐
Links
Bookโs page at manning.com: https://www.manning.com/books/kubernetes-in-action-second-edition
Bookโs repository: https://github.com/luksa/kubernetes-in-action-2nd-edition
This blog postโs code repository: https://github.com/aairom/kiada-go
IBM Bob: https://bob.ibm.com/
Comments (0)
Login to post a comment.