Skip to main content

OpenShift Jenkins configuration via JCasC plugin

·3 mins

Deploying Jenkins on Kubernetes provides significant benefits over a standard VM-based deployment. For example, we are gaining the ability to have project-specific Jenkins slaves (agents) on demand instead of having a pool of VMs idle waiting for a job.

In vanilla Kubernetes, we can deploy Jenkins using Helm, and In OpenShift, we can deploy Jenkins via the developer’s catalog.

As everyone has experienced, setting up Jenkins is a complex process. Both Jenkins and its plugins require some tuning and Configuration, with dozens of parameters to set within the web UI manage section.

Jenkins Config as code #

Configuration as code gives you an opinionated way to configure Jenkins based on yaml files

This post will cover Jenkins configuration code on OpenShift.

  • Mount Jenkins config as a configmap and load configuration
  • Updated configuration file to automate the creation of
    • credentials
    • script approval signatures
    • shared libraries
    • multibranch pipeline seed jobs

Install Plugin #

First, let us install configuration-as-code plugins in Jenkins. In OpenShift, you can easily install plugins by adding the INSTALL_PLUGINS environment variable to the deployment config

....
env:
  - name: INSTALL_PLUGINS
    value: "configuration-as-code:1.35,configuration-as-code-support:1.18,configuration-as-code-groovy:1.1

Create ConfigMap #

Create a configmap from jenkins-config yaml and mount it as a volume at /var/jenkins_config location. Configuration can be now loaded from /var/jenkins_config/jenkins-config.yaml path

oc create configmap jenkins-config --from-file jenkins-config.yaml
....
    volumeMounts:
      - mountPath: /var/jenkins_config
        name: jenkins-config
dnsPolicy: ClusterFirst
restartPolicy: Always
volumes:
  - name: jenkins-config
    configMap:
      name: jenkins-config

Mount Secret #

Since we can have Jenkins configuration in the git repo, we don’t want to hardcode the secrets as it is a security risk. The easiest way to automate credentials in Jenkins configuration is to create an OpenShift secret, and add that secret as an environment variable to the deployment config

oc create secret generic github-ssh --from-file=ssh-privatekey=github-ssh/
oc create secret generic jenkins-credentials --from-literal=OCP_SA="qwerty26sds99ie9kcsd"  --from-literal=GITHUB_PASSWORD="dummypassword"

Mount secrets into the container

....
env:
....
- name: OCP_SA
  valueFrom:
    secretKeyRef:
      name: jenkins-credentials
      key: OCP_SA
- name: GITHUB_SSH
  valueFrom:
    secretKeyRef:
      name: github-ssh
      key: ssh-privatekey
- name: GITHUB_PASSWORD
  valueFrom:
    secretKeyRef:
      name: jenkins-credentials
      key: GITHUB_PASSWORD
....
credentials:
  system:
    domainCredentials:
      - credentials:
          - fileSystemServiceAccountCredential:
              id: "1a12dfa4-7fc5-47a7-aa17-cc56572a41c7"
              scope: GLOBAL
          - basicSSHUserPrivateKey:
              description: "github ssh credentials"
              id: "github-ssh"
              privateKeySource:
                directEntry:
                  privateKey: ${GITHUB_SSH}
              scope: GLOBAL
              username: "github-user"
          - OpenShiftToken:
              id: "jenkins-ocp-token"
              scope: GLOBAL
              secret: ${OCP_SA}
          - usernamePassword:
              description: "github user credentials"
              id: "github-user"
              password: ${GITHUB_PASSWORD}
              scope: GLOBAL
              username: "github-user"

Example Configs #

Security script approval #

security:
  scriptApproval:
    approvedSignatures:
      - "method java.text.DateFormat parse java.lang.String"

Global shared library #

unclassified:
  globalLibraries:
    libraries:
      - defaultVersion: "master"
        name: "shared-pipeline"
        retriever:
          modernSCM:
            scm:
              git:
                credentialsId: "github-ssh"
                id: "shared-pipeline"
                remote: "[email protected]:vikaspogu/jenkins-shared.git"

Multibranch job #

Multibranch seed job with periodic polling, traits for branch discovery

jobs:
  - script: >
      multibranchPipelineJob("sample-repo") {
        branchSources {
          branchSource {
            source {
              github {
                //This is a unique identifier; if not set, the pipeline will be 
                //indexed, and jobs will be kicked off every time new config is applied
                id("5bb970c2-766b-4588-8cf8-e077bfec23a0")
                credentialsId("github-user")
                repoOwner("vikaspogu")
                repository("sample-repo")
                traits {
                  cloneOptionTrait {
                    extension {
                      shallow (false)
                      noTags (false)
                      reference (null)
                      depth(1)
                      honorRefspec (false)
                      timeout (10)
                    }
                  }
                }
              }
            }
          }
        }
        configure {
          def traits = it / sources / data / 'jenkins.branch.BranchSource' / source / traits
          traits << 'com.cloudbees.jenkins.plugins.bitbucket.BranchDiscoveryTrait' {
            strategyId(3) // detect all branches -refer the plugin source code for various options
          }
        }
        configure {
          def traits = it / sources / data / 'jenkins.branch.BranchSource' / source / traits
          traits << 'com.cloudbees.jenkins.plugins.bitbucket.OriginPullRequestDiscoveryTrait' {
            strategyId(2)
          }
        }
        configure {
          def traits = it / sources / data / 'jenkins.branch.BranchSource' / source / traits
          traits << 'com.cloudbees.jenkins.plugins.bitbucket.TagDiscoveryTrait' {}
        }
        orphanedItemStrategy {
          discardOldItems {
            numToKeep(15)
          }
        }
        triggers {
          periodic(2)
        }
      }