Continuing with our theme of organization, kubernetes allows us to think of the cluster as a set of virtual clusters using Namespaces.

What is a Namespace?

A namespace is a logical separation between resources in the same kubernetes cluster.

The word logical implies that there is no physical separation between resources in different namespaces. Resources in different namespaces may talk to each other.

The constraint then, is for the viewer (user). Using RBAC, you can limit a user to only be able to access and deploy to a particular namespace. As a user he/she considers his/her namespace to be all-in-all.

In the post on resources we learnt how kubectl create cannot a create a pod with the same name as an already existing pod. Using namespaces we can!

Things to remember

  1. There is no physical separation between resources. They can talk to each other if they wish to do so.
  2. Users can be given namespace-specific roles as well as roles that span across all namespaces
    1. By default your user in Minikube can access all namespaces.
  3. There are some resources that are outside namespaces, such as nodes etc.
  4. Resources in different namespaces can share the same nodes.

Default namespaces

By default, kubernetes creates 4 namespaces. To see available namespaces you can do kubectl get namespaces

param@param-Inspiron-7560:~$ kubectl get namespaces
NAME              STATUS   AGE
default           Active   5d16h
kube-node-lease   Active   5d16h
kube-public       Active   5d16h
kube-system       Active   5d16h

If you specify no namespace, you will deploy to default namespace. All kubernetes services are deployed in kube-system namespace. kube-node-lease is specifically for lease objects which each node creates to help with status updates. kube-public is a publicly readable namespace (even for unauthenticated users). If you do not specify a namespace when issuing a command default namespace is assumed.

Resources in Namespaces

To view resources in namespaces use the command line option -n in kubectl

$ kubectl get pods -n default
NAME         READY   STATUS    RESTARTS   AGE
centos-pod   1/1     Running   1          2d9h
junk-pod     1/1     Running   1          2d9h
ubuntu-pod   1/1     Running   1          2d9h
$ kubectl get pods -n kube-system
NAME                          READY   STATUS    RESTARTS   AGE
coredns-6955765f44-7hjbw      1/1     Running   6          5d17h
coredns-6955765f44-j8tzv      1/1     Running   6          5d17h
etcd-m01                      1/1     Running   6          5d17h
kube-apiserver-m01            1/1     Running   7          5d17h
kube-controller-manager-m01   1/1     Running   6          5d17h
kube-proxy-9d2sw              1/1     Running   6          5d17h
kube-scheduler-m01            1/1     Running   6          5d17h
storage-provisioner           1/1     Running   11         5d17h

To view resources in all names spaces use the option –all-namespaces.

$ kubectl get pods --all-namespaces
NAMESPACE     NAME                          READY   STATUS    RESTARTS   AGE
default       centos-pod                    1/1     Running   1          2d9h
default       junk-pod                      1/1     Running   1          2d9h
default       ubuntu-pod                    1/1     Running   1          2d9h
kube-system   coredns-6955765f44-7hjbw      1/1     Running   6          5d17h
kube-system   coredns-6955765f44-j8tzv      1/1     Running   6          5d17h
kube-system   etcd-m01                      1/1     Running   6          5d17h
kube-system   kube-apiserver-m01            1/1     Running   7          5d17h
kube-system   kube-controller-manager-m01   1/1     Running   6          5d17h
kube-system   kube-proxy-9d2sw              1/1     Running   6          5d17h
kube-system   kube-scheduler-m01            1/1     Running   6          5d17h
kube-system   storage-provisioner           1/1     Running   11         5d17h

Switching Namespaces like a boss

If you plan to work on a particular namespace exclusively you can tell kubectl to do that with the below command

kubectl config set-context --current --namespace=<insert-namespace-name-here>

Also do take a look at these tools which provide a UI to choose the context and the Namespace. (Only useful if you have many contexts, and many namespaces)

Kubectx and kubens : https://github.com/ahmetb/kubectx

Lets see how we can use namespaces with a real-world example!.

The Tale of Two Teams

Alice and Bob are TechLeads of 2 teams called “Alice” and “Bob” and each has 1 service called (you guessed it!) “Alice” and “Bob” (Narcissism rules in Tech). Your infra team has created a SuperDuperInfraPod which has to be installed, once for each Team. You also are sick of listening to Alice and Bob constantly complaining about each other. You don’t think much about the other engineers (as usual) and so have given both teams instructions to use this pod specification verbatim.

