Category Archives: 01 – Core Concepts

Deployments

Welcome to the NZRT Wiki Podcast. Today we’re looking at Deployments.

So, what exactly is a Deployment in Kubernetes? Think of it as a manager for your running application. A Deployment makes sure a set number of copies of your app — called pod replicas — are up and running at all times. It also handles the tricky business of updating your app and rolling back if something goes wrong.

Let’s talk about what makes Deployments so useful. First, they work declaratively. That means you describe the state you want — say, two copies of your app running the latest image — and Kubernetes figures out how to get there. You don’t have to script every step yourself.

Second, Deployments support rolling updates. When you push a new version of your app, Kubernetes starts new pods before it stops the old ones. That way, your app stays available to users throughout the whole update process, with no downtime.

Third, if something goes wrong with an update, you can roll back. There’s a single command that reverts your Deployment to its previous state, and Kubernetes handles the rest.

And fourth, scaling. If you need more capacity, you can simply adjust the number of replicas — either directly in your configuration, or automatically using something called a Horizontal Pod Autoscaler.

Now let’s look at what a real Deployment definition looks like. The example in the wiki defines a Deployment for a WordPress application running in the production environment. Here’s what it sets up in plain terms.

It tells Kubernetes this is a Deployment object, gives it the name wordpress, and places it in the nzrt-prod namespace. It then says: keep two replicas running at all times. It uses a label — in this case, app equals wordpress — so Kubernetes knows which pods belong to this Deployment.

Inside the pod template, it defines one container, also called wordpress, running version six point five of the official WordPress image. That container listens on port 80, and it’s given an environment variable pointing it to the database — specifically, a service called mysql-service.

The definition also sets resource boundaries. Each pod requests a quarter of a CPU core and 256 megabytes of memory to start. But if it needs more headroom, it can scale up to one full CPU core and 512 megabytes of memory. This stops any single pod from overwhelming your cluster.

Finally, the update strategy is set to rolling update. The configuration allows one pod to be temporarily unavailable during a rollout, and one extra pod to come up above your normal replica count. So during an update, you might briefly have three pods running — two old, one new — before the old ones are taken down.

Now let’s go through the day-to-day commands you’ll use to manage Deployments.

To see all your Deployments in the production namespace, you run a get-deployments command scoped to that namespace. To get detailed information about the WordPress Deployment specifically, you use describe-deployment and give it the name.

Scaling is simple — there’s a scale-deployment command where you specify the new number of replicas. So if you want three copies instead of two, you set replicas to three and you’re done.

Updating the container image is done with a set-image command. You name the Deployment, name the container inside it, and provide the new image version — for example, switching from WordPress six point five to six point six.

To check on a rollout while it’s in progress, there’s a rollout-status command that gives you live feedback on how the update is going.

If something goes wrong, rollout-undo is your safety net. It reverts the Deployment to whatever it was running before, immediately.

And finally, rollout-history shows you the list of previous versions on record, so you know exactly what you can roll back to.

If you want to explore further, the wiki also points to related topics covering Pods and Containers, how Deployments relate to ReplicaSets under the hood, and how Services connect your running Deployment to the outside world.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.

Namespaces

Welcome to the NZRT Wiki Podcast. Today we’re looking at Namespaces.

So, what is a namespace? Think of it as a virtual cluster living inside your actual Kubernetes cluster. Instead of one big shared space where all your workloads, configs, and resources sit together, namespaces let you carve things up into isolated sections. Each section can have its own access controls, its own resource limits, and its own set of rules. It’s a clean way to separate concerns — especially when you’re running multiple environments on the same cluster.

Let’s talk about how NZRT uses namespaces specifically. There are six you need to know about. First is nzrt-prod, which is your production environment. This one is locked down — only xc and dan have access, so treat it with care. Then there’s nzrt-staging, which mirrors the production config and is used for pre-production testing and UAT work. Below that sits nzrt-dev, a more relaxed space for development and experimentation — resource limits are looser here, so you’ve got room to move.

