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 ] |
+-------------------------+-------------------------+-------------------------+
- 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 Application
FROM node:23-alpine
COPY app.js /app.js
COPY html/ /html
ENTRYPOINT ["node", "app.js"]
-
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
-
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 Structure
apiVersion: v1
kind: Pod
metadata:
name: kiada-demo
labels:
app: kiada
spec:
containers:
- name: kiada-container
image: luksa/kiada:0.1
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 App
apiVersion: v1
kind: Pod
metadata:
name: kiada-init-demo
spec:
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/html
containers:
- name: web-server
image: nginx:alpine
volumeMounts:
- name: html-vol
mountPath: /usr/share/nginx/html
volumes:
- name: html-vol
emptyDir: {}
- 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 Probes
apiVersion: v1
kind: Pod
metadata:
name: kiada-healthy
labels:
app: kiada
env: production
spec:
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: 5
- 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
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 Variables
apiVersion: v1
kind: Pod
metadata:
name: kiada-config-demo
spec:
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: password
-
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 Volume
apiVersion: v1
kind: Pod
metadata:
name: kiada-volume-demo
spec:
containers:
- name: kiada
image: luksa/kiada:0.3
volumeMounts:
- name: config-volume
mountPath: /etc/kiada
volumes:
- name: config-volume
configMap:
name: kiada-config
-
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) ]
# Chapter 10: Dynamically Provisioned Storage via PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: quiz-data-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
storageClassName: standard
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 Routing
apiVersion: v1
kind: Service
metadata:
name: kiada-service
spec:
type: ClusterIP
selector:
app: kiada
ports:
- port: 80
targetPort: 8080
- Chapter 12: Ingress β When Layer 7 HTTP routing is needed, path matching, and SSL termination, standard Ingress steps in:
# Chapter 12: Classic Ingress Resource Manifest
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: kiada-ingress
spec:
rules:
- host: kiada.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: kiada-service
port:
number: 80
-
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 ]
# Chapter 13: Modern Traffic Split using Gateway API (HTTPRoute)
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: kiada-route
namespace: default
spec:
parentRefs:
- name: prod-gateway
rules:
- matches:
- path:
type: PathPrefix
value: /api/v1/quotes
backendRefs:
- name: quote-service-v1
port: 8080
weight: 80
- name: quote-service-v2
port: 8080
weight: 20
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 Manifest
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: kiada-rs
spec:
replicas: 3
selector:
matchLabels:
app: kiada
template:
metadata:
labels:
app: kiada
spec:
containers:
- name: kiada
image: luksa/kiada:0.1
-
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 Strategy
apiVersion: apps/v1
kind: Deployment
metadata:
name: kiada-deployment
spec:
replicas: 4
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: kiada
template:
metadata:
labels:
app: kiada
spec:
containers:
- name: kiada
image: luksa/kiada:0.2
-
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 VolumeClaimTemplates
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: quiz-db
spec:
serviceName: "quiz-db-headless"
replicas: 3
selector:
matchLabels:
app: quiz-db
template:
metadata:
labels:
app: quiz-db
spec:
containers:
- name: mongo
image: mongo:7.0
ports:
- containerPort: 27017
volumeMounts:
- name: data
mountPath: /data/db
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 5Gi
- 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 Collector
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd-elasticsearch
spec:
selector:
matchLabels:
name: fluentd-elasticsearch
template:
metadata:
labels:
name: fluentd-elasticsearch
spec:
containers:
- name: fluentd-elasticsearch
image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2
-
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 CronJob
apiVersion: batch/v1
kind: CronJob
metadata:
name: kiada-backup-job
spec:
schedule: "0 2 * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: backup
image: luksa/kiada-backup:1.0
restartPolicy: OnFailure
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 builder
WORKDIR /build
COPY 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.19
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
WORKDIR /app
COPY - from=builder /build/kiada-go /app/kiada-go
USER appuser
EXPOSE 8080
ENTRYPOINT ["/app/kiada-go"]
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.go
package 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 works
go 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)
}
β
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. |
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/v1
kind: Deployment
metadata:
name: kiada-go
namespace: kiada
labels:
app: kiada-go
rel: stable
spec:
replicas: 3
selector:
matchLabels:
app: kiada-go
rel: stable
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
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"
β
# ββ 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/v1
kind: Ingress
metadata:
name: kiada-go
namespace: kiada
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: kiada-go.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: kiada-go
port:
name: http
β
β‘ 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 image
sed "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"
# 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"}
π 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/











Top comments (0)