Skip to content

All posts

Engineering

Kubernetes Namespaces

Updated Jim Bugwadia

Kubernetes namespaces are objects that partition a single Kubernetes cluster into multiple virtual clusters. Each namespace gives the names it contains their own scope, so the same object name can be used in different namespaces. Namespaces let several users, teams or applications share one cluster, with separate resource quotas and RBAC permissions for each.

hello 1

Content contributed by CloudYuga; Photo by rawpixel on Unsplash

What is a Kubernetes namespace?

Each Kubernetes namespace provides the scope for the Kubernetes Names it contains. Combine an object’s name with its namespace and every object gets a unique identity across the cluster.

A new Kubernetes cluster is created with three namespaces:

Namespace What it holds
default All resources created in the cluster land here unless you name another namespace. Until someone sets a resource quota for it, the default namespace lets applications run with unbounded CPU and memory requests and limits.
kube-public Resources that are publicly readable by all users. This namespace is generally reserved for cluster usage.
kube-system Objects created by the Kubernetes system and control plane.

To follow the demo below you need basic experience with a Linux/Unix system, some familiarity with Kubernetes, and a Kubernetes cluster to run the commands against.

How do you create a Kubernetes namespace?

Start by listing the namespaces present in the cluster.

$ kubectl get namespaces

NAME          STATUS    AGE
default       Active    5m
kube-public   Active    5m
kube-system   Active    5m

There are two ways to create a namespace: the kubectl create namespace command, or a configuration file.

  • Create a new Kubernetes namespace my-namespace with the command.
$ kubectl create ns my-namespace namespace/my-namespace created
  • List the Kubernetes namespaces again.
$ kubectl get namespace

NAME           STATUS    AGE
default        Active    8m
kube-public    Active    8m
kube-system    Active    8m
my-namespace   Active    3s

To create a Kubernetes namespace from a configuration file instead, write the manifest:

apiVersion: v1
  kind: Namespace
  metadata:
    name: test-ns
  • Deploy the file.
$ kubectl apply -f namespace.yaml 
namespace/test-ns created
  • List the namespaces.
$ kubectl get namespace

NAME           STATUS    AGE
default        Active    18m
kube-public    Active    18m
kube-system    Active    18m
my-namespace   Active    9m
test-ns        Active    2m

What are Kubernetes namespaces used for?

Namespaces have several use cases. These are the main reasons to use them, each covered in its own section below:

Use case What the namespace gives you Kubernetes feature
Partition cluster resources A logical slice of one cluster per user, team or application namespace field, kubectl config set-context
Resource consumption policies Limits on compute and object counts per namespace Resource Quotas
Policies to run resources Access permissions scoped to one namespace Role-based access control (RBAC)
A unique scope for names The same short name can exist in different namespaces Kubernetes Names

Partition cluster resources

Namespaces divide a cluster into logical partitions, so one large Kubernetes cluster can serve multiple users and teams, or a single user with multiple applications. Each user, team or application in a namespace is isolated from those in other namespaces and operates as if it were the sole user of the cluster. Note that namespaces do not provide network segmentation.

Deploy an application in a specific Kubernetes namespace.

Here is how to create a Kubernetes object inside a specific namespace.

  • List the namespaces.
$ kubectl get namespace

NAME           STATUS    AGE
default        Active    18m
kube-public    Active    18m
kube-system    Active    18m
my-namespace   Active    9m
test-ns        Active    2m
  • Create a pod from the following configuration.
apiVersion: v1
kind: Pod
metadata:
  name: mypod
  namespace: my-namespace
  labels:
     app: mypod
spec:
  containers:
  - name: mypod
    image: nginx:alpine

The field namespace: my-namespace sets the Kubernetes namespace, so this pod will be created inside my-namespace.

  • Deploy a pod with the configuration above.
$ kubectl apply -f mypopd.yaml
pod/mypod created
  • List the pods in the my-namespace namespace.
$ kubectl get pod -n my-namespace

NAME      READY     STATUS             RESTARTS   AGE
mypod     1/1       Running            0          16s

Bind a user to a specific namespace

