Category Archives: 05 – Storage

Configmaps Secrets

Welcome to the NZRT Wiki Podcast. Today we’re looking at ConfigMaps & Secrets.

If you’ve been working with Kubernetes, you’ve probably run into the question of where to store your application’s configuration. Things like environment names, URLs, log levels, database passwords, API keys — all of that has to live somewhere. Kubernetes gives you two dedicated resources for this: ConfigMaps and Secrets. They work in a similar way, but serve different purposes, and knowing which to use and when matters a lot.

Let’s start with ConfigMaps. A ConfigMap is where you store non-sensitive configuration data. Think of it as a key-value store that your application can read at runtime. In NZRT’s setup, you might have a ConfigMap called app-config sitting in the nzrt-prod namespace. Inside it, you’d find entries like the application environment set to production, the application URL pointing to the NZRT network app endpoint, and a log level set to info. None of that is sensitive — it’s just configuration your app needs to know about.

To actually use that ConfigMap inside a pod, you reference it in your pod definition using something called envFrom. What that does is tell Kubernetes to pull all the key-value pairs from the ConfigMap and inject them into your container as environment variables. Your app then reads them just like any normal environment variable — it doesn’t need to know or care that they came from Kubernetes.

Now let’s talk about Secrets. The concept is the same — key-value pairs injected into a pod — but Secrets are designed for sensitive data. Passwords, usernames, tokens, API keys. In the example from the wiki, there’s a Secret called db-credentials, again in nzrt-prod. It holds a database password and a database username. You’ll notice the wiki uses something called stringData, which means you write the values in plain text in your definition file, and Kubernetes automatically base64-encodes them when it saves them to the cluster. Using a Secret in a pod works exactly the same way as a ConfigMap — you use envFrom, but this time you reference a secretRef instead of a configMapRef. The end result is the same: your container sees those values as environment variables.

Now here’s something really important you need to understand about Secrets, and the wiki flags this clearly. Secrets are not encrypted by default. They’re only base64-encoded when stored in etcd, which is Kubernetes’ internal data store. And base64 is not encryption — it’s just encoding. Anyone with access to etcd can decode those values trivially. So for production environments, you need to go further. There are two main approaches. First, you can enable Encryption at Rest on your cluster, which tells Kubernetes to actually encrypt the Secret data before writing it to etcd. Second, and often better for serious deployments, you use an external secrets manager. Tools like HashiCorp Vault, AWS Secrets Manager, or Sealed Secrets are purpose-built for this and give you much stronger security guarantees, audit trails, and access controls.

Finally, let’s cover a few kubectl commands you’ll use regularly when working with these resources. To list all ConfigMaps in the nzrt-prod namespace, you run kubectl get configmaps with the namespace flag. For Secrets, same structure — kubectl get secrets with the namespace flag. If you want to inspect a specific Secret, you use kubectl describe followed by the Secret name and namespace — this shows you metadata and keys but not the actual values, which is intentional. And if you need to create a Secret quickly from the command line without a YAML file, you can use kubectl create secret generic, give it a name, pass in your key-value pairs using the from-literal flag, and specify your namespace. That’s a handy shortcut for quick setups or testing.

To link this back to broader context, ConfigMaps and Secrets connect closely to the Security Overview and Storage Overview docs in the wiki, so if you want to go deeper on cluster security or how persistent data is handled, those are your next stops.

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

Persistent Volumes

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

If you’ve worked with Kubernetes at all, you’ve probably run into the question of where your data actually lives. Containers are ephemeral by design — when one stops, its local data disappears with it. Persistent Volumes solve that problem, and that’s exactly what we’re covering today.

Let’s start with the two core concepts. A PersistentVolume, or PV, is a storage resource that exists at the cluster level. Think of it as a chunk of storage that Kubernetes knows about and can hand out. A PersistentVolumeClaim, or PVC, is how a workload actually requests that storage. Claims are scoped to a namespace, meaning they live within a specific environment in your cluster, and when you create one, Kubernetes binds it to an available PV that matches what you asked for.

Before you can claim storage, you usually need a StorageClass. This is where dynamic provisioning comes in. The first example in the wiki shows a StorageClass definition. It sets a name — in NZRT’s case that’s called nzrt-standard — and points to a provisioner, which is the component that actually goes and creates the underlying storage. The example uses a placeholder provisioner that you would swap out for your real cloud provider’s provisioner in a live deployment. Two other settings matter here: the reclaim policy is set to Retain, which we’ll come back to shortly, and the volume binding mode is set to wait for the first consumer, meaning storage isn’t actually provisioned until something tries to use it.

Next up is the PersistentVolumeClaim itself. The example shows a claim named nextcloud-pvc, sitting in the nzrt-prod namespace. It requests twenty gigabytes of storage, references the nzrt-standard StorageClass you just defined, and specifies an access mode of ReadWriteOnce. That access mode means only one node in the cluster can mount this volume for reading and writing at a time. That’s fine for something like a Nextcloud instance where you have one primary pod handling file access.

