Deploy and orchestrate Mizu applications on Kubernetes.
Kubernetes (often abbreviated as K8s) is an open-source platform for automating the deployment, scaling, and management of containerized applications. Think of it as a system that runs your Docker containers across multiple servers, automatically handling load balancing, restarts, and scaling.While Docker runs containers on a single machine, Kubernetes manages containers across a cluster of machines. If a server fails, Kubernetes automatically moves your containers to healthy servers. If traffic increases, it can spin up more copies of your app. This makes Kubernetes ideal for production workloads that need high availability.This guide covers deploying Mizu applications with proper health checks, scaling, and best practices.
In Kubernetes, you don’t run containers directly. Instead, you describe what you want (e.g., “run 3 copies of my app”) in YAML files, and Kubernetes makes it happen. The two most fundamental resources are:
Deployment: Defines your application—what container image to use, how many replicas to run, and how to update them
Service: Exposes your application to network traffic, load balancing across all replicas
A Deployment tells Kubernetes how to run your application. The replicas: 3 means Kubernetes will always keep 3 copies running. If one crashes, it automatically starts a replacement.
A Service provides a stable network endpoint for your application. Since pods (the smallest deployable units in Kubernetes) can be created and destroyed dynamically, their IP addresses change. A Service gives you a fixed address that automatically routes to healthy pods.
Kubernetes uses probes to monitor your application’s health and make intelligent decisions. Unlike Docker’s simple health checks, Kubernetes has three distinct probe types, each serving a different purpose.Understanding probes is critical: misconfigured probes can cause your app to restart constantly or receive traffic before it’s ready. Mizu’s built-in health handlers (/livez and /readyz) work perfectly with Kubernetes:
Kubernetes provides two resources for managing configuration separately from your container images. This separation is a best practice because it lets you use the same image in different environments (dev, staging, production) with different settings.
A ConfigMap stores non-sensitive configuration data as key-value pairs. Your application reads these as environment variables or mounted files. ConfigMaps are visible to anyone with cluster access, so never store passwords here:
A Secret is like a ConfigMap but designed for sensitive data like passwords, API keys, and certificates. Kubernetes stores Secrets with base64 encoding and can integrate with external secret managers for encryption at rest. While Secrets aren’t perfectly secure by default, they’re treated with more care than ConfigMaps and can be restricted with RBAC policies:
So far, your Service is only accessible inside the Kubernetes cluster. To expose your application to the internet, you need an Ingress. Think of Ingress as the front door to your cluster—it receives external traffic and routes it to the appropriate services based on the URL.Ingress also handles TLS/HTTPS termination, so you can configure SSL certificates in one place rather than in each service. You’ll need an Ingress Controller (like nginx-ingress or Traefik) installed in your cluster for Ingress resources to work.
One of Kubernetes’ most powerful features is automatic scaling. Instead of manually adding or removing instances based on traffic, Kubernetes can do this automatically based on metrics like CPU usage, memory, or even custom metrics like requests per second.
A Horizontal Pod Autoscaler (HPA) watches your pods and adjusts the replica count based on observed metrics. For example, if CPU usage exceeds 70%, it adds more pods. When usage drops, it scales back down to save resources.The HPA continuously monitors metrics and makes smooth adjustments—it won’t instantly scale from 2 to 100 pods, but will increase gradually to avoid thrashing:
When you deploy a new version of your application, you don’t want downtime. Rolling updates solve this by gradually replacing old pods with new ones. Kubernetes starts a new pod, waits for it to be healthy, then terminates an old pod. This continues until all pods are running the new version.If the new version has problems (failing health checks), Kubernetes stops the rollout and you can easily roll back to the previous version. This makes deployments much safer than traditional “stop everything, deploy, start everything” approaches.
apiVersion: apps/v1kind: Deploymentmetadata: name: myappspec: replicas: 3 strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 # Allow 1 extra pod during update maxUnavailable: 0 # Never have less than replicas template: spec: containers: - name: myapp image: myregistry/myapp:v1.0.0 # Graceful shutdown lifecycle: preStop: exec: command: ["/bin/sh", "-c", "sleep 10"] # Wait for pod to be ready before continuing rollout terminationGracePeriodSeconds: 30
In a shared cluster, you need to control how much CPU and memory each application can use. Without limits, one misbehaving app could consume all resources and crash other apps. Kubernetes uses requests and limits to manage resource allocation.
Requests tell Kubernetes the minimum resources your app needs. The scheduler uses this to decide which node to place your pod on—it won’t place a pod on a node that can’t satisfy its requests.Limits are the maximum resources your app can use. If your app tries to exceed its memory limit, Kubernetes kills it (OOMKilled). If it exceeds CPU limit, it gets throttled (slowed down but not killed).
Sometimes Kubernetes needs to evict pods for maintenance—node upgrades, cluster scaling, or rebalancing. A Pod Disruption Budget (PDB) tells Kubernetes the minimum number of pods that must stay running during these voluntary disruptions.For example, if you have 3 replicas and set minAvailable: 2, Kubernetes will only evict one pod at a time, ensuring at least 2 are always running. This prevents accidental outages during maintenance:
apiVersion: policy/v1kind: PodDisruptionBudgetmetadata: name: myappspec: minAvailable: 2 # Or use maxUnavailable: 1 selector: matchLabels: app: myapp
Namespaces are virtual clusters within your Kubernetes cluster. They let you divide resources between different teams, projects, or environments (dev, staging, production). Resources in different namespaces are isolated from each other, and you can apply different resource quotas and access controls to each namespace.A common pattern is to have separate namespaces for each environment: