All writing
Updated 4 min readNaren

Kubernetes objects: Pods, YAML and namespaces

What a Kubernetes object is, how a YAML manifest describes one, and the first two objects you will create, the Pod and the namespace.

The last post set up a local cluster with Minikube or Kind and introduced kubectl. This one covers the building blocks you will create on that cluster: YAML manifests, Pods and namespaces. Everything else in Kubernetes is built on them.

Kubernetes objects

Kubernetes manages objects. An object is a record of intent: it tells Kubernetes what you want the cluster's state to look like. Once you create one, the control plane keeps working to make the cluster's actual state match the desired state you described.

You usually write objects as YAML files. YAML stands for YAML Ain't Markup Language.

YAML manifests

YAML is easy for people to read and good at representing nested data. It lets you describe your resources declaratively: instead of telling Kubernetes how to do something, you tell it what you want.

Almost every Kubernetes manifest has four top-level fields:

  1. apiVersion is the Kubernetes API version the object uses, such as v1 or apps/v1. It tells Kubernetes which set of rules applies to the object.
  2. kind is the type of resource you are creating, such as Pod, Deployment, Service or Namespace.
  3. metadata holds the data that identifies the object, such as its name, namespace and labels.
  4. spec describes the desired state of the object. Its contents change a lot depending on the kind.

YAML uses spaces for indentation, never tabs, and the indentation defines the structure. Keep it consistent: a single misplaced space is enough to make a manifest fail.

Pods

If containers are the bricks of your application, Pods are the smallest houses built from them. A Pod is the smallest deployable unit in Kubernetes, and it wraps:

  • one or more containers
  • shared storage, in the form of volumes
  • a unique IP address
  • options that control how the containers run
Pod Accesses Accesses Uses Uses Container 1 Container 2 Shared Volume Shared Network

Pods are designed to be temporary. When a Pod dies, Kubernetes does not try to heal it. A new Pod replaces it instead, created by a higher-level object such as a Deployment.

Containers in the same Pod share a network namespace, so they can reach each other on localhost using different ports. They can also share storage volumes.

Most Pods hold a single application container. Some hold more than one, usually for the sidecar pattern, where a helper container such as a log shipper or a data synchronizer runs alongside the main application container.

Create your first Pod

This Pod runs an Nginx web server. Save it as nginx-pod.yaml:

# nginx-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: my-nginx-pod
  labels:
    app: nginx
    environment: development
spec:
  containers:
  - name: nginx-container
    image: nginx:latest
    ports:
    - containerPort: 80

Here is what each part does:

  • apiVersion: v1 is the standard API version for Pods.
  • kind: Pod tells Kubernetes to create a Pod.
  • metadata.name gives the Pod a unique name, my-nginx-pod.
  • metadata.labels holds key-value pairs, here app: nginx and environment: development, that organize and identify resources. Labels are how you select and manage groups of objects.
  • spec describes the desired state of the Pod.
  • spec.containers lists the containers to run inside the Pod. This one has a single container named nginx-container, which pulls and runs the nginx:latest image and exposes port 80.

Deploy it to your cluster:

kubectl apply -f nginx-pod.yaml

The output should be pod/my-nginx-pod created.

Check that the Pod is running:

kubectl get pods

my-nginx-pod should show a STATUS of Running. For more detail about the Pod:

kubectl describe pod my-nginx-pod

Delete the Pod using the same file:

kubectl delete -f nginx-pod.yaml

Or by name:

kubectl delete pod my-nginx-pod

You can create Pods directly like this, but in real work you will almost always use a higher-level object such as a Deployment to manage them. Deployments add self-healing, scaling and rolling updates, which any application you depend on needs.

Namespaces

As a cluster grows, it ends up running many applications for different teams and environments, such as development, staging and production. Namespaces keep them apart. You can think of a namespace as a virtual cluster inside your physical cluster.

Namespaces separate resources logically. You can have a Pod named my-app in the development namespace and another Pod named my-app in the production namespace, and they do not conflict.

They also keep a cluster organized when several teams or projects share it.

And they are where you control access and resource use. Resource quotas, which limit CPU and memory use, and role-based access control (RBAC) policies both apply at the namespace level, so different teams or users can get different permissions.

Kubernetes Cluster Namespace A Namespace B Pod A1 Service A1 Pod B1 Service B1

Built-in namespaces

Every cluster comes with a few namespaces already defined:

  • default is where resources go when you don't specify a namespace. It is fine for learning and small experiments, but for serious work, create your own namespaces.
  • kube-system is reserved for objects the Kubernetes control plane creates itself, such as core services like the API server and the scheduler. You generally should not touch anything in it.
  • kube-public holds resources that every user can read.
  • kube-node-lease holds the Lease objects that nodes use as heartbeats.

Working with namespaces

List the namespaces:

kubectl get namespaces
# or
kubectl get ns

You can create a namespace imperatively, with a command:

kubectl create namespace my-dev-namespace

Or declaratively, from a YAML file such as my-dev-namespace.yaml:

# my-dev-namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: my-dev-namespace

Then apply it:

kubectl apply -f my-dev-namespace.yaml

To create a resource in a specific namespace, pass -n or --namespace:

kubectl apply -f nginx-pod.yaml -n my-dev-namespace

To list the resources in a specific namespace:

kubectl get pods -n my-dev-namespace

To delete a namespace:

kubectl delete namespace my-dev-namespace

Deleting a namespace deletes every resource inside it, so be very careful with this command.

The next post moves beyond individual Pods to Deployments and ReplicaSets, which manage and scale your applications for you: Deployments, ReplicaSets, Jobs and CronJobs.