Once you have your claim, you need to attach it to a pod. The third example shows how that works inside a pod specification. You define a volume entry that references your claim by name — nextcloud-pvc in this case — and then inside your container definition, you mount that volume at a specific directory path. Here it’s mounted at the path where Nextcloud expects its web files to live. From the container’s point of view, it just sees a regular folder. The fact that it’s backed by persistent storage is completely transparent to the application.

Now let’s talk about the commands you’ll use day to day. You can list all persistent volumes across the cluster, list all claims within the nzrt-prod namespace specifically, pull up a detailed description of a particular claim to check its status or spot any error messages, and list all available StorageClasses. Those four commands cover most of what you need for routine inspection and troubleshooting.

Finally, reclaim policies — and this one is worth paying close attention to before you start deleting things. The wiki covers three options. Retain means that when you delete a PVC, the underlying PV stays intact and its data is preserved, but you are responsible for cleaning it up manually. Delete means that when the claim is removed, Kubernetes automatically removes the PV and all the backing storage with it. And Recycle is a third option that exists mostly as a historical footnote — it is deprecated, so don’t use it.

For most production workloads at NZRT, Retain is the safer default because it protects you from accidental data loss. Delete makes sense only when you are confident that automatically removing the data is acceptable, such as with temporary or test environments.

If you want to go deeper, the related topics in the wiki are Storage Overview and StatefulSets. StatefulSets in particular pair closely with Persistent Volumes when you need stable, predictable storage for applications that need to remember their state across restarts.

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

Storage Overview

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

If you’ve worked with Kubernetes before, you’ve probably noticed that it goes out of its way to separate your applications from the details of where their data actually lives. That’s the core idea behind Kubernetes storage — it abstracts the underlying storage system away from your workloads, so your pods don’t need to know whether their data is sitting on a local disk, a network drive, or a cloud volume. They just ask for storage, and Kubernetes handles the rest.

Let’s walk through how that actually works, because there’s a clear hierarchy to understand here. Think of it as a chain of four layers, each one sitting on top of the next.

At the top of that chain is something called a StorageClass. This is essentially a template or a definition that says “here’s the type of storage we can provision, and here’s how to provision it.” It points to a provisioner — the thing that actually knows how to create storage on your underlying infrastructure.

Beneath the StorageClass sits the PersistentVolume, or PV. This is the actual storage resource — the real chunk of space that exists in your cluster. It can be created manually by an administrator, or it can be created automatically and dynamically by Kubernetes using the StorageClass you just defined.

Below the PersistentVolume is the PersistentVolumeClaim, or PVC. This is how a pod makes a request for storage. Instead of pointing directly at a specific volume, a pod says “I need some storage with these characteristics” — and the PVC is that request. Kubernetes then matches the claim to an appropriate PersistentVolume.

And finally, at the bottom of the chain, you have the Pod itself. The pod mounts the PVC as a volume, and from that point on it just reads and writes files like normal. It never needs to know anything about the StorageClass or the underlying PersistentVolume that made it all possible.

So to put it simply — StorageClass defines how to make storage, PersistentVolumes are the actual storage, PersistentVolumeClaims are how pods ask for it, and Pods consume it.

Now let’s look at the five key storage objects you’ll encounter in Kubernetes. There are five of them, each with a distinct purpose.

First, the PersistentVolume — this is a cluster-level resource. It represents actual storage, and it can be provisioned manually by an admin or created dynamically when a claim comes in.

Second, the PersistentVolumeClaim — this operates at the namespace level. It’s the pod’s way of saying “I need storage,” and Kubernetes binds it to a matching PersistentVolume.

Third, the StorageClass — this is the provisioner definition. When dynamic provisioning is enabled, Kubernetes uses the StorageClass as a blueprint to create new PersistentVolumes on demand.

Fourth, the ConfigMap — this is how you inject non-sensitive configuration data into your pods. Think of it as key-value pairs that your application can read at runtime, without baking that configuration into your container image.

And fifth, the Secret — this is similar to a ConfigMap, but intended for sensitive data like passwords, tokens, and certificates. One important thing to know here: Secrets are base64-encoded by default, but they are not encrypted. Base64 is an encoding format, not a security measure — so if you need proper encryption at rest, that requires additional configuration in your cluster.

The last thing to understand is access modes — these define how a volume can be mounted across nodes in your cluster. There are three modes to know about.

ReadWriteOnce means only one node can mount that volume with read-write access at a time. This is the most common mode and suits most standard workloads.

ReadOnlyMany means the volume can be mounted as read-only across many nodes simultaneously. Useful when multiple pods need to read shared data but none of them need to write.

ReadWriteMany means many nodes can mount the volume with full read-write access at the same time. This requires storage backends that explicitly support it — not all do — so check your provider’s documentation before assuming this is available.

If you want to dive deeper, the related topics from this wiki page include Persistent Volumes, which goes into the full lifecycle of PV creation and binding, ConfigMaps and Secrets, which covers how to use those objects in practice, and StatefulSets, which is where storage gets especially interesting because StatefulSets are designed for workloads that need stable, persistent storage across restarts.

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