Mastering Kubernetes
上QQ阅读APP看书,第一时间看更新

Running a multi-user cluster

In this section, we will look briefly at the option to use a single cluster to host systems for multiple users or multiple user communities (which is also known as multi-tenancy). The idea is that those users are totally isolated and may not even be aware that they share the cluster with other users. Each user community will have its own resources, and there will be no communication between them (except maybe through public endpoints). The Kubernetes namespace concept is the ultimate expression of this idea.

The case for a multi-user cluster

Why should you run a single cluster for multiple isolated users or deployments? Isn't it simpler to just have a dedicated cluster for each user? There are two main reasons: cost and operational complexity. If you have many relatively small deployments and you want to create a dedicated cluster for each one, then you'll have a separate master node and possibly a three-node etcd cluster for each one. That can add up. Operational complexity is very important too. Managing tens, hundreds, or thousands of independent clusters is no picnic. Every upgrade and every patch needs to be applied to each cluster. Operations might fail and you'll have to manage a fleet of clusters where some of them are in a slightly different state than the others. Meta-operations across all clusters may be more difficult. You'll have to aggregate and write your tools to perform operations and collect data from all clusters.

Let's look at some use cases and requirements for multiple isolated communities or deployments:

  • A platform or service provider for software-as-a-service
  • Managing separate testing, staging, and production environments
  • Delegating responsibility to community/deployment admins
  • Enforcing resource quotas and limits on each community
  • Users see only resources in their community

Using namespaces for safe multi-tenancy

Kubernetes namespaces are the perfect answer to safe multi-tenant clusters. This is not a surprise, as this was one of the design goals of namespaces.

You can easily create namespaces in addition to the built-in kube-system and default. Here is a YAML file that will create a new namespace called custom-namespace. All it has is a metadata item called name. It doesn't get any simpler:

apiVersion: v1
kind: Namespace
metadata:
  name: custom-namespace

Let's create the namespace:

$ kubectl create -f custom-namespace.yaml
namespace/custom-namespace created
$ kubectl get namespaces
NAME               STATUS   AGE
custom-namespace   Active   36s
default            Active   26h
kube-node-lease    Active   26h
kube-public        Active   26h
kube-system        Active   26h

We can see the default namespace, our new custom-namespace, and a few system namespaces prefixed with kube-.

The status field can be Active or Terminating. When you delete a namespace, it will move into the Terminating state. When the namespace is in this state, you will not be able to create new resources in this namespace. This simplifies the clean-up of namespace resources and ensures the namespace is really deleted. Without it, the replication controllers might create new pods when existing pods are deleted.

To work with a namespace, you add the --namespace (or -n for short) argument to kubectl commands. Here is how to run a pod in interactive mode in the custom-namespace namespace:

$ kubectl run trouble -it -n custom-namespace --image=g1g1/py-kube:0.2 --generator=run-pod/v1 bash
If you don't see a command prompt, try pressing enter.
root@trouble:/#

Listing pods in the custom-namespace returns only the pod we just launched:

$ kubectl get pods --namespace=custom-namespace
NAME      READY   STATUS    RESTARTS   AGE
trouble   1/1     Running   0          113s

Listing pods without the namespace returns the pods in the default namespace:

$ kubectl get pods
NAME              READY   STATUS    RESTARTS   AGE
pod-with-secret   1/1     Running   0          11h

Avoiding namespace pitfalls

Namespaces are great, but they can add some friction. When you use just the default namespace, you can simply omit the namespace. When using multiple namespaces, you must qualify everything with the namespace. This can add some burden, but doesn't present any danger.

However, if some users (for example, cluster administrators) can access multiple namespaces, then you're open to accidentally modifying or querying the wrong namespace. The best way to avoid this situation is to hermetically seal the namespace and require different users and credentials for each namespace, just like you should use a user account for most operations on your machine or remote machines and use root via sudo only when you have too.

In addition, you should use tools that help make it clear what namespace you're operating on (for example, shell prompt if working from the command line or listing the namespace prominently in a web interface). One of the most popular tools is kubens (available along with kubectx), available at https://github.com/ahmetb/kubectx.

Make sure that users that can operate on a dedicated namespace don't have access to the default namespace. Otherwise, every time they forget to specify a namespace, they'll operate quietly on the default namespace.