Part 2

Organizing a cluster

As you can imagine, there may be a lot of resources inside a cluster. In fact, at the moment of writing this Kubernetes supports over 100 000 pods in a single cluster.

Namespaces

Namespaces are used to keep resources separated. A company which uses 1 cluster but has multiple projects can use namespaces to split the cluster into virtual clusters, one for each project. Most commonly they would be used to separate environments such as production, testing, staging. DNS entry for services includes the namespace so you can still have projects communicate with each other if needed through service.namespace address. e.g if the example-service from a previous section was in a namespace "ns-test" it could be found from other namespaces via "http://example-service.ns-test".

Accessing namespaces with kubectl is achieved by using the -n flag. For example, you can see what the namespace kube-system has with

$ kubectl get pods -n kube-system

To see everything you can use --all-namespaces.

$ kubectl get all --all-namespaces

Namespaces should be kept separate - you could run all of the examples and do the exercises of this course in a cluster that is shared with critical software. An administrator should set a ResourceQuota for that namespace so that you can safely run anything there. We'll look into resource limits and requests later.

Defining a namespace is a oneliner, but requires the namespace not to exist already (kubectl create namespace example-namespace):

...
metadata:
  namespace: example-namespace
  name: example
...

If you're using a namespace constantly, you can set the namespace to be used by default with kubectl config set-context --current --namespace=<name>.

Kubernetes Best Practices - Organizing Kubernetes with Namespaces

Labels

Labels are used to separate an application from others inside a namespace and to group different resources together. Labels are key-value pairs and they can be modified, added or removed at any time. Labels are identifying and you can query resources that have a certain label.

Let's look at the labels in Deployment yamls. This is the first yaml we created:

deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hashgenerator-dep
spec:
  replicas: 1
  selector:
    matchLabels:
      app: hashgenerator
  template:
    metadata:
      labels:
        app: hashgenerator
    spec:
      containers:
        - name: hashgenerator
          image: jakousa/dwk-app1:78031863af07c4c4cc3c96d07af68e8ce6e3afba

The selector and matchLabels reveal that the instructions of the deployment are directed to pods with the following label. matchLabels is a key-value pair but we could've used matchExpressions instead. While the template metadata includes a label with key-value pair app and hashgenerator. We can use the same label on multiple namespaces and the namespace would keep them from interfering with each other.

Grouping is simple. Either add the label into the file or if you've already deployed the hashgenerator above add the label and you can query with -l.

$ kubectl label po hashgenerator-dep-7b9b88f8bf-lvcv4 examplelabel=smart
  pod/hashgenerator-dep-7b9b88f8bf-lvcv4 labeled

$ kubectl get po -l examplelabel=smart
  NAME                                 READY   STATUS    RESTARTS   AGE
  hashgenerator-dep-7b9b88f8bf-lvcv4   1/1     Running   0          17m

With labels we can even move pods to labeled nodes. Let's say we have a few nodes which have qualities that we wish to avoid. For example they might have a slower network. With labels and nodeSelector configured to deployment we can do just that. First add nodeSelector to the deployment and then label the node(s):

deployment.yaml

    ...
    spec:
      containers:
        - name: hashgenerator
          image: jakousa/dwk-app1:78031863af07c4c4cc3c96d07af68e8ce6e3afba
      nodeSelector:
        networkquality: excellent

If you already had it running, it won't move the pod to avoid unwanted changes in the system. We'll delete the pod so that Kubernetes will move the new version to the correct node.

$ kubectl delete po hashgenerator-dep-7b9b88f8bf-tnvfg
  pod "hashgenerator-dep-7b9b88f8bf-tnvfg" deleted

$ kubectl get po
  NAME                                 READY   STATUS    RESTARTS   AGE
  hashgenerator-dep-7b9b88f8bf-lvcv4   0/1     Pending   0          4s

Now the status is "Pending" as there are no nodes with an excellent network quality. Next, label the agent-1 as being one with excellent network quality and Kubernetes will know where the pod is able to run .

$ kubectl label nodes k3d-k3s-default-agent-1 networkquality=excellent
  node/k3d-k3s-default-agent-1 labeled

$ kubectl get po
  NAME                                 READY   STATUS    RESTARTS   AGE
  hashgenerator-dep-7b9b88f8bf-lvcv4   1/1     Running   0          5m30s

nodeSelector is a blunt tool. Let's say you have a cluster of various machines, ranging from a fighter jet to a toaster to a supercomputer. Kubernetes can use affinity and anti-affinity to select which nodes are prioritized for which applications and taints with tolerances so that a pod can avoid certain nodes. For example, if a machine has a high network latency and we wouldn't want it to do some latency critical tasks.

See affinity and anti-affinity and taints and tolerances for detailed information. We will not be assigning pods to specific nodes on this course, as we have a homogeneous cluster.

:
Loading...
:
Loading...

Login to view the exercise

You have reached the end of this section! Continue to the next section: