Kubernetes Namespaces

December 9, 2021

Introduction

Various Kubernetes objects like Pods, Deployments, Services etc. were created on a Cluster without structuring in previous parts of this series. If you continue this process, these objects will grow exponentially and become challenging to maintain at some point. So, now is a good time to introduce a concept that will mitigate this effect. Kubernetes NAMESPACE is a virtual cluster for organising and structuring Kubernetes objects to ensure smooth operations and project management.

What Is a Kubernetes Namespace?

A Namespace is a Kubernetes object that helps group and structure other Kubernetes objects and partitions them in a Kubernetes cluster. This concept allows you to organize or isolate your Kubernetes resources in a box-like form according to their purpose across multiple users and projects in a cluster.

Characteristics of Kubernetes Namespaces:

Question:

In one of the previous exercises, a Pod was created without specifying or declaring a namespace, and yet, there was no error; does this mean the Pod was not created in any namespace?

The answer to the question above leads us to the next topic: There are three pre-configured namespaces created by Kubernetes when a cluster is set up, which are:

  1. Default Namespace: Every namespaced Kubernetes object that is created without specifying a namespace goes to the Namespace defined in your client’s configuration. If none are set, objects go to the default Namespace. So, Kubernetes objects that are namespaced are created in a Namespace which could be either the default Namespace or the one specified by the user.
  2. Kube-System Namespace: This Namespace is used for system processes like etcd, kube-scheduler, etc. Do not modify or create any objects in this Namespace, as it is not meant for users (to avoid modifying the resources or deleting the components accidentally).
  3. Kube-public Namespace: This namespace houses publicly accessible data, including a ConfigMap which stores cluster information like the cluster’s public certificate for communicating with the Kubernetes API.

How to Create a Namespace

A Namespace can be created imperatively or declaratively like any other Kubernetes objects. You can read more on the imperative and declarative methods of creating Kubernetes objects in a previous part of this series. 

The steps below will guide you on how to create a Namespace and how to create a Kubernetes object in the Namespace:

Step 1: Create a yaml file with your desired editor:

$ vim dev-space.yaml

Step 2: Copy and paste the below configuration into the yaml file:

apiVersion: v1
kind: Namespace
metadata:
  name: dev   ## name of the namespace

Step 3: Use kubectl create command to create the Namespace:

$ kubectl create -f dev-space.yaml
namespace/dev created

Alternatively, you can also create it imperatively on the command line with the command below:

$ kubectl create namespace prod 
namespace/prod created     ## prod is the Namespace name

Step 4: Check the status of the Namespace with the kubectl command:

$ kubectl get namespaces
NAME              STATUS      AGE
default           Active      16m
dev               Active      6m23s
kube-public       Active      16m
kube-system       Active      16m
prod              Active      5m50s

The output shows that we have five Namespaces - the three pre-configured Namespaces and the two we just created.

Step 5: Check the detailed description of the Namespaces with kubectl describe command:

Name:         dev
Labels:       <none>
Annotations:  <none>
Status:       Active

No resource quota.  ## More about this further on in this post.

No LimitRange resource. ## More about this later on in this post.
------------------------------------------------------------------
Name:         prod
Labels:       <none>
Annotations:  <none>
Status:       Active

No resource quota. 
 
No LimitRange resource. 

The detailed description above shows the name of the Namespaces, which are dev and prod respectively, and the status which is set to active.

How to create Kubernetes Objects in a Namespace

Creating an object in a Namespace depends on the method (declarative or imperative) used to create the object.

If you create a Kubernetes object imperatively, the Namespace where you want to create the object will be transferred as a parameter together with the command on the command line. In the case of the declarative method, the namespace property with its name will be declared in the manifest YAML file. You can find more details in the example below.

Example 1: Create a Deployment with two replicas, one in the dev and one in the prod Namespaces:

$ kubectl create deployment my-app --image=redis --replicas=2 -n dev
deployment.apps/my-app created

or

$ kubectl create deployment my-app --image=redis --replicas=2 --namespace dev
deployment.apps/my-app created

You can either pass a Namespace property as a flag with -n or --namespace; they function the same way. Also, dev here is the name of the Namespace.

Example 2: The above object can be created in the dev namespace in declarative form by specifying a Namespace property in the Deployment manifest YAML file. The configuration will look like this:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  namespace: prod    ## where prod is the name of the namespace
  labels:
    app: my-app
spec:
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - image: nginx
        name: nginx-img

When you create the Deployment with the kubectl create command, it is created in the prod Namespace. Now check the Deployments in their respective namespaces:

$ kubectl get pods -n prod	# Only the Pods in the prod Namespace will be delivered.


NAME                      	READY   STATUS    RESTARTS     AGE
my-app-667cdc9ffb-bkrv4   	 1/1    Running      0         2m32s
my-app-667cdc9ffb-mwn9k   	 1/1    Running      0         2m32s

$ kubectl get pods -n dev 	# Only the Pods in the dev Namespace will be delivered.


NAME                      	READY   STATUS    RESTARTS     AGE
my-app-667cdc9ffb-lmqvn   	 1/1    Running      0         2m40s
my-app-667cdc9ffb-s7sm5   	 1/1    Running      0         2m40s

Connectivity in Namespaces

A Kubernetes object can directly access another object in the same Namespace using its name. For example, a Pod can access a Service in the same Namespace using the name of the Service. Also, a Kubernetes object in a Namespace can access the object in another Namespace but not as easily as when both objects are in the same Namespace. A Pod in the prod Namespace can access a Service in the dev Namespace. It will look like this:

pod-name.(“service-name.namespace-name.svc.cluster.local”), where svc is the Service and cluster.local is the domain.

In addition to unrestricted communication between namespaces, networking between them can be locked down using NetworkPolicies. These allow you to define networking rules that can prevent namespace-to-namespace or pod-to-pod communication, if desired.

Namespaces Resource Quota

Each Namespace can be configured to have its own policy on who can modify, create, or edit an object in the namespace. The permission management model behind this is called RBAC (Role-Based Access Control). Individual role assignments allow different teams to use Namespaces in a shared cluster. Resource limits can also be assigned to a Namespace which will control memory and CPU requests and operations. This will add a defined rather than a general level of restriction per Namespace on the cluster.

Conclusion

The significance of Namespace in object demarcation cannot be overemphasised. Moreover, the advantage of having your applications grouped according to teams and departments to guard against cross-departmental errors when accessing the applications on the cluster makes Namespace usage a lot more attractive in Kubernetes.

Learn More

Seyi Ewegbemi

Seyi Ewegbemi

Student Worker