Installation

This document describes installation procedure of self-hosted Operator Service for Jenkins®.

Installation of a self-hosted Operator Service for Jenkins® happens with Helm Chart.

When purchasing the Operator Service for Jenkins, client is given a personalized token with a password and name of the registry to access the Operator’s image and helm chart.

First create namespaces of choice to deploy Operator and Jenkins in.

$ kubectl create ns <operator-namespace>
$ kubectl create ns <jenkins-namespace>

Second create a secret for downloading the Enterprise image by exchanging the placeholders in the below code:

$ kubectl create secret docker-registry token \
--namespace <operator-namespace> \
--docker-server=<registry-name> \
--docker-username=<token-name> \
--docker-password=<password>

This secret must reside in the same namespace as Operator and be named image-secret in order to fetch the image.

Third create a secret with the license information.

apiVersion: v1
kind: Secret
metadata:
  name: license
  namespace: <operator-namespace>
stringData:
  clientName: "<your-name>"
  licenseKey: "<your-license-key>"

By default, the Operator will look for a secret named “license”, but you can use custom name for this secret. You can do that by specifying it in the flag in the Operator command:

-license-secret=<custom-name>

Next, prepare your two custom values.yaml files: values-operator.yaml and values-crs.yaml, and specify all of the desired configuration for the Operator and other available Custom Resources. Don’t forget to exchange the jenkins namespace and operator namespace with the one you have just created. You can copy and customize the default files:

# Operator Service for Jenkins Helm chart

# apiVersion is the version of the Custom Resources manifests
apiVersion: operator-service.com/v1beta1

# operator is section for configuring operator deployment
operator:

  replicaCount: 1

  # image is the name (and tag) of the Operator Service for Jenkins image
  image: operatorservice.azurecr.io/op-svc-jenkins:0.11.1

  # imagePullPolicy defines policy for pulling images
  imagePullPolicy: IfNotPresent

  # imagePullSecrets is used to pull images from private repository
  imagePullSecrets:
    - name: token

  # command
  command:
    - /manager

  # args is used to specify flags
  args:
    - --leader-elect=true

  # nameOverride overrides the app name
  nameOverride: ""

  # fullnameOverride overrides the deployment name
  fullnameOverride: ""

  # Resource limit/request for Operator Service
  # See https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ for details
  resources: {}

  # NodeSelector for Operator Service
  # For more details see https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/
  nodeSelector: {}

  # Tolerations are applied to pods, and allow the pods to schedule onto nodes with matching taints.
  # See https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ fore more details
  tolerations: []

  # Affinity allows you to constrain which nodes your pod is eligible to be scheduled on, based on labels on the node.
  # For more details see https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity
  affinity: {}

  # JenkinsNamespace is used by Operator Service to watch namespace where Jenkins will be deployed
  jenkinsNamespace: "jenkins"
# Operator Service for Jenkins Custom Resources Helm chart

# apiVersion is the version of the Custom Resources manifests
apiVersion: operator-service.com/v1beta1

# Jenkins instance configuration
jenkins:
  # enabled can enable or disable the Jenkins instance
  # Set to false if you have configured CR already and/or you want to deploy an operator only
  enabled: true

  # name of resource
  # The pod name will be jenkins-<name> (name will be set as suffix)
  name: jenkins

  # labels are injected into metadata labels field
  #labels: {}

  # annotations are injected into metadata annotations field
  annotations: {}

  # podLabels are injected into Jenkins Controller Pod's metadata labels field
  podLabels: {}

  # podSpec
  podSpec:
    initContainers: []
    sidecars: []
    jenkinsController:
      name: jenkins-controller
      image: jenkins/jenkins:2.319.1-lts
      imagePullPolicy: IfNotPresent
      command: []
      livenessProbe: {}
      readinessProbe: {}
      # Resource limit/request for Jenkins
      # See https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ for details
      resources:
        limits:
          cpu: 1500m
          memory: 3Gi
        requests:
          cpu: 1
          memory: 500Mi
      env: []
      envFrom: []
      volumeMounts: []
    volumes: []
    restartPolicy: ""
    imagePullSecrets: []
    hostAliases: []
    podSecurityContext: {}
    affinity: {}
    priorityClassName: ""
    tolerations: []

  # homePVC allows to set PersistentVolumeClaim properties for Jenkins home
  homePVC: {}

  # accessMode specifies the way the plugins cache can be mounted
  # accessMode: ""

  # resourceStorage is the plugins cache volume size
  # resourceStorage: ""

  # storageClassName is the name of the StorageClass required by the claim
  # storageClassName: ""
  # storageClassName: ""

  # pluginsCache allows to set plugins cache specific pvc properties
  pluginsCache: {}

  # accessMode specifies the way the plugins cache can be mounted
  # accessMode: ""

  # resourceStorage is the plugins cache volume size
  # resourceStorage: ""

  # storageClassName is the name of the StorageClass required by the claim
  # storageClassName: ""

  # plugins are plugins required by the user
  # You can define plugins here
  #
  # Example:
  #
  # plugins:
  # - name: jacoco
  #   version: "3.1.1"
  plugins: []

  # roles defines list of extra RBAC roles for the Jenkins Master pod service account
  roles: []

  # services allows to configure Jenkins services
  services: {}
#    Http is Jenkins web UI service
#    http:
#      labels are injected into metadata labels field
#      labels: {}
#
#      annotations are injected into metadata annotations field
#      annotations: {}
#
#      Spec describes the attributes that a user creates on a service.
#      spec: {}
#
#    Agent is Jenkins agent service
#    agent:
#      labels are injected into metadata labels field
#      labels: {}
#
#      annotations are injected into metadata annotations field
#      annotations: {}
#
#      Spec describes the attributes that a user creates on a service.
#      spec: {}

  # defines authorization strategy of the operator for the Jenkins API
  authorizationStrategy: createUser

  # disableCSRFProtection can enable or disable operator built-in CSRF protection
  # Set it to true if you are using OpenShift Jenkins Plugin
  # See https://github.com/jenkinsci/kubernetes-operator/pull/193 for more info
  disableCSRFProtection: false

# jenkinsGroovyScriptsEnabled can enable or disable the JenkinsGroovyScript instances
# Set to false if you have configured CR(s) already and/or you want to deploy an operator only
jenkinsGroovyScriptsEnabled: true

# JenkinsGroovyScripts instances configuration
# JenkinsGroovyScriptSpec defines the desired state of JenkinsGroovyScript. It allows to write Groovy Scripts to modify the Jenkins.
jenkinsGroovyScripts:
  # name of resource
  - name: groovy

    # labels are injected into metadata labels field. Each JenkinsSeedJob Custom Resource need to reference corresponding
    # Jenkins Custom Resource via labels field
    labels:
      operator-service.com/jenkins: jenkins

    # annotations are injected into metadata annotations field
    annotations: {}

    # data is inline Groovy script
    data: |
      import jenkins.model.Jenkins

      def systemMessage = "Hello from v1beta1.JenkinsGroovyScript!"

      Jenkins jenkins = Jenkins.getInstance()
      jenkins.setSystemMessage(systemMessage)
      jenkins.save()

      println "Hello world!"      

    # secretRef is secret reference which allows to inject the secrets into Groovy script code
    #secretRef:
      #name: ""
      #namespace: ""

    # dependsOn is JenkinsGroovyScript reference which determines the order of the Groovy scripts
    #dependsOn:
      #name: ""
      #namespace: ""

# jenkinsSeedJobsEnabled can enable or disable the JenkinsSeedJobs instances
# Set to false if you have configured CR(s) already and/or you want to deploy an operator only
jenkinsSeedJobsEnabled: true