apiVersion: "v1"
kind: Pod
metadata:
  name: superduperinfra
  labels:
    app: superduperinfra
    version: v5
    role: backend
spec:
  containers:
  - name: ubuntu-container
    image: ubuntu
    command: ["/bin/bash"]
    args: ["-c", "while [ \"a\" = \"a\" ]; do echo \"All your pods are belong to us\"; sleep 5; done" ]

Here are alice and bob pod specifications. Please treat these as highly confidential.

apiVersion: "v1"
kind: Pod
metadata:
  name: alice
  labels:
    app: alice
    version: v5
    role: backend
spec:
  containers:
  - name: ubuntu-container
    image: ubuntu
    command: ["/bin/bash"]
    args: ["-c", "while [ \"a\" = \"a\" ]; do echo \"alice is the best\"; sleep 5; done" ]
apiVersion: "v1"
kind: Pod
metadata:
  name: bob
  labels:
    app: bob
    version: v5
    role: backend
spec:
  containers:
  - name: ubuntu-container
    image: ubuntu
    command: ["/bin/bash"]
    args: ["-c", "while [ \"a\" = \"a\" ]; do echo \"Bob is the best\"; sleep 5; done" ]

Deploying Alice And Bob

You first need to create the namespaces. Lets think of some good names! How about “Alice’s team” and “Bob’s team”? perfect!

$ kubectl create namespace "alice's team"
The Namespace "alice's team" is invalid: metadata.name: Invalid value: "alice's team": a DNS-1123 label must consist of lower case alphanumeric characters or '-', and must start and end with an alphanumeric character (e.g. 'my-name',  or '123-abc', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?')

That sucks, you are only allowed [a-z][0-9] and -. Lets try again.

$ kubectl create namespace "alices-team"
namespace/alices-team created
$ kubectl create namespace "bobs-team"
namespace/bobs-team created
$ kubectl get namespaces
NAME              STATUS   AGE
alices-team       Active   21s
bobs-team         Active   13s
default           Active   5d18h
kube-node-lease   Active   5d18h
kube-public       Active   5d18h
kube-system       Active   5d18h 

Lets deploy alice and bob services to their respective namespaces

$ kubectl create -f alice.yml -n alices-team
pod/alice created
$ kubectl create -f bob.yml -n bobs-team
pod/bob created

Quick check to see if everything is running.

param@param-Inspiron-7560:~/repos/kubernetes101$ kubectl get pods -n bobs-team
NAME   READY   STATUS    RESTARTS   AGE
bob    1/1     Running   0          2m32s
param@param-Inspiron-7560:~/repos/kubernetes101$ kubectl get pods -n alices-team
NAME    READY   STATUS    RESTARTS   AGE
alice   1/1     Running   0          2m58s

By using proper permissions we can restrict Alice’s team to only see the namespace alices-team and Bob’s team to only see the namespace bobs-team.

Finally lets create the SuperDuperInfraPod in both namespaces.

$ kubectl create -f superduperinfra.yml -n alices-team
pod/superduperinfra created
$ kubectl create -f superduperinfra.yml -n bobs-team
pod/superduperinfra created
$ kubectl get pods -n alices-team
NAME              READY   STATUS    RESTARTS   AGE
alice             1/1     Running   0          6m9s
superduperinfra   1/1     Running   0          16s
$ kubectl get pods -n bobs-team
NAME              READY   STATUS    RESTARTS   AGE
bob               1/1     Running   0          5m53s
superduperinfra   1/1     Running   0          14s

Learnings

Namespace is only a logical separation. They can still talk to each other.

Try not to name your services and teams by the Tech Lead’s name. (I know its hard)

Pods and Resources in different namespace can have the same name.

Users can be configured to have access only to specific namespaces.

In a company I worked for, we had a service called Kingsly which handled certificate expiry, because, before the service, Kingsly used to do it. Good joke, but the first question every engineer asks at onboarding is Why Kingsly? Even worse, if someone has an issue with Kingsly, they, by default, ping Kingsly who no longer works on that service!

Conclusion

Labels and Namespaces are ways to organize your kube-cluster. Right now you may be thinking of a pod here or a service there, but very soon you will be dealing with 10000s of pods. There is much pain to be avoided here!

The logical structure of your cluster(s) should follow the structure of your org. When you are a single team then there is no need for namespaces. When the team splits though, you need to setup proper separation and interfaces. Namespaces and labels are here to help. A little thought can save a lot of pain later.

In the next post we will look at setting up Roles based on Namespaces.