Skip to content

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.

sequenceDiagram
  Admin->> Controller: Step 1: Create a "central" project for infrastructure management and to enforce governance (through blueprints etc.)
  Admin->> Controller: Step 2: Create projects for the two teams (e.g. alpha & beta)
  Admin->> Cluster: Step 3: Import the shared cluster to the "central" project by applying the bootstrap
  Admin->> Controller: Step 4: Share the imported cluster with projects, alpha and beta. Apply resource quotas
  Admin->> Cluster: Step 5: Add labels to existing namespaces in the imported cluster to align with the teams that own and operate them
  Admin->> Controller: Step 6: Create a blueprint with "namespace sync on" and apply it to the cluster
  Admin->> Controller: Step 7: Verify that the namespaces are imported to the right projects and are healthy
  Admin->> Controller: 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

  • Login into your Org as an Org Admin
  • Click on New Project

New Project

  • Provide the name for the project (e.g. central) and a suitable description

Project Name & Description

  • Click Create

Step 2: Create projects for the two teams

  • Click on New Project
  • Provide names for the projects (e.g. alpha and beta) and a suitable description
  • Click Create

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

  • Navigate to project central
  • Click on New Cluster

Create cluster

  • Select Import Existing Kubernetes Cluster
  • Click Continue
  • Select Environment and Kubernetes Distribution as appropriate
  • Provide a cluster name (e.g. shared-cluster-alpha-beta) and description as needed

Create cluster

  • Click Continue
  • We will keep the Blueprint selection as minimal for now, click Continue
  • Download the cryptographically unique bootstrap YAML required to register the cluster

Bootstrap

  • Apply bootstrap to the clusters to initiate the import process

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.

Imported cluster


Step 4: Share the imported cluster and apply resource quotas

Share the imported cluster

  • Navigate to central project
  • Click on the gear icon next to the shared cluster (e.g. shared-cluster-alpha-beta) and select the Manage Cluster Sharing option from the dropdown

Share cluster

  • Select the Specific Projects options for Sharing
  • Select alpha and beta from the list

Share cluster

  • Click Save

Apply resource quotas

  • Click on the gear icon next to project alpha in the listing page

Share cluster

  • Click on the Resource Quotas tab
  • Configure Project Limit (per cluster limit) and Namespace Limit as appropriate

Share cluster

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"

  • Navigate to the central project
  • Click on New Blueprint

Blueprint

  • Provide a name (e.g. central-blueprint) and an appropriate description
  • Click Save
  • Provide a version name (e.g. v1), select minimal as the base blueprint
  • Turn the Enable Namespace Sync on

Blueprint

  • Click Save Changes

  • Navigate to the shared cluster (e.g. shared-cluster-alpha-beta)

  • Click on the gear icon next to the cluster and select the Update Blueprint option from the dropdown

Blueprint

  • Select the blueprint and the version (e.g. central-blueprint, v1)
  • Click Save and Publish
  • Wait for the Blueprint sync process to complete

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.

Namespace

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

Namespace

Namespace


Step 8: Create "project specific roles" for users

  • Login into your Org as an Org Admin
  • Navigate to System -> Users
  • Click on New User
  • Input appropriate details (do not add any groups as yet)

Create New User

  • Click Save & Exit
  • You will see a pop-up stating that the user has not been assigned to any groups. Select Yes to continue
  • Select the user that was just created
  • Click on the Projects tab
  • Select Assign User To Project

Assign User

  • Select alpha project from the dropdown on the left
  • Select the Workspace Admin role

Assign Role

  • Click Save & Exit

  • Log out of the console now and log in as the user that was created

  • You can now notice that the user only has access to alpha project and cannot view project beta or project central (and the resources in those projects)

alpha project only

user profile

The workspace admin role allows the user to:

  • Create a new namespace
  • Update resource quotas on existing namespaces
  • Delete an existing namespace

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.


Step 1: Create a central project for the platform team

You can alternatively create projects by using the declarative spec. For more information on automation via RCTL CLI, refer here.

apiVersion: system.k8smgmt.io/v3
kind: Project
metadata:
  description: for infrastructure management and to enforce governance controls
  name: central
spec:
  default: false
  • Type the command below to create project alpha
rctl apply -f <path-to-filename>.yaml

Step 2: Create projects for the two teams

Create projects (e.g. alpha and beta) for the two teams using the example spec provided as part of Step 1.


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

An illustrative example of the cluster spec YAML file is shown below.

kind: Cluster
metadata:  
  name: shared-cluster-alpha-beta
  project: central
spec:
  type: imported
  # location, can be custom or predefined
  location: newyorkcity-us  
  blueprint: minimal  
  • Type the command below to create a cluster entry in project alpha
rctl create cluster -f <path-to-filename>.yaml -p central
  • Type the command below to download the cryptographically unique bootstrap YAML required to register the cluster
rctl get clusterbootstrap shared-cluster-alpha-beta -o yaml > <path-to-bootstrap-filename>.yaml -p central
  • Apply bootstrap to the clusters to initiate the import process

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.

Imported cluster


Step 4: Share the imported cluster and apply resource quotas

Share the imported cluster

  • Navigate to central project
  • Click on the gear icon next to the shared cluster (e.g. shared-cluster-alpha-beta) and select the Manage Cluster Sharing option from the dropdown

Share cluster

  • Select the Specific Projects options for Sharing
  • Select alpha and beta from the list

Share cluster

  • Click Save

Apply resource quotas