# JenkinsSeedJobs instances configuration
# See https://virtuslabrnd.github.io/operator-service-docs/operator-service-for-jenkins/latest/getting-started/seedjob-configuration/ for additional info
jenkinsSeedJobs:
  # name of resource
  - name: example

    # labels are injected into metadata labels field. Each JenkinsSeedJob Custom Resource need to reference corresponding
    # Jenkins Custom Resource via labels field
    labels:
      operator-service.com/jenkins: jenkins

    # annotations are injected into metadata annotations field
    annotations: {}

    # Repository is VCS repository settings
    repository:

      # branch is the repository branch where seed job definitions are stored
      branch: master

      # URL is the repository access URL. Can be SSH or HTTPS.
      url: https://github.com/jenkinsci/kubernetes-operator.git

      # targets is the path from repository root where seed job definitions are stored
      targets: "cicd/jobs/*.jenkins"

      # credentialID is the Kubernetes secret name which stores repository access credentials
      credentialID: ""

      # credentialType is the https://jenkinsci.github.io/kubernetes-credentials-provider-plugin/ credential type (optional)
      # allowed types:
      # "" define none Jenkins credential type
      # "basicSSHUserPrivateKey" basic SSH Jenkins credential type
      # "usernamePassword" define username & password Jenkins credential type
      # "external" defines other credential type
      credentialType: ""

    # agentRef represents a Jenkins Kubernetes Agent Reference. It has enough information to retrieve agent
    # in any namespace
    #agentRef:

      # name is unique within a namespace to reference a secret resource.
      #name:

      # namespace defines the space within which the secret name must be unique.
      #namespace:

    # triggers define circumstances that execute jobs
    triggers:

      # bitbucketTrigger is used for Bitbucket web hooks (optional)
      bitbucketTrigger:
        push: false

      # gitHubTrigger is used for GitHub web hooks (optional)
      gitHubTrigger:
        push: false

      # buildPeriodically is used for scheduled timer trigger (optional)
      buildPeriodically: ""

      # pollSCM is setting for polling changes in SCM (optional)
      pollSCM: ""

    # settings configures the job build options
    settings:

      # ignoreMissingFiles is setting for Job DSL API plugin to ignore files that are missing (optional)
      ignoreMissingFiles: false

      # additionalClasspath is setting for Job DSL API plugin to set Additional Classpath (optional)
      additionalClasspath: ""

      # failOnMissingPlugin is setting for Job DSL API plugin that fails job if required plugin is missing (optional)
      failOnMissingPlugin: false

      # unstableOnDeprecation is setting for Job DSL API plugin that sets build status as unstable if build using deprecated features (optional)
      unstableOnDeprecation: false

# jenkinsConfigurationsAsCodeEnabled can enable or disable the JenkinsConfigurationAsCode instances
# Set to false if you have configured CR(s) already and/or you want to deploy an operator only
jenkinsConfigurationsAsCodeEnabled: true

# JenkinsConfigurationAsCode instances configuration
# For configuration as code creation tutorial, check https://virtuslabrnd.github.io/operator-service-docs/operator-service-for-jenkins/latest/getting-started/customization/
jenkinsConfigurationsAsCode:
  # name of resource
  - name: casc

    # labels are injected into metadata labels field. Each JenkinsConfigurationAsCode Custom Resource need to reference corresponding
    # Jenkins Custom Resource via labels field
    labels:
      operator-service.com/jenkins: jenkins

    # annotations are injected into metadata annotations field
    annotations: {}

    # data is inline Groovy script
    data: |
      jenkins:
        systemMessage: |
          Welcome to your CI/CD server managed by Operator Service for Jenkins!
        numExecutors: 1      

    # secretRef is secret reference which allows to inject the secrets into Configuration As Code script
    #secretRef:
      #name: ""
      #namespace: ""

# jenkinsKubernetesAgentEnabled can enable or disable the JenkinsKubernetesAgent instances
# Set to false if you have configured CR(s) already and/or you want to deploy an operator only
jenkinsKubernetesAgentEnabled: true

# JenkinsKubernetesAgent instances configuration
# For configuration as code creation tutorial, check https://virtuslabrnd.github.io/operator-service-docs/operator-service-for-jenkins/latest/getting-started/seedjob-configuration/
jenkinsKubernetesAgents:
  # name of resource
  - name: first-agent

    # labels are injected into metadata labels field. Each JenkinsKubernetesAgent Custom Resource need to reference corresponding
    # Jenkins Custom Resource via labels field
    labels:
      operator-service.com/jenkins: jenkins

    # annotations are injected into metadata annotations field
    annotations: {}

    # PodSpec allows to set Jenkins Kubernetes Agent specific pod properties
    podSpec:
      containers:
        - name: jnlp
          image: jenkins/inbound-agent:4.10-3-alpine
          imagePullPolicy: IfNotPresent

    properties:
      # Description of Jenkins Agent
      description: ""

      # Executors defines the maximum number of concurrent builds that Jenkins may perform on this node.
      executors:

      # RemoteRootDirectory is directory dedicated to Jenkins for temporary files storage purposes.
      remoteRootDirectory: ""

      # Usage controls how Jenkins schedules builds on this node.
      # Available usage options are defined by AgentUsage enum
      usage: ""

      # LaunchMethod controls how Jenkins starts this agent.
      # AgentLaunchMethod is enum that defines the available launch methods
      launchMethod: ""

      # DisableWorkDir allows disabling Remoting Work Directory for the agent.
      disableWorkDir: false

      # CustomWorkDirPath is a custom Remoting work directory will be used instead of the Agent Root Directory
      customWorkDirPath: ""

      # InternalDataDirectory defines a storage directory for the internal data
      # By default it's "remoting"
      internalDataDirectory: ""

      # FailIfWorkspaceIsMissing if true, remoting will fail at startup if the target work directory is missing
      failIfWorkplaceIsMissing: false

      # UseWebSocket uses websocket to connect to the Jenkins Controller rather than the TCP port
      useWebSocket: false

      # TunnelConnectionThrough allows to route connection to another host
      # Field allowed values: "HOST:PORT", ":PORT" and "HOST:"
      tunnelConnectionThrough: ""

      # JVMOptions are additional startup arguments for Java Virtual Machine which runs agent
      jvmOptions: ""

      # Availability controls when Jenkins starts and stops this agent.
      availability: ""

      # ToolLocations is list of tools location
      toolLocations:
        - name: ""
          home: ""

    # RoleRef defines list of extra RBAC roles for the Jenkins Kubernetes Agent pod service account
    roleRef: []

# JenkinsAuthenticationEnabled can enable or disable the JenkinsAuthentication instance
# Set to true if you want to deploy the resource, set to false if have configured CR(s) already and/or you want to deploy an operator only
jenkinsAuthenticationEnabled: false

# JenkinsAuthentication configuration
# For authentication creation tutorial, check https://virtuslabrnd.github.io/operator-service-docs/operator-service-for-jenkins/latest/getting-started/authentication/
jenkinsAuthentication:
  # name of resource
  name: authentication

  # labels are injected into metadata labels field. Each JenkinsAuthentication Custom Resource need to reference corresponding
  # Jenkins Custom Resource via labels field
  labels:
    operator-service.com/jenkins: jenkins

  # annotations are injected into metadata annotations field
  annotations: {}

  # type indicates which authentication provider is set
  type: "githubOAuth"

  # githubOAuth is configuration for GitHub OAuth provider
  githubOAuth:
    # clientID is the client ID you received from GitHub for your OAuth App.
    clientID: ""

    # clientSecretRef is a secret reference which allows to safely pass into Authorization Spec. Has to contain "clientSecret" key with value of
    # the client secret you received from GitHub for your OAuth App.
    clientSecretRef:
      name: ""
      namespace: ""

    # WebURI used if you are using GitHub Enterprise. The URL to the web UI root of your GitHub installation.
    # The 'https://' or 'http://' part needs to be specified. There should not be any trailing slash (/).
    # By default set to 'https://github.com'. (optional)
    webUri: "https://github.com"

    # APIURI used if you are using GitHub Enterprise. The URI to the API root of your GitHub installation.
    # The 'https://' or 'http://' part needs to be specified. There should not be any trailing slash (/).
    # By default set to 'https://api.github.com'. (optional)
    apiUri: "https://api.github.com"

    # Scopes let you specify exactly what your app is requesting access to. Scopes limit access for OAuth tokens.
    # They do not grant any additional permission beyond that which the user already has.
    # By default these are set to "org:user,user:email" (optional)
    scopes:
      - "read:org"
      - "user:email"

  # googleOAuth is configuration for Google OAuth provider
  googleOAuth:
    # clientID is the client ID you from Google OAuth credentials
    clientID: ""

    # clientSecretRef is a secret reference which allows to safely pass into Authorization Spec. Has to contain "clientSecret" key with value of
    # the client secret from Google OAuth credentials
    clientSecretRef:
      name: ""
      namespace: ""

    # Domain is the public domain of your Jenkins instance. Leave empty for localhost (optional)
    domain: ""

  # openIDConnectAuth is configuration for various authentication providers compliant with OpenID Connect standard.
  # For more information, visit the documentation of the oic-auth: https://github.com/jenkinsci/oic-auth-plugin
  openIDConnectAuth:
    # clientID is the client ID you received from your identity provider
    clientID: ""

    # clientSecretRef is a secret reference which lets you safely pass the client secret to Authentication Spec.
    # The secret has to contain the "clientSecret" key with value of the client secret from OpenID Connect credentials.
    clientSecretRef:
      name: ""
      namespace: ""

    # autoManualConfigure specifies configuration mode. This can be either auto or manual.
    # If set to auto, WellKnownOpenIDConfigurationURL will be required and configuration will be fetched from the
    # well-known configuration endpoint. If set to false, tokenServerURL and authorizationServerURL will be required.
    autoManualConfig: ""

    # WellKnownOpenIDConfigurationURL is an endpoint with well-known configuration endpoint, where your OpenID server
    # publishes its metadata. Required when autoManualConfigure is set to auto, otherwise optional.
    wellKnownOpenIDConfigurationURL: ""

    # Required when autoManualConfigure is set to manual, otherwise optional.
    tokenServerURL: ""

    # Required when autoManualConfigure is set to manual, otherwise optional.
    authorizationServerURL: ""

    # (optional)
    userInfoServerURL: ""

    # (optional)
    userNameField: ""

    # (optional)
    tokenFieldToCheckKey: ""

    # (optional)
    tokenFieldToCheckValue: ""

    # (optional)
    fullNameFieldName: ""

    # (optional)
    emailFieldName: ""

    # scopes are used to specify access privileges while authenticating. It is a string containing space-separated
    # scopes. (optional)
    #
    # Example:
    #
    # scopes: "openid email profile"
    scopes: ""

    # (optional)
    groupsFieldName: ""

    # (optional)
    disableSSLVerification: false

    # logoutFromOpenIDProvider specifies whether to call endSessionEndpoint on logout from Jenkins. (optional)
    logoutFromOpenIDProvider: false

    # endSessionEndpoint is an endpoint to be called on logging out from Jenkins.
    # Required when logoutFromOpenIDProvider is set to true, otherwise optional.
    endSessionEndpoint: ""

    # (optional)
    postLogoutRedirectURL: ""

    # (optional)
    escapeHatchEnabled: false

    # (optional)
    escapeHatchUsername: ""

    # escapeHatchSecretRef is a secret reference which lets you safely pass the escape hatch secret to Authentication Spec.
    # It is required when EscapeHatchEnabled is set to true.
    # The secret has to contain the "escapeHatchSecret" key with value of the client secret from OpenID Connect credentials.
    # Required when escapeHatchEnabled is set to true, otherwise optional.
    escapeHatchSecretRef:
      name: ""
      namespace: ""

    # (optional)
    escapeHatchGroup: ""

Login to registry to download Helm charts:

$ export HELM_EXPERIMENTAL_OCI=1
$ helm registry login operatorservice.azurecr.io -u <token-name> -p <token-password>

Download Helm charts from registry:

$ helm chart pull operatorservice.azurecr.io/helm/op-svc-jenkins:latest
$ helm chart pull operatorservice.azurecr.io/helm/op-svc-jenkins-crs:latest

Export Helm charts from cache to change values and configure operator and Custom Resources:

$ helm chart export operatorservice.azurecr.io/helm/op-svc-jenkins:latest
$ helm chart export operatorservice.azurecr.io/helm/op-svc-jenkins-crs:latest
$ helm pull oci://operatorservice.azurecr.io/charts/op-svc-jenkins --version 0.3.1
$ helm pull oci://operatorservice.azurecr.io/charts/op-svc-jenkins-crs --version 0.3.1

In this step, replace default values.yaml with your own. Deploy Operator Service for Jenkins® in the first one running Helm command:

$ helm install operator-service -f values-operator.yaml ./op-svc-jenkins -n <operator-namespace>
$ helm install operator-service-crs -f values-crs.yaml ./op-svc-jenkins-crs -n <jenkins-namespace>

At that moment, the Operator and Jenkins pods will start to appear. You can watch over the process by running:

$ kubectl get po --all-namespaces -w

Operator will keep on printing logs about reaching consecutive phases and announce itself Ready. Then you can start to use it freely.

To connect to the UI you can use:

$ kubectl -n <jenkins-namespace> port-forward <jenkins-pod> 8080:8080

At http://localhost:8080 (or with customized suffix) you will find the Jenkins UI.

Login credentials can be obtained using commands below:

$ kubectl -n <jenkins-namespace> get secret <jenkins-name>-credentials -o 'jsonpath={.data.user}' | base64 -d
$ kubectl -n <jenkins-namespace> get secret <jenkins-name>-credentials -o 'jsonpath={.data.password}' | base64 -d

Jenkins UI

What’s next?

For further information about customization and configuration of Jenkins please refer to the Getting Started section.