Setting a context binds a user to a specific Kubernetes namespace, which then becomes that user’s default namespace. You can do this by editing the kubeconfig file or with the commands below.

  • Create a Kubernetes namespace for each team: dev, qa and production.
$ kubectl create ns dev # Namespace for Developer team
$ kubectl create ns qa # Namespace for QA team
$ kubectl create ns production # Namespace for Production team
  • Set the context for each user group.
# Bind dev context to dev namespace
$ kubectl config set-context dev --namespace=dev --cluster=kubernetes --user=dev

# Bind qa context to QA namespace
kubectl config set-context qa --namespace=qa --cluster=kubernetes --user=qa

# Bind production context to production namespace
kubectl config set-context production --namespace=prod --cluster=kubernetes --user=production

This binds the Dev team to the dev namespace, the QA team to the qa namespace and the Production team to the production namespace. Each of these namespaces acts as the default namespace for the team assigned to it, so team members don’t have to pass -n on every command. For details on Kubernetes contexts and kubeconfig, see the documentation at kubernetes.io.

Set resource consumption policies with a ResourceQuota

Resource Quotas applied to a namespace limit how much of the cluster a particular set of users can consume. A resource quota limits resource consumption per Kubernetes namespace. It can cap the number of objects of each type created in the namespace, and the total compute resources that its resources may consume.

Here is how to configure a resource quota for a specific namespace.

  • Create a new demo namespace.
$ kubectl create namespace demo
namespace/demo created
  • Create a resource quota object for the demo namespace.
apiVersion: v1
kind: ResourceQuota
metadata:
  name: mem-cpu
  namespace: demo
spec:
  hard:
    requests.cpu: "0.5"
    requests.memory: 512Mi
    limits.cpu: "1"
    limits.memory: 1Gi

In the demo namespace, workloads cannot request more than 0.5 CPU and 512Mi RAM overall. If a pod with a 256Mi request is already running, a new pod that needs more than the remaining 256Mi of memory will not be scheduled. The quota also sets a hard limit of 1 CPU and 1GB RAM for the namespace.

  • Deploy the resource quota object.
$ kubectl apply -f qouta.yaml
resourcequota/mem-cpu created
  • Get detailed information about the resource quota you created.
$ kubectl get resourcequota mem-cpu --namespace=demo --output=yaml

apiVersion: v1
kind: ResourceQuota
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","kind":"ResourceQuota","metadata": {"annotations":{},"name":"mem-cpu","namespace":"demo"},"spec":{"hard":{"limits.cpu":"1","limits.memory":"1Gi","requests.cpu":"0.5","requests.memory":"512Mi"}}}
  creationTimestamp: 2018-11-21T07:05:48Z
  name: mem-cpu
  namespace: demo
  resourceVersion: "6091"
  selfLink: /api/v1/namespaces/demo/resourcequotas/mem-cpu
  uid: dfd1002c-ed5b-11e8-ab3b-507b9d3bd0b6
spec:
  hard:
    limits.cpu: "1"
    limits.memory: 1Gi
    requests.cpu: 500m
    requests.memory: 512Mi
status:
  hard:
    limits.cpu: "1"
    limits.memory: 1Gi
    requests.cpu: 500m
    requests.memory: 512Mi
  used:
    limits.cpu: "0"
    limits.memory: "0"
    requests.cpu: "0"
    requests.memory: "0"

The output shows the hard limits and the resources used so far in the namespace.

What happens when a pod exceeds the quota?

First, deploy a Demo1 application whose resource request fits within the quota set for the namespace.

apiVersion: v1
kind: Pod
metadata:
  namespace: demo
  name: pod-demo1
  labels:
     app: demo1
spec:
  containers:
  - name: demo1
    image: nginx:alpine
    ports:
    - containerPort: 80
    resources:
      limits:
        memory: "400Mi"
        cpu: "0.3"      
      requests:
        memory: "300Mi"
        cpu: "0.2"
  • Deploy the demo1 application.
$ kubectl apply -f demo1.yaml
pod/pod-demo1 created

Its resource request was within the quota’s specification, so the pod was deployed.

  • Now create another pod in the demo namespace whose resource request exceeds the quota, and see what happens.
apiVersion: v1
kind: Pod
metadata:
  namespace: demo
  name: demo-pod2
  labels:
     app: demo
