ZyVOP Logo
Content That Connects
SeriesAI NewsWhy ZyVOPJoin Discord
LoginGet Started
ZyVOP Logo
Content That Connects

The Developer Publishing Hub. Write once, cross-post to Dev.to, Medium, Hashnode, WordPress & Bluesky with automated canonical source tags and zero paywalls.

Content

  • Categories
  • Tags
  • Badges
  • Leaderboard
  • Write Article
  • Newsletter

Company

  • About Us
  • Why ZyVOP
  • Developer API & CLI
  • Write for Us
  • Contact

Connect

  • Privacy Policy
  • Terms of Service
  • Cookie Policy
  • DMCA Policy
  • Code of Conduct

ยฉ 2026 ZyVOP. Developer Publishing Hub.

Zero paywalls ยท Full content ownership
All systems operational
HomeBook Review & Technical Implementation: Kubernetes in Action, Second Edition

Book Review & Technical Implementation: Kubernetes in Action, Second Edition

Alain Airom (Ayrom)
Alain Airom (Ayrom)
Build Engineer
August 31, 2026
13 min read
Book Review & Technical Implementation: Kubernetes in Action, Second Edition
#bookreview#bob#Kubernetes

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, and kube-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 kubectl interacts 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.1

Enter 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 net and ipc namespaces. This enables tight co-location, shared localhost networking, 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: 5

Enter 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: password

Enter fullscreen mode Exit fullscreen mode

  • Chapter 9: Volumes โ€” This chapter covers temporary volume types like emptyDir, host filesystem access with hostPath, 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-config

Enter 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: standard

Enter 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), NodePort bindings, 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: 8080

Enter 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: 80

Enter 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: 20

Enter 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.1

Enter fullscreen mode Exit fullscreen mode

  • Chapter 15: Deployments โ€” Deployments build on top of ReplicaSets to offer zero-downtime rolling updates, canary rollouts, quick rollbacks, 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.2

Enter 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: 5Gi

Enter 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.2

Enter 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: OnFailure

Enter 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 / SIGINT signal 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/quote and /proxy/quiz endpoints that forward requests to internal cluster microservices via DNS service 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: http

Enter 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.

Alain Airom (Ayrom)
Alain Airom (Ayrom)

Build Engineer

IT guy, IBMer... sharing my hands-on experiences and technical subjects of my interest (IBM or not). A bit "touche ร  tout"!

Subscribe to Alain Airom (Ayrom)'s Newsletter

More from Alain Airom (Ayrom)

View profile

Automating AI Context: How I Built a Custom Extension for IBM Bob IDE to Inject Project Rules

Building my own โ€œvsixโ€ extension to automate my own projects Introduction Setting up consistent workspace instructions across projects can quickly become a tedi...

10 minAug 31

Deep Dive: Testing Radar UI for Kubernetes using MCP, a Go GUI, and an Autonomous Agent

Hand-on test of radarhq.io K8S UI and dashboard on a macOS with Minikube and Podman Introduction Kubernetes dashboards are often either overloaded with unnecess...

5 minAug 31

Embedding Docling-NLP in Ad-Hoc UI Applications: A Lightweight Blueprint

Implementing a โ€œGraph Language Modelโ€ with Docling-NLP Image from Docling-AI Building a local, privacy-focused Document AI pipeline often feels like balancing h...

3 minAug 31

Loop Engineering 101

From Curiosity to Creation: Building a Loop Engineering Application with IBMโ€™s Bob Introduction For some time now, โ€œLoop Engineeringโ€ has been generating signif...

9 minAug 31

Building an OpenTelemetry Instrumentation Wizard

Accelerating observability adoption by automating OpenTelemetry instrumentation across heterogeneous codebases Introduction Years ago, I was tasked with buildin...

14 minAug 31