Learn KOP - Create Isolation Boundaries for dedicated clusters - Rafay Product Documentation

Shared clusters

What Will You Do

In this part of the self-paced exercise, we will focus on the following use case:

Clusters are shared between teams. Platform teams want to enforce governance controls but not at the cost of slowing down application teams.

For this example, we will consider two teams, alpha and beta sharing a cluster, shared-cluster.

  1. Step 1: Create a "central" project for infrastructure management and to enforce governance (through blueprints etc.)
  2. Step 2: Create projects for the two teams (e.g. alpha & beta)
  3. Step 3: Import the shared cluster to the "central" project by applying the bootstrap
  4. Step 4: Share the imported cluster with projects, alpha and beta. Apply resource quotas
  5. Step 5: Add labels to existing namespaces in the imported cluster to align with the teams that own and operate them
  6. Step 6: Create a blueprint with "namespace sync on" and apply it to the cluster
  7. Step 7: Verify that the namespaces are imported to the right projects and are healthy
  8. Step 8: Create "project specific roles" for users in alpha/beta teams and verify access

Declarative specifications are also provided for this exercise.

Step 1: Create a central project for the platform team

Step 2: Create projects for the two teams

Step 3: Import the shared cluster to the "central" project

Use kubectl to apply the "cluster bootstrap" file on your K8s cluster.

kubectl apply -f  [path to file]/shared-cluster-alpha-beta-bootstrap.yaml

This will create a namespace for the k8s mgmt operator, download the container images, and register with the controller. This one time import process can take ~2 minutes.

namespace/rafay-system created
serviceaccount/system-sa created
clusterrole.rbac.authorization.k8s.io/rafay:manager created
clusterrolebinding.rbac.authorization.k8s.io/rafay:rafay-system:manager-rolebinding created
clusterrole.rbac.authorization.k8s.io/rafay:proxy-role created
clusterrolebinding.rbac.authorization.k8s.io/rafay:rafay-system:proxy-rolebinding created
priorityclass.scheduling.k8s.io/rafay-cluster-critical created
role.rbac.authorization.k8s.io/rafay:leader-election-role created
rolebinding.rbac.authorization.k8s.io/rafay:leader-election-rolebinding created
customresourcedefinition.apiextensions.k8s.io/namespaces.cluster.rafay.dev created
customresourcedefinition.apiextensions.k8s.io/tasklets.cluster.rafay.dev created
customresourcedefinition.apiextensions.k8s.io/tasks.cluster.rafay.dev created
service/controller-manager-metrics-service-v3 created
deployment.apps/controller-manager-v3 created
configmap/connector-config-v3 created
configmap/proxy-config-v3 created
deployment.apps/rafay-connector-v3 created
service/rafay-drift-v3 created
validatingwebhookconfiguration.admissionregistration.k8s.io/rafay-drift-validate-v3 created

Once the k8s operator is operational, it will "establish and maintain a heartbeat" with the controller.

Step 4: Share the imported cluster and apply resource quotas

Share the imported cluster

Apply resource quotas

Important: Project Resource quotas ensure that the cluster resource utilization within that specific project context never exceeds the configured limit. This makes sure that teams cannot consume resources (more than what is assigned) and impact other teams with whom the cluster is being shared. Repeat the same exercise for project beta.

Step 5: Add labels to existing namespaces

In this specific example, we have two existing namespaces (alpha1, alpha2) in the shared cluster that belong to the alpha team and two existing namespaces (beta1, beta2) that belong to the beta team. There is also an "infra" namespace where common services such as security tooling etc. have been installed by the platform.

kubectl get ns
NAME              STATUS   AGE
alpha1            Active   89s
alpha2            Active   86s
beta1             Active   82s
beta2             Active   79s
default           Active   62m
infra             Active   66s
kube-node-lease   Active   62m
kube-public       Active   62m
kube-system       Active   62m
rafay-system      Active   25m

The platform offers a namespace reconciliation feature that can synchronize existing namespaces to the platform and convert them into managed namespaces. As part of this process, we would want to make sure that namespaces alpha1/alpha2 get synchronized to alpha project and namespaces beta1/beta2 and beta project.

In order to do this, add k8smgmt.io/project label with the project name to each of the namespaces.

kubectl label ns alpha1 k8smgmt.io/project=alpha
kubectl label ns alpha2 k8smgmt.io/project=alpha
kubectl label ns beta1 k8smgmt.io/project=beta
kubectl label ns beta2 k8smgmt.io/project=beta

If the label is not added, the namespace gets synchronized to the parent project (which is "central" project in this case). We will not add a label to "infra" namespace, it will be synchronized to the central project.

Step 6: Apply a blueprint with "namespace sync on"

Step 7: Verify that namespaces are imported to the right projects

Navigate to the namespaces page in the central project. You should be able to see the "infra" namespace listed within this project context.

You should be able to similarly see alpha1/alpha2 namespaces in alpha project and beta1/beta2 namespaces in beta project.

Step 8: Create "project specific roles" for users

The workspace admin role allows the user to:

All of these actions listed above can be performed within their specific project context (i.e. they cannot delete namespaces belong to other teams in the shared cluster etc.) and is also constrained by the governance controls put in place by the platform teams (e.g. creation of a new namespace is blocked if the project resource quota is exceeded).

Recap

Congratulations! At this point, you have successfully leveraged "Projects" and "Workspace as a service" capabilities to achieve isolation between two teams that share a cluster.