You can alternatively enable "namespace sync" by using the declarative blueprint spec YAML.

  {
  "apiVersion": "system.k8smgmt.io/v3",
  "kind": "Project",
  "metadata": {
    "name": "alpha"
  },
  "spec": {
    "default": false,
    "clusterResourceQuota": {
      "cpuRequests": "1000m",
      "memoryRequests": "1024Mi",
      "cpuLimits": "2000m",
      "memoryLimits": "2048Mi",
      "configMaps": 10,
      "persistentVolumeClaims": 10,
      "secrets": 10,
      "services": 10,
      "servicesLoadBalancers": 10,
      "servicesNodePorts": 10,
      "storageRequests": 10,
      "pods": 10,
      "replicationControllers": 10
    },
    "defaultClusterNamespaceQuota": {
      "cpuRequests": "200m",
      "memoryRequests": "512Mi",
      "cpuLimits": "1000m",
      "memoryLimits": "1024Mi",
      "configMaps": 5,
      "persistentVolumeClaims": 5,
      "secrets": 5,
      "services": 5,
      "servicesLoadBalancers": 5,
      "servicesNodePorts": 5,
      "storageRequests": 5,
      "pods": 5,
      "replicationControllers": 5
    }
  }
}
  • Type the command below to apply the configured resource quotas
rctl apply -f <path-to-filename>.yaml -p alpha
  • You can verify that the project quotas are configured by using the below command
kubectl get projects.system.k8smgmt.io -o yaml

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=bet

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"

You can alternatively enable "namespace sync" by using the declarative blueprint spec YAML.

Create Blueprint

apiVersion: infra.k8smgmt.io/v3
kind: Blueprint
metadata:
  name: central-blueprint
  project: central
spec:
  base:
    name: minimal
    version: 1.21.0
  defaultAddons:
    csiSecretStoreConfig:
      providers: {}
    enableIngress: false
    enableLogging: false
    enableMonitoring: false
    enableVM: false
  drift:
    enabled: false      
  version: v1
  namespaceConfig:
    enableSync: true
  • Type the command below to create the new blueprint
rctl apply -f <path-to-filename>.yaml -p central
  • Type the command below to verify creation of the blueprint
rctl get blueprint -v <blueprint_name> -p central

Assign the Blueprint to the cluster

You can alternatively assign the blueprint to the cluster using the RCTL command.

rctl update cluster <cluster_name> -b <blueprint_name> --blueprint-version <version_name> -p central

Type the command below to verify creation of the blueprint

rctl get cluster -v <cluster_name> -p central

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.

Namespace

Alternatively, you can use the rctl command to verify the same.

rctl get ns -p central
+-------+-------------+------------------------------+---------------------------+---------+-------------------------------------+-------------+
| NAME  | TYPE        | CREATEDAT                    | DEPLOYEDCLUSTERS          | ID      | LABELS                              | ANNOTATIONS |
+-------+-------------+------------------------------+---------------------------+---------+-------------------------------------+-------------+
| infra | RafayWizard | Tue Jan 17 19:08:08 UTC 2023 | shared-cluster-alpha-beta | 24lg9lk | [kubernetes.io/metadata.name:infra] | []          |
+-------+-------------+------------------------------+---------------------------+---------+-------------------------------------+-------------+

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

Namespace

+--------+-------------+------------------------------+---------------------------+---------+--------+-------------+
| NAME   | TYPE        | CREATEDAT                    | DEPLOYEDCLUSTERS          | ID      | LABELS | ANNOTATIONS |
+--------+-------------+------------------------------+---------------------------+---------+--------+-------------+
| alpha1 | RafayWizard | Tue Jan 17 19:08:06 UTC 2023 | shared-cluster-alpha-beta | 2wywx8k |        |             |
+--------+-------------+------------------------------+---------------------------+---------+--------+-------------+
| alpha2 | RafayWizard | Tue Jan 17 19:08:07 UTC 2023 | shared-cluster-alpha-beta | m15q8ok |        |             |
+--------+-------------+------------------------------+---------------------------+---------+--------+-------------+

Namespace

+-------+-------------+------------------------------+---------------------------+---------+--------+-------------+
| NAME  | TYPE        | CREATEDAT                    | DEPLOYEDCLUSTERS          | ID      | LABELS | ANNOTATIONS |
+-------+-------------+------------------------------+---------------------------+---------+--------+-------------+
| beta1 | RafayWizard | Tue Jan 17 19:08:07 UTC 2023 | shared-cluster-alpha-beta | k3o1l7k |        |             |
+-------+-------------+------------------------------+---------------------------+---------+--------+-------------+
| beta2 | RafayWizard | Tue Jan 17 19:08:07 UTC 2023 | shared-cluster-alpha-beta | 2qxg9zm |        |             |
+-------+-------------+------------------------------+---------------------------+---------+--------+-------------+

Step 8: Create "project specific roles" for users

  • Login into your Org as an Org Admin
  • Navigate to System -> Users
  • Click on New User
  • Input appropriate details (do not add any groups as yet)

Create New User

  • Click Save & Exit
  • You will see a pop-up stating that the user has not been assigned to any groups. Select Yes to continue
  • Select the user that was just created
  • Click on the Projects tab
  • Select Assign User To Project

Assign User

  • Select alpha project from the dropdown on the left
  • Select the Workspace Admin role

Assign Role

  • Click Save & Exit

  • Log out of the console now and log in as the user that was created

  • You can now notice that the user only has access to alpha project and cannot view project beta or project central (and the resources in those projects)

alpha project only

user profile

The workspace admin role allows the user to:

  • Create a new namespace
  • Update resource quotas on existing namespaces
  • Delete an existing namespace

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.