Welcome everyone! Today we're diving into Kubernetes Fundamentals — from containers to production-grade orchestration. We'll cover what problems Kubernetes solves, the core architecture and primitives like Pods, Services, and Deployments, then move into networking, Ingress, Helm package management, Prometheus monitoring, common pitfalls, and battle-tested best practices. Whether you're new to K8s or looking to solidify your understanding, this session will give you everything you need to run containerized workloads in production. Let's get started.
Before Kubernetes, running containerized applications at scale was painful. Teams had to manually scale by adding servers during traffic spikes. Resource utilization was terrible — servers typically ran at just ten to twenty percent capacity. Every deployment required custom scripts for each environment. When applications crashed, they stayed down until someone noticed and manually intervened. And service discovery meant hard-coded IP addresses everywhere. Docker solved the packaging problem, but orchestration was still entirely manual. Teams needed a way to automate deployment, scaling, and management across hundreds or thousands of containers. That's the gap Kubernetes fills.
list
Kubernetes solves these problems through four key capabilities. {{step}}First, orchestration — it automates the deployment, scaling, and management of containerized applications across your entire cluster. {{step}}Second, self-healing. Kubernetes automatically restarts failed containers, replaces unhealthy nodes, and kills containers that don't respond to health checks. {{step}}Third, load balancing. It distributes network traffic across healthy Pods with built-in service discovery, so you never have to manage endpoints manually. {{step}}And fourth, resource management. Kubernetes bin-packs containers onto nodes for optimal utilization, making sure you get the most out of your infrastructure. The fundamental idea is that you declare your desired state in YAML, and Kubernetes continuously works to make reality match.
cards
Let's look at how Kubernetes is structured. The diagram shows the two main components. At the top is the control plane — the brain of the cluster. The API Server is the central point that everything talks through. etcd is a distributed key-value store that holds all cluster state. The Scheduler decides which node to place Pods on. And the Controller Manager runs control loops that constantly reconcile desired state with actual state. Below the control plane are the worker nodes. Each node runs a kubelet, which is the node agent that manages Pods on that machine. The kubelets communicate back to the API Server to receive instructions and report status. This separation means you can scale worker nodes independently while the control plane maintains centralized coordination.
mermaid
Here's a table of the six core Kubernetes resources you need to know. Pods are the smallest deployable unit — they're ephemeral, meaning they can die at any time and get rescheduled. Deployments manage ReplicaSets and handle rolling updates — they're persistent and the primary way you run applications. Services provide stable network endpoints for your Pods, since Pod IPs change constantly. ConfigMaps store non-sensitive configuration data like database URLs and feature flags. Secrets store sensitive data like passwords and API tokens. And Namespaces give you virtual clusters for resource isolation — you'd typically have separate namespaces for dev, staging, and production. These six resources are what you'll work with every day.
table
Let's look at a Pod manifest. Every Kubernetes resource follows the same structure: apiVersion, kind, metadata, and spec. Here we're defining a Pod running nginx version one twenty-five. The metadata includes labels — key-value pairs that other resources use for selection, like services routing traffic to pods with the label app equals web. The important part is the resources section at the bottom. Requests define the minimum guaranteed resources — this is what the scheduler uses to place the Pod on a node. Limits define the maximum the container can use. Always set both to avoid resource contention. If you skip limits, one runaway container can consume all the CPU and memory on the node, starving every other Pod.
code
Now here's a Deployment manifest. A Deployment wraps Pods in a ReplicaSet for declarative updates. The spec dot replicas field says we want three copies of this Pod running at all times. The selector with matchLabels connects the Deployment to its Pods using the label app equals web. The template section is the actual Pod spec — identical to what we just saw, defining the container image and ports. When you apply this YAML, Kubernetes creates a ReplicaSet which creates three Pods. If one crashes, the ReplicaSet automatically creates a replacement. When you update the image tag, the Deployment performs a rolling update — replacing Pods one at a time so there's zero downtime. This is why you should never manage Pods directly — always use Deployments.
code
kubectl is your primary interface to Kubernetes, and these five commands will cover ninety percent of your daily work. First, kubectl get pods lists all pods with their status, restart count, and age. Second, kubectl describe gives you the full details for a resource including events — this is your go-to debugging command. Look at the Events section at the bottom for scheduling, image pulling, and container start information. Third, kubectl logs streams the container output, essential for diagnosing application errors. Fourth, kubectl apply creates or updates resources from a YAML file — this is how you deploy. And fifth, kubectl scale adjusts the replica count on the fly. Master these five commands first, and you'll be productive with Kubernetes immediately.
terminal
Services solve the fundamental networking challenge in Kubernetes. Pods are ephemeral — they come and go, and their IP addresses change every time they're rescheduled. A Service provides a stable IP and DNS name that stays constant regardless of what happens to the underlying Pods. Looking at this diagram, when a client sends traffic to the nginx Service at ClusterIP ten dot ninety-six dot zero dot one, Kubernetes uses iptables or IPVS to load-balance that traffic across the three healthy Pods. Each Pod has its own dynamic IP, but the client only ever talks to the Service. Kubernetes watches for Pod changes and automatically updates the routing table. This decoupling of service discovery from Pod lifecycle is what makes Kubernetes networking work at scale.
mermaid
Kubernetes has four service types, each for a different use case. {{step}}ClusterIP is the default — it creates an internal-only IP accessible within the cluster. This is what you'll use for most backend services that don't need external access. {{step}}NodePort exposes the service on every node's IP at a static port between thirty thousand and thirty-two thousand seven sixty-seven. It gives you external access but is rarely used in production. {{step}}LoadBalancer provisions a cloud load balancer from your cloud provider — AWS ELB, GCP GLB, and so on. This is your production solution for external traffic, though each one costs money. {{step}}And ExternalName simply creates a DNS alias that points to an external service. There's no proxying or load balancing — just DNS redirection. In production, the smart move is to use a single Ingress controller instead of one LoadBalancer per service — it's much more cost-effective.
cards
Ingress provides HTTP and HTTPS routing to multiple services through a single load balancer. Looking at this YAML, we define an Ingress resource with routing rules. The annotation configures nginx-specific behavior like URL rewriting. Under rules, we specify that requests to api dot example dot com with the path slash users go to the user-service on port eighty, and requests to slash orders go to the order-service on port eighty. This is path-based routing — one hostname, multiple backend services. Popular Ingress controllers include nginx-ingress, Traefik, and Istio Gateway. They also handle TLS termination, so your backend services don't need to manage certificates. The key benefit: instead of paying for one cloud load balancer per service, you have one Ingress controller handling all your HTTP routing. Much cheaper at scale.
code
This slide shows a before and after comparison for configuration management. On the left is the bad practice — hardcoding values directly in your container spec. The database URL and API key are baked right into the deployment. This means you need different YAML files for each environment. On the right is the proper approach. The database URL comes from a ConfigMap using configMapKeyRef, and the API key comes from a Secret using secretKeyRef. This externalizes your configuration so the same deployment YAML works across dev, staging, and production — you just swap the ConfigMap and Secret. One important caveat: Kubernetes Secrets are only base64 encoded, not encrypted by default. For real security, enable encryption at rest in etcd, or better yet, use an external secrets manager like HashiCorp Vault or your cloud provider's KMS.
code
Helm is the package manager for Kubernetes. Instead of managing dozens of YAML files for a complex application, you install a single Helm chart. In this terminal walkthrough, we start by adding the Bitnami repository, which hosts hundreds of production-ready charts. Searching for postgres shows us the available chart with its version. Then we install it with helm install — one command and we have a complete PostgreSQL deployment running in our cluster. Helm list shows all installed releases with their status. And when we need to scale up, helm upgrade lets us change configuration on the fly, like increasing the replica count to three. The real power is in templating — you define your YAML templates once and override values per environment using values files. Plus, if something goes wrong, helm rollback reverts to the previous release instantly. You can find thousands of public charts at Artifact Hub.
terminal
Monitoring is absolutely non-negotiable in production Kubernetes. This diagram shows the standard monitoring stack. Prometheus sits at the center, scraping metrics from three sources in your cluster: Node Exporter provides host-level metrics like CPU, memory, and disk. kube-state-metrics exposes Kubernetes resource state like pod status and deployment counts. And your applications expose custom metrics at a slash metrics endpoint. Prometheus then feeds data to two consumers: Alertmanager handles notifications, sending alerts to Slack, PagerDuty, or email when thresholds are breached. And Grafana provides the visualization layer with pre-built dashboards. The easiest way to deploy this entire stack is with a single Helm chart — kube-prometheus-stack gives you everything configured out of the box.
mermaid
Here are the six essential metrics you should monitor from day one. Container CPU usage seconds total tracks CPU time per container — alert if it exceeds eighty percent sustained. Container memory working set bytes shows active memory usage — alert above eighty-five percent of your configured limit. kube pod status phase with phase equals Pending catches pods that are stuck and can't be scheduled — any pending pod for more than five minutes needs attention. Pod container status restarts total detects crash loops — more than five restarts in ten minutes means something is fundamentally broken. kubelet running pods tracks how many pods are on each node — the default limit is a hundred and ten, and exceeding it causes instability. And API server request duration seconds measures control plane latency — if your p95 exceeds one second, the entire cluster is sluggish. Set up alerts on these six metrics first, and you'll catch most issues before users notice.
table
These four issues account for eighty percent of beginner Kubernetes problems. {{step}}First, missing resource limits. Without CPU and memory limits, one misbehaving pod can starve the entire node. OOMKilled means your memory limit is too low. CPU throttling means the limit is too aggressive. Always set both requests and limits. {{step}}Second, ImagePullBackOff. This means Kubernetes can't pull your container image. Check the image name and tag for typos, verify your imagePullSecrets are configured, and test connectivity to the registry. {{step}}Third, CrashLoopBackOff. The container starts, crashes, and Kubernetes keeps restarting it with exponential backoff. Check logs with kubectl logs, verify your entrypoint command, and fix the application startup logic. {{step}}And fourth, services not routing traffic. If traffic isn't reaching your Pods, verify that the selector labels match the Pod labels exactly, check that readiness probes are passing, and confirm the port numbers match between Service and Pod. Always check labels first — mismatched labels are the number one cause.
cards
Health checks are how Kubernetes knows if your application is actually working. This YAML shows both types of probes on a container. The livenessProbe hits slash healthz on port eighty eighty. It waits thirty seconds before the first check to give the app time to start, then runs every ten seconds. If the liveness check fails, Kubernetes restarts the container. Think of it as asking: is this process still alive? The readinessProbe hits slash ready on port eighty eighty. It starts checking after just five seconds and runs every five seconds. If readiness fails, Kubernetes removes the Pod from Service endpoints — it won't receive traffic until it passes again. The key difference: use different endpoints. Your healthz endpoint should be a basic ping — is the process responding at all. Your ready endpoint should check deeper — is the database connected, are dependencies available. Without these probes, Kubernetes has no visibility into your application's actual health.
code
Let me leave you with nine production best practices. Use namespaces to separate environments and team boundaries. Label everything with consistent key-value pairs — labels power selectors, which power everything else. Always set resource requests and limits to avoid noisy neighbors and OOMKills. Implement health checks — liveness and readiness probes are non-negotiable. Use Deployments, never bare Pods — you get declarative updates and self-healing for free. Version your container images with specific tags — never use latest in production because it breaks reproducibility and rollbacks. Store secrets externally using Vault, AWS Secrets Manager, or GCP Secret Manager rather than Kubernetes Secrets alone. Set up monitoring from day one with Prometheus and Grafana before you deploy to production. And automate everything with CI/CD using GitOps tools like ArgoCD or Flux for declarative deployments. These aren't optional — they're the difference between a reliable system and a house of cards.
list
Let's wrap up with six key takeaways. Kubernetes automates container orchestration at scale — handling deployment, scaling, and self-healing so you don't have to. It's all declarative YAML — you define the desired state and Kubernetes makes it reality. The core primitives to remember are Pods which are ephemeral, Deployments which are persistent, and Services which provide stable networking. Helm charts package complex applications into reusable, configurable bundles — use them instead of managing raw YAML. Prometheus and Grafana provide production-grade observability out of the box with the kube-prometheus-stack Helm chart. And finally, set resource limits and implement health checks from day one — these two practices alone prevent the majority of production incidents. Kubernetes has a steep learning curve, but once you internalize the declarative model, it becomes incredibly powerful. Thank you for joining this session!
list