DEV Community

Cover image for I Deployed 11 Microservices Locally With kind, Then Broke One on Purpose published
Vivian Chiamaka Okose
Vivian Chiamaka Okose

Posted on • Originally published at vivianokose.hashnode.dev

I Deployed 11 Microservices Locally With kind, Then Broke One on Purpose published

Online Boutique
Online Boutique running locally on kind. 11 microservices, 5 languages, one kubectl apply command.

I want to be honest with you: before this deployment, "microservices" was just a word I had read about. I knew the definition. I could explain it in theory. But I had never actually run a microservices application and watched it breathe.

This changed that.

Google's Online Boutique is a demo e-commerce app made up of 11 separate services, written in five different programming languages, all talking to each other over gRPC. I ran all of it on my laptop using kind, and then I did something that is not in any tutorial: I injected a CPU fault into one of the services just to see what would happen.


What is Online Boutique and Why Does It Matter?

Online Boutique is an open-source cloud-native reference application built by Google. It is not a toy. Google uses it internally to demo Kubernetes, gRPC, distributed tracing, and service mesh patterns.

What makes it interesting for learning is the architecture. Every part of the app is a completely separate service with its own codebase, its own container, and its own runtime:

  • frontend is Go. It is the HTTP entry point — the thing your browser talks to.
  • cartservice is C#. It stores your cart items in Redis.
  • checkoutservice is Go. It calls six other services to complete one order.
  • recommendationservice is Python. It suggests related products.
  • adservice is Java. It returns ads based on page context.

They all run at the same time. They all depend on each other. That is exactly what a microservices production environment looks like.


Why I Used kind Instead of minikube

kind stands for Kubernetes IN Docker. Instead of spinning up a virtual machine (like minikube does), kind runs your entire Kubernetes cluster inside Docker containers. That means:

  • No hypervisor needed
  • Faster cluster startup
  • Lower resource overhead
  • Clean teardown: kind delete cluster removes everything

If you have Docker running, you can have a Kubernetes cluster in under a minute.


Setting It Up

Install kind and kubectl, then create your cluster:

kind create cluster --name online-boutique
Enter fullscreen mode Exit fullscreen mode

Clone the repo and deploy:

git clone https://github.com/GoogleCloudPlatform/microservices-demo.git
cd microservices-demo
kubectl apply -f ./release/kubernetes-manifests.yaml
Enter fullscreen mode Exit fullscreen mode

Online Boutique
One command creates 22 Kubernetes resources across 11 services.

Now watch the pods come up:

kubectl get pods --watch
Enter fullscreen mode Exit fullscreen mode

Pods in ContainerCreating phase
The pull phase. Docker is downloading container images for all 11 services. This is the real process — not just the happy ending.

First run takes 5–10 minutes because Docker has to pull images. After that it is fast because images are cached locally.

All 11 pods 1/1 Running
All 11 pods Running. This is the screenshot I had been working towards.


Accessing the Application

kind does not give you a LoadBalancer (that requires a cloud provider). Use port-forward instead:

kubectl port-forward deployment/frontend 8080:8080
Enter fullscreen mode Exit fullscreen mode

Open http://localhost:8080 in your browser.

Online Boutique homepage
An e-commerce store running entirely on my laptop. 11 services, all talking to each other over gRPC.

I clicked through the whole app. Added items to the cart. Completed a checkout. Every action crossed multiple service boundaries: the frontend called the productcatalogservice, the cartservice wrote to Redis, the checkoutservice called the paymentservice, emailservice, and shippingservice in sequence.


The Thing That Surprised Me: Live Traffic Was Already Running

After everything was up, I ran this out of curiosity:

kubectl logs -l app=frontend --tail=30
Enter fullscreen mode Exit fullscreen mode

The logs were already full of requests. Not from me.

The loadgenerator service — which is part of the deployment — had been quietly simulating real user traffic the whole time. It browses the store, adds items to carts, and checks out orders on a loop, automatically. I did not configure it. It just happened.

That was the moment the architecture clicked for me: in a real production system, observability tools would already be watching this traffic, flagging anomalies, measuring latency. The loadgenerator is a built-in simulation of production load.


Then I Broke It on Purpose

Once I confirmed everything was healthy, I injected a CPU fault into the recommendationservice:

kubectl exec -it deployment/recommendationservice -- sh -c "while true; do true; done"
Enter fullscreen mode Exit fullscreen mode

What this does: it opens a shell inside the running container and starts an infinite loop that burns CPU as fast as possible. The container is now consuming all the CPU it can get.

kubectl top pods showing recommendationservice CPU spike
CPU usage on recommendationservice spiking after fault injection. Other services remain stable.

What I expected: Kubernetes would notice, restart the pod, and everything would be fine.

What actually happened: Nothing. Kubernetes did not restart the pod. It just kept running, getting slower and slower, because the container was not crashing. It was degrading.

Kubernetes only restarts containers that fail health checks or crash outright. A container that is alive but overwhelmed is invisible to the default scheduler.

The recommendation feature slowed down. The rest of the app kept working fine — cart, checkout, payment, all normal.

To recover, I deleted the pod manually:

kubectl delete pod -l app=recommendationservice
Enter fullscreen mode Exit fullscreen mode

Kubernetes immediately created a fresh one. Clean slate. Thirty seconds later, recommendations were back to normal.


What I Took Away From This

  1. kubectl apply -f is more powerful than it looks. One command, 22 resources, 11 services. The manifest is the source of truth.

  2. Microservices isolate failure well. A broken recommendationservice did not take down the cart or checkout. That is the point of the architecture.

  3. Kubernetes does not save you from everything. A degraded-but-not-dead service is an invisible problem without resource limits, liveness probes, and readiness probes properly configured.

  4. kind is excellent for local Kubernetes experimentation. Fast, clean, no cloud cost.

  5. The loadgenerator is underrated. It gives you something to observe immediately without setting up synthetic monitoring yourself.


What's Next

Next step for me is deploying the same application on AWS EKS and Azure AKS. The Kubernetes manifests will not change at all. That is the whole point of cloud-native architecture: the workload does not care where it runs. The infrastructure is the variable.

I will document both cloud deployments the same way I documented this one.


If you are learning DevOps or cloud engineering and have not tried running Online Boutique locally yet — do it. Then break something. That is where the real learning is.

GitHub: github.com/vivianokose
LinkedIn: linkedin.com/in/okosechiamaka

Top comments (0)