spec:
  containers:
  - name: demo
    image: nginx:alpine
    ports:
    - containerPort: 80
    resources:
      limits:
        memory: "700Mi"
        cpu: "0.6"      
      requests:
        memory: "600Mi"
        cpu: "0.6"
  • Try to deploy the demo2 application.
$ kubectl apply -f demo2.yaml

Error from server (Forbidden): error when creating "demo2.yaml": pods "demo-pod2" is forbidden: exceeded quota: mem-cpu, requested: limits.memory=700Mi,requests.cpu=600m,requests.memory=600Mi, used: limits.memory=400Mi,requests.cpu=200m,requests.memory=300Mi, limited: limits.memory=1Gi,requests.cpu=500m,requests.memory=512Mi

The error occurs because this pod requests more resources than the resource quota allows.

  • Delete the demo namespace. This deletes the namespace along with all the objects running inside it.
$ kubectl delete namespace demo
namespace "demo" deleted
  • Delete the Kubernetes namespaces created earlier.
$ kubectl delete namespace my-namespace test-ns
namespace "my-namespace" deleted
namespace "test-ns" deleted

Access policies and a unique scope for names

With Role-based access control (RBAC), you can control access permissions within a particular Kubernetes namespace. A cluster admin grants permissions to a user or group of users in specific namespaces with a Role Binding.

Namespaces also provide the scope for Kubernetes Names. Inside a namespace, an object can be referred to by a short name like my-app, and the namespace adds further scope to identify it, e.g. my-app.my-namespace. The name of an object must be unique within its namespace, and the combination of name and namespace (e.g. my-app.my-namespace) must be unique at the cluster level.

Summary

Namespaces are how you divide and manage a Kubernetes cluster. They let you logically separate users, teams or applications and assign resources to each. They provide the basic building blocks for resource allowances, access control and isolation. And because one cluster can now run a diverse set of workloads, namespaces help you use cluster resources more efficiently.

Next steps: to apply policies to namespaces as code, see Kyverno and our guide to policy as code. For more Kubernetes basics, read Kubernetes for Developers Part 2: Replica Sets and Deployments.

References

This blog post was contributed by our training partner CloudYuga.
For expert training in Kubernetes, including Kubernetes namespaces, check out their website at https://cloudyuga.guru/.

Discover all that Nirmata’s DevSecOps platform for Kubernetes has to offer by visiting this page.

Frequently asked questions

Do Kubernetes namespaces isolate network traffic?

No. Namespaces scope names, quotas and RBAC permissions, but by default a pod in one namespace can still reach pods in other namespaces over the network. To restrict traffic between namespaces, apply NetworkPolicy resources, which need a network plugin that supports them. Treat a namespace as an administrative boundary, not a security boundary on its own.

Are all Kubernetes objects namespaced?

No. Pods, Services, Deployments and ResourceQuotas live in a namespace, but some resources are cluster-scoped: Nodes, PersistentVolumes, StorageClasses and Namespace objects themselves. Run kubectl api-resources --namespaced=true to list the namespaced kinds, or --namespaced=false to list the cluster-scoped ones. Cluster-scoped objects need names that are unique across the whole cluster.

How do I reach a Service in another namespace?

Use its DNS name. When you create a Service, Kubernetes creates a DNS entry of the form <service-name>.<namespace-name>.svc.cluster.local. A pod that looks up only <service-name> resolves it inside its own namespace, so to call a Service in a different namespace, use at least <service-name>.<namespace-name> or the fully qualified name.

Why does my cluster have a kube-node-lease namespace?

Newer Kubernetes versions create a fourth initial namespace, kube-node-lease, next to default, kube-public and kube-system. It holds one Lease object per node. The kubelet updates its Lease as a heartbeat, which lets the control plane detect node failures without the cost of frequent full Node status updates. You normally don't create anything in it yourself.

Nirmata Control HubOne control plane for Kyverno policies.
ShareXLinkedIn

Stay up-to-date with the latest in AI, governance, and infrastructure

Subscribe to our free monthly newsletter to get industry news, DevOps tips, and articles right to your inbox on Kyverno, containerization, Kubernetes deployment & management and more.