The GitOps Way

A Jenkins user’s Field Report: From Docker Compose to Kubernetes

Last week we gave our Jenkins build system some ❤️.

💡The basic idea behind this undertaking is to switch from a kind of static Docker Compose “installation” to a more scalable and easier-to-maintain Kubernetes deployment.

In essence, we switch from docker-compose up to helmfile apply.

roboll/helmfile - Deploy Kubernetes Helm Charts

The standard usage is as easy as helmfile apply.

Per default, you specify the helm charts to install via helmfile.yaml.

repositories:
  # helm repo add jenkinsci https://charts.jenkins.io
  - name: jenkinsci
    url: https://charts.jenkins.io

releases:
  # helm install my-jenkins jenkinsci/jenkins --version 3.8.8
  - chart: jenkinsci/jenkins
    name: jenkins
    namespace: jenkinsci
    installed: true
    cleanupOnFail: false

If you are familiar with helm, you can easily translate the configuration into helm commands as shown in the comments of the configuration file.

See the link for more details on how to configure the helm chart check Jenkins helmchart.

$ helmfile apply
…
UPDATED RELEASES:
NAME      CHART               VERSION
jenkins   jenkinsci/jenkins     3.8.8

Forward the port on your local machine with:

$ kubectl --namespace=jenkinsci port-forward svc/jenkins 8080:8080 

Forwarding from 127.0.0.1:8080 -> 8080
Forwarding from [::1]:8080 -> 8080

Now you can point your browser to localhost:8080 to access Jenkins.

Tip: You can grab the generated password for user admin with:

kubectl --namespace=jenkinsci get secret jenkins \
  -o jsonpath='{.data.jenkins-admin-password}' \
  | base64 --decode \
  | pbcopy

Q: I get: “Error: unknown command "diff" for "helm"” - check Diff issues when running helmfile apply #1182

Install databus23/helm-diff

$ helm plugin install https://github.com/databus23/helm-diff
…
Installed plugin: diff

Q: How can I check the current configuration?

Use helm show values jenkinsci/jenkins.

Q: How can I split the values in its own file e.g. Jenkins-values.yaml?

releases:
    values:
      - jenkins-values.yaml

Q: How can I add/update plugins?

controller:
  installPlugins:
# bump versions of default plugins
    - kubernetes:1.30.8
    - workflow-aggregator:2.6
    - git:4.10.0
    - configuration-as-code:1.54
  additionalPlugins:
    - job-dsl:1.78.1
# credentials (2.6.2) requires a greater version of Jenkins (2.308) than 2.303.3
    - credentials:2.6.1
    - warnings-ng:9.7.0
    - jacoco:3.3.0

Q: How can I add jobs (e.g. a multi-branch pipeline job)?

controller:
  additionalExistingSecrets:
    - name: jenkins-existing-secrets
      keyName: jenkins-gitolite-id-rsa

  JCasC:
    configScripts:
      job-config: |
        jobs:
          - script: >
              folder(‘tools’)
          - script: >
              multibranchPipelineJob(‘tools/build-pipeline') {
                  branchSources {
                      git {
                          id('4711') // IMPORTANT: use a constant and unique identifier
                          remote('git@example.org:planets-tools’)
                          credentialsId('jenkins-id')
                          includes('*')
                      }
                  }
              }

Q: How can I add external credentials (e.g. managed by K8s)?

controller:
  additionalExistingSecrets:
    - name: existing-secrets
      keyName: jenkins-id
  JCasC:
      base-config: |
        credentials:
          system:
            domainCredentials:
              - credentials:
                - basicSSHUserPrivateKey:
                    scope: GLOBAL
                    id: "jenkins--id"
                    username: git
                    description: "git ssh key"
                    privateKeySource:
                      directEntry:
                        privateKey: "${existing-secrets-jenkins-id}"

K8s variable names are derived from name and keyName of the additional secrets.

Q: How can I remove the Jenkins installation? helmfile destroy.

Other resources


🙌 Photo by Milivoj Kuhar on Unsplash