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:
- It provides scope for names
- It has unique names for resources within but not across namespaces
- It does not allow for nesting inside each other
- It is used in an environment with many users spread across multiple teams and projects
- A Kubernetes object can only be in one Namespace
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:
- 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.
- 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).
- 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 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
$ 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
--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
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.
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.