Today, we will look at Namespaces.
Namespaces give us an option to divide our Kubernetes cluster to multiple virtual clusters. This may be useful if you want to create different environments, for example for Prod, Dev, and Test, or if you want to assign specific permissions and policies to users. It also allows you to define resource quotas, defining how many resources can a given namespace use.
Before we start creating custom namespaces, we can have a look at namespaces that already exist in our cluster by running kubectl get namespaces command:
kubectl get namespaces NAME STATUS AGE default Active 83d kube-node-lease Active 83d kube-public Active 83d kube-system Active 83d
- Default namespace, as its name suggest, is a location where all of the objects get created, unless they have another namespace specified. This is where all of our Pods, Services, and Deployments live.
- kube-node-lease contains node lease objects.
- kube-public is readable by all users publicly.
- kube-system runs system components, such as DNS.
Note: It is worth to mention that not ALL objects are namespaced, such as namespaces themselves or nodes. To get a full list, run kubectl api-resources:
kubectl api-resources NAME SHORTNAMES APIVERSION NAMESPACED KIND bindings v1 true Binding componentstatuses cs v1 false ComponentStatus configmaps cm v1 true ConfigMap endpoints ep v1 true Endpoints events ev v1 true Event limitranges limits v1 true LimitRange namespaces ns v1 false Namespace nodes no v1 false Node ...
To see objects running in a specific namespace, you can add –namespace after the commands we have been using previously.
For example, to see all pods running in the kube-system namespace, we can run the following:
kubectl get pods --namespace kube-system NAME READY STATUS RESTARTS AGE calico-kube-controllers-c6f659bdc-8bjnm 1/1 Running 0 20d calico-node-jvbcx 1/1 Running 1 20d calico-node-lvrvx 1/1 Running 0 20d calico-node-mqhgb 1/1 Running 0 20d coredns-5664fbb6d6-ffbmr 1/1 Running 0 29d coredns-5664fbb6d6-rftmq 1/1 Running 0 29d csi-linode-controller-0 4/4 Running 2 5d14h csi-linode-node-5bn6f 2/2 Running 1 5d14h csi-linode-node-fpsp8 2/2 Running 0 5d14h csi-linode-node-tbgrw 2/2 Running 0 5d14h kube-proxy-8gwb6 1/1 Running 0 20d kube-proxy-pvfnf 1/1 Running 0 20d kube-proxy-t2jfv 1/1 Running 0 20d metrics-server-5556757555-vrrzq 1/1 Running 0 56d
Creating a new Namespace
Now that we know which namespaces we already have in place, we can proceed with creating a new Namespace.
Let’s say I have a junior member of staff called Lily. I want to create an environment for her that she can use to play with.
First, we will create it:
kubectl create namespace playpen namespace/playpen created kubectl get namespaces NAME STATUS AGE default Active 83d kube-node-lease Active 83d kube-public Active 83d kube-system Active 83d playpen Active 8s
We will now deploy a simple pod to this namespace. As we mentioned previously, there are imperative ways of achieving this by using the –namespace flag, but we will stick to declarative way and define our namespace by adding it to pod definition.
We will create a new file called lilypod.yml and enter the following details:
apiVersion: v1 kind: Pod metadata: name: lily-pod namespace: playpen spec: containers: - name: busybox image: busybox command: ['sh', '-c', 'while true; do sleep 3600; done']
Next we’ll deploy it:
kubectl create -f lilypod.yml pod/lily-pod created
If we now look for our pod, we will not be able to see it:
kubectl get pods |grep lily
This is because at the moment, we are looking into the Default namespace:
kubectl config get-contexts CURRENT NAME CLUSTER AUTHINFO NAMESPACE kind-kind kind-kind kind-kind * lke27049-ctx lke27049 lke27049-admin default
To see Lily’s pod, we can use the –namespace flag to list it:
kubectl get pods --namespace playpen NAME READY STATUS RESTARTS AGE lily-pod 1/1 Running 0 7m4s
Another way is to switch our context to the newly created namespace. This will be also handy if we plan on doing more work in that namespace:
kubectl config set-context --current --namespace playpen Context "lke27049-ctx" modified. kubectl get pods NAME READY STATUS RESTARTS AGE lily-pod 1/1 Running 0 9m11s
Adding Resource Quotas
As I mentioned in the beginning, we can use Resource Quotas to define how many resources can a namespace use. For example, it allows us to define how much RAM or CPU can an object request or use, how much storage can be consumed, but also how many objects can be deployed in the namespace.
To demonstrate this behaviour, we will first confirm that there are no quotas set in our namespace. This is the default configuration:
kubectl describe namespace playpen Name: playpen Labels: <none> Annotations: <none> Status: Active No resource quota. No LimitRange resource.
We will now create a Resource Quota called object-quota.yml, in which we will define that we want to only allow 2 pods to be created in this namespace:
apiVersion: v1 kind: ResourceQuota metadata: name: object-counts spec: hard: pods: "2"
Next we will create this quota:
kubectl create -f object-quota.yml resourcequota/object-counts created
When we look at our namespace again, we will see that Quotas have been added:
kubectl describe namespace playpen Name: playpen Labels: <none> Annotations: <none> Status: Active Resource Quotas Name: object-counts Resource Used Hard -------- --- --- pods 1 2 No LimitRange resource.
If we now try to deploy another pod (using the same lilypod.yml, just changing the name), we should be able to:
kubectl create -f lilypod.yml pod/lily-pod2 created
We will see that we have already reached the limit in our namespace description:
kubectl describe namespace playpen Name: playpen Labels: <none> Annotations: <none> Status: Active Resource Quotas Name: object-counts Resource Used Hard -------- --- --- pods 2 2 No LimitRange resource.
Let’s see what happens if we try to deploy another pod:
kubectl create -f lilypod.yml Error from server (Forbidden): error when creating "lilypod.yml": pods "lily-pod3" is forbidden: exceeded quota: object-counts, requested: pods=1, used: pods=2, limited: pods=2
The third pod failed to create as it would violate our defined quota. We will still be able to see our two previously deployed pods running successfully:
kubectl get pods NAME READY STATUS RESTARTS AGE lily-pod 1/1 Running 0 23m lily-pod2 1/1 Running 0 28s
We have now demonstrated how object quotas work.
Defining resource consumption quotas requires a bit more configuration so we will look into that in the next post.