Provision and manage CloudBees CI across multiple Kubernetes clusters and cloud providers

7 minute read

CloudBees CI on modern cloud platforms can be provisioned and managed across multiple Kubernetes clusters and cloud providers. You can run operations center on a main Kubernetes cluster that manages masters across other Kubernetes clusters. These clusters can be hosted on all the major cloud providers. You can set up a multicluster configuration to provision masters in different clusters located in the same cloud provider or a different one.

You can provision, update, and manage CloudBees CI masters on multiple Kubernetes clusters from a common operations center, which allows users to:

  • Separate divisions or business units who need to run workloads in individual clusters.

  • Leverage Helm charts and Configuration as Code to configure, provision, and update using version-controlled configuration files.

Common use cases for multicluster

  • Masters in multiple Kubernetes clusters

    In this use case, the operations center runs in one Kubernetes cluster. Some masters run in the same Kubernetes cluster as the operations center. Any number of additional masters run in a separate Kubernetes cluster.

    Each instance, both operations center and each master, is tied to its own Kubernetes cluster and cannot move after it is provisioned.

  • Agents in separate Kubernetes clusters

    In this use case, agents are deployed in a separate Kubernetes cluster from the Kubernetes cluster where a master is set up.

    The master can be configured to schedule agents between several Kubernetes clouds. Note that no control mechanism is available to spread the load across different Kubernetes clusters because a pod template is tied to a Kubernetes cloud.

Networking considerations for multicluster

Keep in mind the following information about networking for provisioned masters and agents:

  • When provisioning a master on a remote Kubernetes cluster, the Kubernetes API must be accessible from the operations center.

    Upon startup, a master connects back to the operations center through HTTP or HTTPS when using Websockets. If you are not using Websockets, it connects using inbound TCP. If the master is located in a different Kubernetes cluster:

    • The operations center must provide its external hostname so that the master can connect back.

    • If using WebSockets, the operations center HTTP / HTTPS port must be exposed.

    • If not using WebSockets, the operations center inbound TCP port must be exposed.

  • When provisioning an agent on a remote Kubernetes cluster, the Kubernetes API must be accessible from the Managed Master.

    Upon startup, an agent connects back to its master. If the agent is in a different Kubernetes cluster:

    • The master must provide its external hostname so that the master can connect back.

    • If using WebSockets, the master HTTP / HTTPS port must be exposed.

    • If not using WebSockets, the master inbound TCP port must be exposed.

  • In order for masters to be accessible, each Kubernetes cluster must have its own Ingress controller installed, and the configured endpoint for each master should be consistent with the DNS pointing to the Ingress controller of that Kubernetes cluster.

  • Bandwidth, latency, and reliability can be issues when running components in different regions or clouds.

    • operations center <> Master connection is required for features like shared agents, licensing (every 72 hours) or SSO. An unstable connection can result in the inability to sign in, unavailable shared agents or an invalid license if the disconnected time is too long.

    • Master <> agent connection is required to transfer commands and logs. An unstable connection can result in failed builds, unexpected delays, or timeouts while running builds.

About provisioning Managed Masters in multiple Kubernetes clusters

To provision Managed Masters in multiple Kubernetes clusters, you must do the following:

Preparing a namespace to install a Managed Master

  1. To prepare a namespace to install a Managed Master. use the following example values.yaml file:

        Enabled: false
        Enabled: true
        OperationsCenterNamespace: ci (1)
        Enabled: true
    1Replace ci with the actual namespace where the operations center is installed. If the operations center is located in another cluster, it can be set to the same value as the current namespace, then an operations center service account must be created for authentication.
  2. Use the following example to perform the installation.

    export NAMESPACE=my-team (1)
    kubectl create namespace $NAMESPACE || true
    helm install ci-masters-$NAMESPACE cloudbees/cloudbees-core --namespace $NAMESPACE -f values.yaml
    1Replace my-team with the actual namespace where the Managed Masters will be created.

Master provisioning configuration

To provision masters in their own projects, each master must use a specific sub-domain. For example, if the operations center domain is and the URL is, a master dev1 should use the sub-domain or It is often preferable to use the latter if using a wild card certificates for domain

To configure each master to use a specific sub-domain, set the 'Master URL Pattern' in the main Jenkins configuration page 'Manage Jenkins → Configure System' under 'Kubernetes Master Provisioning' advanced options. For example if the operations center domain is, the 'Master URL Pattern' would be https://**/.

Provision Masters

The project for the master resources can be configured as the default project for all Managed Masters in the main operations center configuration screen with the 'namespace' parameter.

The project can also specify a specific Managed Master in the master configuration screen with the 'namespace' parameter.

Leave the namespace value empty to use the value defined by the Kubernetes endpoint.

