Why is the 'Jenkins Controller Disk Space in GB field' not editable in the Configuration of a Managed Controller

Issue

  • I cannot edit the “Jenkins Controller Disk Space in GB” field in the configuration of a Manage Controller
  • I have changed the size of my Persistent Volume manually but I cannot change the value in the Manage Controller configuration.

Environment

Explanation

The “Jenkins Controller Disk Space in GB” field is only editable if the Storage Class used to manage the Persistent Volume Claim of the controller has the allowVolumeExpansion set to true.

Note: If not familiar with it, read about Allow Volume Expansion. Adding this value is not necessarily the solution. It is only truly supported by certain type of volumes.

What is more is that if the Operations Center cannot retrieve information the storage class in the cluster where the controller is provisioned - perhaps because of a lack of cluster permissions - then this field is made non-editable by default. The service account used by the Operations Center requires permission to get and list the cluster resource storageclasses.

Those permissions are not given by default when deployment CloudBees CI. The values .rbac.installCluster must be set to true to have them added.

Troubleshooting

Check the Storage Class

Use kubectl get sc -o yaml and verify whether allowVolumeExpansion is set to true.

Check the Operations Center logs

To check if Operations is unable to retrieve information about the Storage Class, tail the logs of the Operations Center with kubectl logs -f cjoc-0, open the Manage Controller configure page and look for messages coming from KubernetesMasterProvisioning$DescriptorImpl#isDiskEditable. For example c.c.m.k.KubernetesMasterProvisioning$DescriptorImpl#isDiskEditable: cannot check disk size editability. That would mean that Operations Center is not able to retrieve the necessary details. And therefore the field remain non-editable by default.

Resolution

The solution depends on the scenario. Either the storage class misses an attribute or the Operations Center is unable to get information about the storage class.

  • Make sure that the allowVolumeExpansion: true is added to the Storage Class if the volume type supports it.

  • Make sure that the Operations Center has the requirement permissions, which can be given with the following helm values:

    rbac
      installCluster: true
    

    Note: If not using helm or if using a multi-cluster environment, the permissions might need to be given manually. Here is an example of what is required for the service account binding:

    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: cjoc-role-binding-sda
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: cjoc-master-management-sda
    subjects:
    - kind: ServiceAccount
      name: <serviceAccountName>
      namespace: <serviceAccountNamespace>
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: cjoc-master-management-sda
    rules:
    - apiGroups:
      - storage.k8s.io
      resources:
      - storageclasses
      verbs:
      - get
      - list
    

Workaround

In cases where this field cannot be made editable - such as a storage class that does not support the Volume Expansion feature or security policies that prevent giving cluster level permission to get / list storage classes - the workaround would be to set the size via the the REST API / Groovy. For example with a script like the following, to execute under Manage Jenkins > Script Console:

// Name of the controller
String controllerName = "<controllerName>"
// Size of the disk
Integer newDiskSize = <newSize>

def controllerItem = jenkins.model.Jenkins.instanceOrNull.getAllItems(com.cloudbees.opscenter.server.model.ManagedMaster.class)
  .findAll { it -> it.getConfiguration() instanceof com.cloudbees.masterprovisioning.kubernetes.KubernetesMasterProvisioning}
  .find {it -> controllerName == it.name };

if (newDiskSize != controllerItem.configuration.getDisk()) {
    println "${controllerItem.fullDisplayName} disk size was ${controllerItem.configuration.getDisk()}. Changing it to ${newDiskSize}"
    controllerItem.configuration.setDisk(newDiskSize)
    controllerItem.save()
} else {
    println "${controllerItem.fullDisplayName} disk size is already ${controllerItem.configuration.getDisk()}"
}
return

Have more questions?

0 Comments

Please sign in to leave a comment.