Beyond those three environment namespaces, there are a few infrastructure ones. The monitoring namespace is home to the shared observability stack — that’s Prometheus, Grafana, and Loki all running together. Then there’s ingress-nginx, which handles the Nginx ingress controller for the whole cluster. And finally, kube-system — this is where Kubernetes puts its own system components. Leave this one alone. Don’t modify it.

Now, Kubernetes also comes with a set of default namespaces out of the box. The one simply called default catches any resource that doesn’t have a namespace explicitly assigned to it. Kube-system, as mentioned, is for the core Kubernetes internals. Kube-public is readable by everyone in the cluster and holds general cluster information. And kube-node-lease is used internally for node heartbeat tracking — you won’t need to touch that one directly either.

Let’s walk through some of the common commands you’ll use day to day. If you want to see all the namespaces currently in your cluster, you run a get namespaces command with kubectl. To create a new namespace — say, nzrt-staging — you use kubectl create namespace followed by the name. If you want to see all pods running across every namespace at once, you pass the all-namespaces flag to a get pods command. To narrow it down to just one namespace, like nzrt-prod, you use the n flag followed by the namespace name. And if you want to set a default namespace for your current context so you don’t have to type it every time, there’s a config set-context command where you pass the current flag and then specify the namespace you want to default to.

Now let’s look at resource quotas, because this is where namespaces really earn their keep in a shared cluster. A resource quota is a Kubernetes object that caps how much compute a namespace can consume. In the example for nzrt-prod, the quota is named nzrt-prod-quota and it’s scoped to the nzrt-prod namespace. It sets a minimum CPU request of four cores, a minimum memory request of four gigabytes, a maximum CPU limit of eight cores, a maximum memory limit of eight gigabytes, and a hard cap of twenty pods running at any one time. This means no matter what gets deployed into production, it can never exceed those boundaries — which protects the rest of the cluster from being starved of resources by a runaway workload.

If you want to go deeper on access control within namespaces, check out the RBAC wiki page, which covers role-based access policies. And for the broader picture of how all of this fits together, the NZRT Kubernetes Architecture page is your next stop.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.

Pods Containers

Welcome to the NZRT Wiki Podcast. Today we’re looking at Pods & Containers.

If you’re working with Kubernetes, the first concept you need to get comfortable with is the Pod. A Pod is the smallest deployable unit in Kubernetes. Think of it as a wrapper that holds one or more containers together, letting them share the same network and storage resources.

So what does that actually mean in practice? Every container inside a Pod shares the same IP address and port space. That means if you have two containers running side by side in the same Pod, they can talk to each other just by using localhost — no complicated networking required. It’s as if they’re running on the same machine.

One thing that’s really important to understand about Pods is that they are ephemeral. They’re not designed to be repaired when something goes wrong — they’re replaced. If a Pod fails, the system spins up a new one. Because of this, you never create Pods directly in a production environment. Instead, you manage them through something called a Deployment, which handles the lifecycle for you.

Now let’s talk about the Pod lifecycle. A Pod moves through a series of phases depending on what’s happening with its containers. There are five phases to know. First is Pending — this means the cluster has accepted the Pod, but the containers haven’t started yet. Next is Running, which means at least one container is currently active. Then there’s Succeeded, which means all containers finished their work and exited cleanly with a success code. After that is Failed — meaning at least one container exited with an error code, signalling something went wrong. And finally there’s Unknown, which means the system simply can’t determine the current state of the Pod. That one’s usually a sign of a communication issue between the node and the control plane.

Now let’s look at what a Pod definition actually looks like. If you were to write a basic Pod manifest — that’s the configuration file that tells Kubernetes what to create — it would specify a few key things. You’d declare the type of object you’re creating, in this case a Pod, and give it a name. In this example it’s called example-pod, placed in a namespace called nzrt-prod, with a label identifying it as part of an app. Then under the specification section, you’d define the container itself. Here the container is named app, it’s running an nginx web server at version 1.25, and it’s listening on port 80. You’d also set resource boundaries. In this example, the container requests a minimum of 100 millicores of CPU and 128 megabytes of memory, with a hard ceiling of 500 millicores of CPU and 256 megabytes of memory. Those limits make sure one misbehaving container can’t consume all the resources on your node.

Finally, let’s cover the commands you’ll actually use day to day when working with Pods. There are five core ones to know. The first lists all Pods running in your production namespace, giving you a quick overview of what’s up and what isn’t. The second lets you describe a specific Pod in detail — this is your go-to when something looks wrong, because it surfaces events, container statuses, and resource usage all in one place. Third is the logs command, which streams output from a named Pod so you can see exactly what the application inside is doing, or where it crashed. Fourth is the exec command, which drops you into an interactive shell inside a running Pod — think of it like connecting directly into the container to poke around. And fifth is the delete command, which removes a Pod by name. Just keep in mind that if that Pod is managed by a Deployment, a replacement will start up automatically right after you delete it.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.

Services

Welcome to the NZRT Wiki Podcast. Today we’re looking at Services.

So, what is a Service in Kubernetes? At its core, a Service gives you a stable network endpoint — think of it as a fixed address made up of a DNS name and an IP — for a group of pods. Here’s the thing about pods: they come and go. They spin up, they restart, they get replaced. But the Service address stays constant. That’s the whole point. You point your traffic at the Service, and Kubernetes takes care of routing it to whichever pods are actually running behind the scenes.

Now, not all Services work the same way. There are four types, and choosing the right one depends on what you’re trying to do.

The first type is called ClusterIP, and it’s the default. This one is for internal access only — pod-to-pod communication inside your cluster. Nothing outside the cluster can reach it directly.

The second type is NodePort. This exposes your service on each node’s IP address at a fixed port number. It’s a step up from ClusterIP in that you can reach it from outside the cluster, but it’s fairly manual and better suited for testing or simple setups.

Third is LoadBalancer. This one provisions an actual cloud load balancer — so if you’re running on a cloud provider, Kubernetes will automatically create a load balancer and wire it up to your service. This is your go-to for proper external access in production.

And the fourth type is ExternalName. Rather than routing to pods inside your cluster, this maps your service to an external DNS name. Useful when you need your cluster workloads to talk to something living entirely outside Kubernetes.

Let’s look at what a Service definition actually looks like. The example we have is a ClusterIP service for WordPress, sitting in the nzrt-prod namespace. The definition tells Kubernetes which pods to route traffic to — in this case, any pod labelled as a WordPress app. It then maps port 80 on the Service itself through to port 80 on those pods, using standard TCP. And since no type is explicitly set to something else, it defaults to ClusterIP, meaning internal only.

That’s a pretty typical pattern: you define which pods to target, you declare the port mapping, and you pick your type. Kubernetes handles the rest.

Next up, DNS. Once your Service is running, how do other things in the cluster actually talk to it? Kubernetes gives every service a DNS name that follows a predictable pattern. You take the service name, add the namespace, and then the suffix svc dot cluster dot local. So for the WordPress service in the nzrt-prod namespace, the full address would be wordpress-service dot nzrt-prod dot svc dot cluster dot local. That’s the fully qualified form.

If you’re working from within the same namespace, you can skip most of that and just use the service name on its own. Kubernetes DNS figures out the rest automatically.

Finally, let’s talk about the commands you’ll use most often when working with Services. There are three key ones. The first retrieves a list of all services running in the nzrt-prod namespace — handy for a quick overview of what’s live. The second gives you a detailed description of a specific service — in this case the WordPress service — including its selector, ports, and current state. And the third shows you the endpoints for that service, meaning the actual IP addresses and ports of the pods currently backing it. That last one is especially useful when you’re troubleshooting and you want to confirm that traffic actually has somewhere to go.

So to tie it all together: Services are how Kubernetes gives you a stable, reliable way to reach your pods no matter how many times they restart or get rescheduled. You pick the type that matches your use case — ClusterIP for internal, NodePort or LoadBalancer for external, ExternalName for mapping to outside systems. You write a short manifest, apply it, and from that point on your cluster has a consistent address to work with. DNS handles discovery automatically, and a handful of commands let you inspect and debug everything when you need to.

That’s it for this episode of the NZRT Wiki Podcast. Thanks for listening.