Adding a ServiceAccount for operations center

  1. Create a ServiceAccount named cjoc in the namespace provided as .Master.OperationsCenterNamespace.

    kubectl create serviceaccount cjoc -n ci (1)
    1Replace ci with the actual value used for .Master.OperationsCenterNamespace
  2. Create a kubeconfig for the operations center service account:

    apiVersion: v1
    kind: Config
    - name: kubernetes
        certificate-authority-data: <CLUSTER_CA_BASE64_ENCODED> (1)
        server: <KUBE_APISERVER_ENDPOINT> (2)
    - name: cjoc
        cluster: kubernetes
        namespace: <NAMESPACE> (3)
        user: cjoc
    current-context: cjoc
    - name: cjoc
        token: <CJOC_SERVICEACCOUNT_TOKEN> (4)
    1Replace <CLUSTER_CA_BASE64_ENCODED> with the base64 encoded value of the Cluster Certificate Authority, see Kubernetes - Service Account Tokens.
    2Replace <KUBE_APISERVER_ENDPOINT> with the URL of the Kubernetes API Server.
    3Replace <CJOC_SERVICEACCOUNT_NAMESPACE> with the namespace where the cjoc ServiceAccount has been created.
    4Replace <CJOC_SERVICEACCOUNT_TOKEN> with the decoded value of the cjoc ServiceAccount token. See Kubernetes - Service Account Tokens.
    Another way of generating a kubeconfig file for the operations center service account is to use the following kubectl plugin: view-serviceaccount-kubeconfig, and run the command kubectl view-serviceaccount-kubeconfig cjoc -n ci
  3. Make sure it works before trying to use it in the following steps:

    KUBECONFIG=<PATH_TO_KUBECONFIG_FILE> kubectl version (1)
    1Replace <PATH_TO_KUBECONFIG_FILE> by the location of the kubeconfig file created.

Adding a new Kubernetes cluster endpoint

  1. In operations center, browse to Manage Jenkins > Configure System.

    In the section Kubernetes Master Provisioning, the list of endpoints is displayed.

    The first one corresponds to the current cluster and namespace that operations center is running.

  2. Click Add.

    new cluster endpoint
    Figure 1. New Cluster Endpoint
    • Set the API endpoint URL. You’ll find it in your Cloud console, or alternatively in your kubeconfig file.

    • Pick a name to identify the cluster endpoint.

    • Set up credentials. To use a kubeconfig file, create a Secret file.

    • If needed, provide the server certificate. Or, disable the certificate check.

    • Pick a namespace. If left empty, it uses the name of the current namespace where operations center is deployed.

    • Set the Master URL Pattern to the domain name configured to target the ingress controller on the Kubernetes cluster.

    • The Jenkins URL can be left empty, unless there is a specific link between clusters requiring access to operations center using a different name than the public one.

    • Select Use WebSocket to enable WebSockets for all Managed Masters that use this endpoint. See Using WebSockets to connect masters to operations center for details about WebSockets.

  3. Click Validate to make sure the connection to the remote Kubernetes cluster can be established and the credentials are valid.

  4. Click Save.

Adding a Managed Master to a Kubernetes cluster

To add a new Managed Master to a Kubernetes cluster:

  1. Select the cluster endpoint to use.

  2. Adjust the master configuration to your needs.

  3. If you don’t want to use the default storage class from the cluster, set the storage class name through the dedicated field.

  4. If the Ingress Controller isn’t the default one, use the YAML field to set an alternate Ingress class.

    kind: "Ingress"
      annotations: 'nginx'
  5. Save and provision.

Deploying agents in a separate Kubernetes cluster from a Managed Master

Follow these steps to provision Kubernetes agents on another cluster.

If you are performing the steps below in a Kubernetes Shared Cloud, the Kubernetes Shared Cloud can be shared with only one Managed Master because the Kubernetes URL is injected using the DNS of the master. In a multicluster environment, a Kubernetes Shared Cloud cannot be shared among multiple Managed Masters.

To deploy agents in a separate Kubernetes cluster from a Managed Master:

  1. Set up kubectl to point to the target (agent) cluster.

  2. Type the following command to install only serviceaccount/jenkins and the related role and role binding:

    helm install <helm deployment name> cloudbees/cloudbees-core --set OperationsCenter.Enabled=false
  3. Type the following command:

    The Krew plugin manager is required to run this command.
    kubectl krew install view-serviceaccount-kubeconfig
  4. Type the following command:

    kubectl view-serviceaccount-kubeconfig jenkins > /tmp/sa-jenkins.yaml
  5. On your Managed Master, create Secret File credentials using the service account.

  6. In Manage Jenkins > Manage Nodes and Clouds, select Configure Clouds.

  7. Select Add a new cloud, and then select Kubernetes.

  8. Enter a Name of your choice, and then select Kubernetes Cloud details.

  9. In Credentials, add a Secret File credential type, and then upload the sa-jenkins.yaml file that you created in step 1.

  10. Select WebSocket.

  11. In Jenkins URL, enter the public (ingress) URL of the Managed Master.

  12. Leave all other fields blank.

  13. Select Pod Templates > Add Pod Template.

  14. Enter a pod template name.

  15. Select Pod Template details.

  16. In Labels, enter the label of the pod. NOTE: The Labels field of the pod template is the one used to select the template in a Pipeline, not the name. So it’s important to complete the Labels field.

  17. Click Save.

TLS for remote masters in a multicluster environment

The recommended approach to set up Ingress TLS for masters in remote clusters is to add the secret to the namespace where the master is deployed, and then add the TLS to each remote master’s Ingress (through the YAML field).

Removing masters from a cluster

If you remove a master from operations center, the master’s Persistent Volume Claim, which represents the JENKINS_HOME, is left behind.

To remove a master from a cluster:

  1. Type the following command:

    kubectl delete pvc <pvc-name>
    The <pvc-name> is always jenkins-home-<master name>-0.

Troubleshooting multicluster and multicloud

  1. What should I do if my master cannot connect back to the operations center?

    Use kubectl to retrieve the master. Then, inspect where it tries to connect and how it matches the configuration that is defined in operations center.

  2. My master starts and shows as connected in operations center. Why isn’t my master browsable?

    This can be caused by either a DNS/Ingress misconfiguration or a URL misconfiguration.