blob: b54c28b313a0640ceb86909115dd9ce792d24e7c [file] [log] [blame] [view]
Giorgi Lekveishvili35982662024-04-05 13:05:40 +04001# Jenkins
2
3[![Artifact Hub](https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/jenkins)](https://artifacthub.io/packages/helm/jenkinsci/jenkins)
4[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
5[![Releases downloads](https://img.shields.io/github/downloads/jenkinsci/helm-charts/total.svg)](https://github.com/jenkinsci/helm-charts/releases)
6[![Join the chat at https://app.gitter.im/#/room/#jenkins-ci:matrix.org](https://badges.gitter.im/badge.svg)](https://app.gitter.im/#/room/#jenkins-ci:matrix.org)
7
gio20157e82026-07-22 13:10:48 +04008[Jenkins](https://www.jenkins.io/) is the leading open source automation server, Jenkins provides over 2000 plugins to support building, deploying and automating any project.
Giorgi Lekveishvili35982662024-04-05 13:05:40 +04009
10This chart installs a Jenkins server which spawns agents on [Kubernetes](http://kubernetes.io) utilizing the [Jenkins Kubernetes plugin](https://plugins.jenkins.io/kubernetes/).
11
12Inspired by the awesome work of [Carlos Sanchez](https://github.com/carlossg).
13
14## Get Repository Info
15
16```console
17helm repo add jenkins https://charts.jenkins.io
18helm repo update
19```
20
21_See [`helm repo`](https://helm.sh/docs/helm/helm_repo/) for command documentation._
22
23## Install Chart
24
25```console
gio20157e82026-07-22 13:10:48 +040026helm install [RELEASE_NAME] jenkins/jenkins [flags]
27```
28
29Since version `5.6.0` the chart is available as an OCI image and can be installed using:
30
31```console
32helm install [RELEASE_NAME] oci://ghcr.io/jenkinsci/helm-charts/jenkins [flags]
Giorgi Lekveishvili35982662024-04-05 13:05:40 +040033```
34
35_See [configuration](#configuration) below._
36
37_See [helm install](https://helm.sh/docs/helm/helm_install/) for command documentation._
38
39## Uninstall Chart
40
41```console
42# Helm 3
43$ helm uninstall [RELEASE_NAME]
44```
45
46This removes all the Kubernetes components associated with the chart and deletes the release.
47
48_See [helm uninstall](https://helm.sh/docs/helm/helm_uninstall/) for command documentation._
49
50## Upgrade Chart
51
52```console
53# Helm 3
54$ helm upgrade [RELEASE_NAME] jenkins/jenkins [flags]
55```
56
57_See [helm upgrade](https://helm.sh/docs/helm/helm_upgrade/) for command documentation._
58
59Visit the chart's [CHANGELOG](https://github.com/jenkinsci/helm-charts/blob/main/charts/jenkins/CHANGELOG.md) to view the chart's release history.
60For migration between major version check [migration guide](#migration-guide).
61
62## Building weekly releases
63
64The default charts target Long-Term-Support (LTS) releases of Jenkins.
65To use other versions the easiest way is to update the image tag to the version you want.
66You can also rebuild the chart if you want the `appVersion` field to match.
67
68## Configuration
69
70See [Customizing the Chart Before Installing](https://helm.sh/docs/intro/using_helm/#customizing-the-chart-before-installing).
71To see all configurable options with detailed comments, visit the chart's [values.yaml](https://github.com/jenkinsci/helm-charts/blob/main/charts/jenkins/values.yaml), or run these configuration commands:
72
73```console
74# Helm 3
75$ helm show values jenkins/jenkins
76```
77
gio20157e82026-07-22 13:10:48 +040078For a summary of all configurable options, see [VALUES.md](https://github.com/jenkinsci/helm-charts/blob/main/charts/jenkins/VALUES.md).
Giorgi Lekveishvili35982662024-04-05 13:05:40 +040079
80### Configure Security Realm and Authorization Strategy
81
82This chart configured a `securityRealm` and `authorizationStrategy` as shown below:
83
84```yaml
85controller:
86 JCasC:
87 securityRealm: |-
88 local:
89 allowsSignup: false
90 enableCaptcha: false
91 users:
92 - id: "${chart-admin-username}"
93 name: "Jenkins Admin"
94 password: "${chart-admin-password}"
95 authorizationStrategy: |-
96 loggedInUsersCanDoAnything:
97 allowAnonymousRead: false
98```
99
100With the configuration above there is only a single user.
101This is fine for getting started quickly, but it needs to be adjusted for any serious environment.
102
103So you should adjust this to suite your needs.
104That could be using LDAP / OIDC / .. as authorization strategy and use globalMatrix as authorization strategy to configure more fine-grained permissions.
105
106### Consider using a custom image
107
108This chart allows the user to specify plugins which should be installed. However, for production use cases one should consider to build a custom Jenkins image which has all required plugins pre-installed.
109This way you can be sure which plugins Jenkins is using when starting up and you avoid trouble in case of connectivity issues to the Jenkins update site.
110
gio20157e82026-07-22 13:10:48 +0400111The [Docker repository](https://github.com/jenkinsci/docker) for the Jenkins image contains [documentation](https://github.com/jenkinsci/docker#preinstalling-plugins) how to do it.
Giorgi Lekveishvili35982662024-04-05 13:05:40 +0400112
113Here is an example how that can be done:
114
115```Dockerfile
116FROM jenkins/jenkins:lts
117RUN jenkins-plugin-cli --plugins kubernetes workflow-aggregator git configuration-as-code
118```
119
120NOTE: If you want a reproducible build then you should specify a non-floating tag for the image `jenkins/jenkins:2.249.3` and specify plugin versions.
121
122Once you built the image and pushed it to your registry you can specify it in your values file like this:
123
124```yaml
125controller:
126 image: "registry/my-jenkins"
127 tag: "v1.2.3"
128 installPlugins: false
129```
130
131Notice: `installPlugins` is set to false to disable plugin download. In this case, the image `registry/my-jenkins:v1.2.3` must have the plugins specified as default value for [the `controller.installPlugins` directive](https://github.com/jenkinsci/helm-charts/blob/main/charts/jenkins/VALUES_SUMMARY.md#jenkins-plugins) to ensure that the configuration side-car system works as expected.
132
133In case you are using a private registry you can use 'imagePullSecretName' to specify the name of the secret to use when pulling the image:
134
135```yaml
136controller:
137 image: "registry/my-jenkins"
138 tag: "v1.2.3"
139 imagePullSecretName: registry-secret
140 installPlugins: false
141```
142
143### External URL Configuration
144
145If you are using the ingress definitions provided by this chart via the `controller.ingress` block the configured hostname will be the ingress hostname starting with `https://` or `http://` depending on the `tls` configuration.
146The Protocol can be overwritten by specifying `controller.jenkinsUrlProtocol`.
147
148If you are not using the provided ingress you can specify `controller.jenkinsUrl` to change the URL definition.
149
150### Configuration as Code
151
152Jenkins Configuration as Code (JCasC) is now a standard component in the Jenkins project.
153To allow JCasC's configuration from the helm values, the plugin [`configuration-as-code`](https://plugins.jenkins.io/configuration-as-code/) must be installed in the Jenkins Controller's Docker image (which is the case by default as specified by the [default value of the directive `controller.installPlugins`](https://github.com/jenkinsci/helm-charts/blob/main/charts/jenkins/VALUES_SUMMARY.md#jenkins-plugins)).
154
155JCasc configuration is passed through Helm values under the key `controller.JCasC`.
156The section ["Jenkins Configuration as Code (JCasC)" of the page "VALUES_SUMMARY.md"](https://github.com/jenkinsci/helm-charts/blob/main/charts/jenkins/VALUES_SUMMARY.md#jenkins-configuration-as-code-jcasc) lists all the possible directives.
157
158In particular, you may specify custom JCasC scripts by adding sub-key under the `controller.JCasC.configScripts` for each configuration area where each corresponds to a plugin or section of the UI.
159
160The sub-keys (prior to `|` character) are only labels used to give the section a meaningful name.
161The only restriction is they must conform to RFC 1123 definition of a DNS label, so they may only contain lowercase letters, numbers, and hyphens.
162
163Each key will become the name of a configuration yaml file on the controller in `/var/jenkins_home/casc_configs` (by default) and will be processed by the Configuration as Code Plugin during Jenkins startup.
164
165The lines after each `|` become the content of the configuration yaml file.
166
167The first line after this is a JCasC root element, e.g. jenkins, credentials, etc.
168
169Best reference is the Documentation link here: `https://<jenkins_url>/configuration-as-code`.
170
171The example below sets custom systemMessage:
172
173```yaml
174controller:
175 JCasC:
176 configScripts:
177 welcome-message: |
178 jenkins:
179 systemMessage: Welcome to our CI\CD server.
180```
181
182More complex example that creates ldap settings:
183
184```yaml
185controller:
186 JCasC:
187 configScripts:
188 ldap-settings: |
189 jenkins:
190 securityRealm:
191 ldap:
192 configurations:
193 - server: ldap.acme.com
194 rootDN: dc=acme,dc=uk
195 managerPasswordSecret: ${LDAP_PASSWORD}
196 groupMembershipStrategy:
197 fromUserRecord:
198 attributeName: "memberOf"
199```
200
201Keep in mind that default configuration file already contains some values that you won't be able to override under configScripts section.
202
203For example, you can not configure Jenkins URL and System Admin email address like this because of conflicting configuration error.
204
205Incorrect:
206
207```yaml
208controller:
209 JCasC:
210 configScripts:
211 jenkins-url: |
212 unclassified:
213 location:
214 url: https://example.com/jenkins
215 adminAddress: example@mail.com
216```
217
218Correct:
219
220```yaml
221controller:
222 jenkinsUrl: https://example.com/jenkins
223 jenkinsAdminEmail: example@mail.com
224```
225
gio20157e82026-07-22 13:10:48 +0400226Further JCasC examples can be found in the [configuration-as-code repository](https://github.com/jenkinsci/configuration-as-code-plugin/tree/master/demos).
Giorgi Lekveishvili35982662024-04-05 13:05:40 +0400227
228#### Breaking out large Config as Code scripts
229
gio20157e82026-07-22 13:10:48 +0400230Jenkins Config as Code scripts can become quite large, and maintaining all of your scripts within one yaml file can be difficult. The Config as Code plugin itself suggests updating the `CASC_JENKINS_CONFIG` environment variable to be a comma separated list of paths for the plugin to traverse, picking up the yaml files as needed.
231However, under the Jenkins helm chart, this `CASC_JENKINS_CONFIG` value is maintained through the templates. A better solution is to split your `controller.JCasC.configScripts` into separate values files, and provide each file during the helm install.
Giorgi Lekveishvili35982662024-04-05 13:05:40 +0400232
233For example, you can have a values file (e.g values_main.yaml) that defines the values described in the `VALUES_SUMMARY.md` for your Jenkins configuration:
234
235```yaml
236jenkins:
237 controller:
238 jenkinsUrlProtocol: https
239 installPlugins: false
240 ...
241```
242
243In a second file (e.g values_jenkins_casc.yaml), you can define a section of your config scripts:
244
245```yaml
246jenkins:
247 controller:
248 JCasC:
249 configScripts:
gio20157e82026-07-22 13:10:48 +0400250 jenkinsCasc: |
Giorgi Lekveishvili35982662024-04-05 13:05:40 +0400251 jenkins:
252 disableRememberMe: false
253 mode: NORMAL
254 ...
255```
256
257And keep extending your config scripts by creating more files (so not all config scripts are located in one yaml file for better maintenance):
258
259values_jenkins_unclassified.yaml
260
261```yaml
262jenkins:
263 controller:
264 JCasC:
265 configScripts:
266 unclassifiedCasc: |
267 unclassified:
268 ...
269```
270
gio20157e82026-07-22 13:10:48 +0400271When installing, you provide all relevant yaml files (e.g `helm install -f values_main.yaml -f values_jenkins_casc.yaml -f values_jenkins_unclassified.yaml ...`). Instead of updating the `CASC_JENKINS_CONFIG` environment variable to include multiple paths, multiple CasC yaml files will be created in the same path `var/jenkins_home/casc_configs`.
Giorgi Lekveishvili35982662024-04-05 13:05:40 +0400272
273#### Config as Code With or Without Auto-Reload
274
275Config as Code changes (to `controller.JCasC.configScripts`) can either force a new pod to be created and only be applied at next startup, or can be auto-reloaded on-the-fly.
276If you set `controller.sidecars.configAutoReload.enabled` to `true`, a second, auxiliary container will be installed into the Jenkins controller pod, known as a "sidecar".
277This watches for changes to configScripts, copies the content onto the Jenkins file-system and issues a POST to `http://<jenkins_url>/reload-configuration-as-code` with a pre-shared key.
278You can monitor this sidecar's logs using command `kubectl logs <controller_pod> -c config-reload -f`.
279If you want to enable auto-reload then you also need to configure rbac as the container which triggers the reload needs to watch the config maps:
280
281```yaml
282controller:
283 sidecars:
284 configAutoReload:
285 enabled: true
286rbac:
287 create: true
288```
289
290### Allow Limited HTML Markup in User-Submitted Text
291
292Some third-party systems (e.g. GitHub) use HTML-formatted data in their payload sent to a Jenkins webhook (e.g. URL of a pull-request being built).
293To display such data as processed HTML instead of raw text set `controller.enableRawHtmlMarkupFormatter` to true.
294This option requires installation of the [OWASP Markup Formatter Plugin (antisamy-markup-formatter)](https://plugins.jenkins.io/antisamy-markup-formatter/).
295This plugin is **not** installed by default but may be added to `controller.additionalPlugins`.
296
297### Change max connections to Kubernetes API
gio20157e82026-07-22 13:10:48 +0400298
Giorgi Lekveishvili35982662024-04-05 13:05:40 +0400299When using agents with containers other than JNLP, The kubernetes plugin will communicate with those containers using the Kubernetes API. this changes the maximum concurrent connections
gio20157e82026-07-22 13:10:48 +0400300
Giorgi Lekveishvili35982662024-04-05 13:05:40 +0400301```yaml
302agent:
303 maxRequestsPerHostStr: "32"
304```
gio20157e82026-07-22 13:10:48 +0400305
Giorgi Lekveishvili35982662024-04-05 13:05:40 +0400306This will change the configuration of the kubernetes "cloud" (as called by jenkins) that is created automatically as part of this helm chart.
307
308### Change container cleanup timeout API
gio20157e82026-07-22 13:10:48 +0400309
Giorgi Lekveishvili35982662024-04-05 13:05:40 +0400310For tasks that use very large images, this timeout can be increased to avoid early termination of the task while the Kubernetes pod is still deploying.
gio20157e82026-07-22 13:10:48 +0400311
Giorgi Lekveishvili35982662024-04-05 13:05:40 +0400312```yaml
313agent:
314 retentionTimeout: "32"
315```
gio20157e82026-07-22 13:10:48 +0400316
Giorgi Lekveishvili35982662024-04-05 13:05:40 +0400317This will change the configuration of the kubernetes "cloud" (as called by jenkins) that is created automatically as part of this helm chart.
318
319### Change seconds to wait for pod to be running
gio20157e82026-07-22 13:10:48 +0400320
Giorgi Lekveishvili35982662024-04-05 13:05:40 +0400321This will change how long Jenkins will wait (seconds) for pod to be in running state.
gio20157e82026-07-22 13:10:48 +0400322
Giorgi Lekveishvili35982662024-04-05 13:05:40 +0400323```yaml
324agent:
325 waitForPodSec: "32"
326```
gio20157e82026-07-22 13:10:48 +0400327
Giorgi Lekveishvili35982662024-04-05 13:05:40 +0400328This will change the configuration of the kubernetes "cloud" (as called by jenkins) that is created automatically as part of this helm chart.
329
330### Mounting Volumes into Agent Pods
331
332Your Jenkins Agents will run as pods, and it's possible to inject volumes where needed:
333
334```yaml
335agent:
336 volumes:
gio20157e82026-07-22 13:10:48 +0400337 - type: Secret
338 secretName: jenkins-mysecrets
339 mountPath: /var/run/secrets/jenkins-mysecrets
Giorgi Lekveishvili35982662024-04-05 13:05:40 +0400340```
341
342The supported volume types are: `ConfigMap`, `EmptyDir`, `HostPath`, `Nfs`, `PVC`, `Secret`.
343Each type supports a different set of configurable attributes, defined by [the corresponding Java class](https://github.com/jenkinsci/kubernetes-plugin/tree/master/src/main/java/org/csanchez/jenkins/plugins/kubernetes/volumes).
344
345### NetworkPolicy
346
347To make use of the NetworkPolicy resources created by default, install [a networking plugin that implements the Kubernetes NetworkPolicy spec](https://kubernetes.io/docs/tasks/administer-cluster/declare-network-policy#before-you-begin).
348
349[Install](#install-chart) helm chart with network policy enabled by setting `networkPolicy.enabled` to `true`.
350
351You can use `controller.networkPolicy.internalAgents` and `controller.networkPolicy.externalAgents` stanzas for fine-grained controls over where internal/external agents can connect from.
352Internal ones are allowed based on pod labels and (optionally) namespaces, and external ones are allowed based on IP ranges.
353
354### Script approval list
355
356`controller.scriptApproval` allows to pass function signatures that will be allowed in pipelines.
357Example:
358
359```yaml
360controller:
361 scriptApproval:
362 - "method java.util.Base64$Decoder decode java.lang.String"
363 - "new java.lang.String byte[]"
364 - "staticMethod java.util.Base64 getDecoder"
365```
366
367### Custom Labels
368
369`controller.serviceLabels` can be used to add custom labels in `jenkins-controller-svc.yaml`.
370For example:
371
372```yaml
373ServiceLabels:
374 expose: true
375```
376
377### Persistence
378
379The Jenkins image stores persistence under `/var/jenkins_home` path of the container.
380A dynamically managed Persistent Volume Claim is used to keep the data across deployments, by default.
381This is known to work in GCE, AWS, and minikube. Alternatively, a previously configured Persistent Volume Claim can be used.
382
383It is possible to mount several volumes using `persistence.volumes` and `persistence.mounts` parameters.
384See additional `persistence` values using [configuration commands](#configuration).
385
386#### Existing PersistentVolumeClaim
387
3881. Create the PersistentVolume
3892. Create the PersistentVolumeClaim
3903. [Install](#install-chart) the chart, setting `persistence.existingClaim` to `PVC_NAME`
391
gio20157e82026-07-22 13:10:48 +0400392#### Long Volume Attach-/Mount Times
Giorgi Lekveishvili35982662024-04-05 13:05:40 +0400393
394Certain volume type and filesystem format combinations may experience long
395attach/mount times, [10 or more minutes][K8S_VOLUME_TIMEOUT], when using
gio20157e82026-07-22 13:10:48 +0400396`fsGroup`. This issue may result in the following entries in the pod's event
Giorgi Lekveishvili35982662024-04-05 13:05:40 +0400397history:
398
399```console
400Warning FailedMount 38m kubelet, aks-default-41587790-2 Unable to attach or mount volumes: unmounted volumes=[jenkins-home], unattached volumes=[plugins plugin-dir jenkins-token-rmq2g sc-config-volume tmp jenkins-home jenkins-config secrets-dir]: timed out waiting for the condition
401```
402
403In these cases, experiment with replacing `fsGroup` with
gio20157e82026-07-22 13:10:48 +0400404`supplementalGroups` in the pod's `securityContext`. This can be achieved by
Giorgi Lekveishvili35982662024-04-05 13:05:40 +0400405setting the `controller.podSecurityContextOverride` Helm chart value to
406something like:
407
408```yaml
409controller:
410 podSecurityContextOverride:
411 runAsNonRoot: true
412 runAsUser: 1000
413 supplementalGroups: [1000]
414```
415
416This issue has been reported on [azureDisk with ext4][K8S_VOLUME_TIMEOUT] and
417on [Alibaba cloud][K8S_VOLUME_TIMEOUT_ALIBABA].
418
419[K8S_VOLUME_TIMEOUT]: https://github.com/kubernetes/kubernetes/issues/67014
420[K8S_VOLUME_TIMEOUT_ALIBABA]: https://github.com/kubernetes/kubernetes/issues/67014#issuecomment-698770511
421
422#### Storage Class
423
424It is possible to define which storage class to use, by setting `persistence.storageClass` to `[customStorageClass]`.
425If set to a dash (`-`), dynamic provisioning is disabled.
426If the storage class is set to null or left undefined (`""`), the default provisioner is used (gp2 on AWS, standard on GKE, AWS & OpenStack).
427
428### Additional Secrets
429
430Additional secrets and Additional Existing Secrets,
431can be mounted into the Jenkins controller through the chart or created using `controller.additionalSecrets` or `controller.additionalExistingSecrets`.
432A common use case might be identity provider credentials if using an external LDAP or OIDC-based identity provider.
433The secret may then be referenced in JCasC configuration (see [JCasC configuration](#configuration-as-code)).
434
435`values.yaml` controller section, referencing mounted secrets:
gio20157e82026-07-22 13:10:48 +0400436
Giorgi Lekveishvili35982662024-04-05 13:05:40 +0400437```yaml
438controller:
439 # the 'name' and 'keyName' are concatenated with a '-' in between, so for example:
440 # an existing secret "secret-credentials" and a key inside it named "github-password" should be used in Jcasc as ${secret-credentials-github-password}
441 # 'name' and 'keyName' must be lowercase RFC 1123 label must consist of lower case alphanumeric characters or '-',
442 # and must start and end with an alphanumeric character (e.g. 'my-name', or '123-abc')
443 # existingSecret existing secret "secret-credentials" and a key inside it named "github-username" should be used in Jcasc as ${github-username}
444 # When using existingSecret no need to specify the keyName under additionalExistingSecrets.
445 existingSecret: secret-credentials
gio20157e82026-07-22 13:10:48 +0400446
Giorgi Lekveishvili35982662024-04-05 13:05:40 +0400447 additionalExistingSecrets:
448 - name: secret-credentials
449 keyName: github-username
450 - name: secret-credentials
451 keyName: github-password
452 - name: secret-credentials
453 keyName: token
gio20157e82026-07-22 13:10:48 +0400454
Giorgi Lekveishvili35982662024-04-05 13:05:40 +0400455 additionalSecrets:
456 - name: client_id
457 value: abc123
458 - name: client_secret
459 value: xyz999
460 JCasC:
461 securityRealm: |
462 oic:
463 clientId: ${client_id}
464 clientSecret: ${client_secret}
465 ...
466 configScripts:
467 jenkins-casc-configs: |
468 credentials:
469 system:
470 domainCredentials:
471 - credentials:
472 - string:
473 description: "github access token"
474 id: "github_app_token"
475 scope: GLOBAL
476 secret: ${secret-credentials-token}
477 - usernamePassword:
478 description: "github access username password"
479 id: "github_username_pass"
480 password: ${secret-credentials-github-password}
481 scope: GLOBAL
482 username: ${secret-credentials-github-username}
483```
484
485For more information, see [JCasC documentation](https://github.com/jenkinsci/configuration-as-code-plugin/blob/master/docs/features/secrets.adoc#kubernetes-secrets).
486
487### Secret Claims from HashiCorp Vault
488
489It's possible for this chart to generate `SecretClaim` resources in order to automatically create and maintain Kubernetes `Secrets` from HashiCorp [Vault](https://www.vaultproject.io/) via [`kube-vault-controller`](https://github.com/roboll/kube-vault-controller)
490
491These `Secrets` can then be referenced in the same manner as Additional Secrets above.
492
493This can be achieved by defining required Secret Claims within `controller.secretClaims`, as follows:
gio20157e82026-07-22 13:10:48 +0400494
Giorgi Lekveishvili35982662024-04-05 13:05:40 +0400495```yaml
496controller:
497 secretClaims:
498 - name: jenkins-secret
499 path: secret/path
500 - name: jenkins-short-ttl
501 path: secret/short-ttl-path
502 renew: 60
503```
504
505### RBAC
506
507RBAC is enabled by default. If you want to disable it you will need to set `rbac.create` to `false`.
508
509### Adding Custom Pod Templates
510
511It is possible to add custom pod templates for the default configured kubernetes cloud.
512Add a key under `agent.podTemplates` for each pod template. Each key (prior to `|` character) is just a label, and can be any value.
513Keys are only used to give the pod template a meaningful name. The only restriction is they may only contain RFC 1123 \ DNS label characters: lowercase letters, numbers, and hyphens. Each pod template can contain multiple containers.
514There's no need to add the _jnlp_ container since the kubernetes plugin will automatically inject it into the pod.
515For this pod templates configuration to be loaded the following values must be set:
516
517```yaml
518controller.JCasC.defaultConfig: true
519```
520
521The example below creates a python pod template in the kubernetes cloud:
522
523```yaml
524agent:
525 podTemplates:
526 python: |
527 - name: python
528 label: jenkins-python
529 serviceAccount: jenkins
530 containers:
531 - name: python
532 image: python:3
533 command: "/bin/sh -c"
534 args: "cat"
535 ttyEnabled: true
536 privileged: true
537 resourceRequestCpu: "400m"
538 resourceRequestMemory: "512Mi"
539 resourceLimitCpu: "1"
540 resourceLimitMemory: "1024Mi"
541```
542
543Best reference is `https://<jenkins_url>/configuration-as-code/reference#Cloud-kubernetes`.
544
545### Adding Pod Templates Using additionalAgents
546
547`additionalAgents` may be used to configure additional kubernetes pod templates.
548Each additional agent corresponds to `agent` in terms of the configurable values and inherits all values from `agent` so you only need to specify values which differ.
549For example:
550
551```yaml
552agent:
553 podName: default
554 customJenkinsLabels: default
555 # set resources for additional agents to inherit
556 resources:
557 limits:
558 cpu: "1"
559 memory: "2048Mi"
560
561additionalAgents:
562 maven:
563 podName: maven
564 customJenkinsLabels: maven
565 # An example of overriding the jnlp container
566 # sideContainerName: jnlp
567 image: jenkins/jnlp-agent-maven
568 tag: latest
569 python:
570 podName: python
571 customJenkinsLabels: python
572 sideContainerName: python
573 image: python
574 tag: "3"
575 command: "/bin/sh -c"
576 args: "cat"
577 TTYEnabled: true
578```
579
580### Ingress Configuration
581
582This chart provides ingress resources configurable via the `controller.ingress` block.
583
584The simplest configuration looks like the following:
585
586```yaml
587controller:
gio20157e82026-07-22 13:10:48 +0400588 ingress:
589 enabled: true
590 paths: []
591 apiVersion: "extensions/v1beta1"
592 hostName: jenkins.example.com
Giorgi Lekveishvili35982662024-04-05 13:05:40 +0400593```
594
595This snippet configures an ingress rule for exposing jenkins at `jenkins.example.com`
596
597You can define labels and annotations via `controller.ingress.labels` and `controller.ingress.annotations` respectively.
598Additionally, you can configure the ingress tls via `controller.ingress.tls`.
599By default, this ingress rule exposes all paths.
600If needed this can be overwritten by specifying the wanted paths in `controller.ingress.paths`
601
602If you want to configure a secondary ingress e.g. you don't want the jenkins instance exposed but still want to receive webhooks you can configure `controller.secondaryingress`.
603The secondaryingress doesn't expose anything by default and has to be configured via `controller.secondaryingress.paths`:
604
605```yaml
606controller:
gio20157e82026-07-22 13:10:48 +0400607 ingress:
608 enabled: true
609 apiVersion: "extensions/v1beta1"
610 hostName: "jenkins.internal.example.com"
611 annotations:
612 kubernetes.io/ingress.class: "internal"
613 secondaryingress:
614 enabled: true
615 apiVersion: "extensions/v1beta1"
616 hostName: "jenkins-scm.example.com"
617 annotations:
618 kubernetes.io/ingress.class: "public"
619 paths:
620 - /github-webhook
Giorgi Lekveishvili35982662024-04-05 13:05:40 +0400621```
622
623## Prometheus Metrics
624
625If you want to expose Prometheus metrics you need to install the [Jenkins Prometheus Metrics Plugin](https://github.com/jenkinsci/prometheus-plugin).
626It will expose an endpoint (default `/prometheus`) with metrics where a Prometheus Server can scrape.
627
628If you have implemented [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator), you can set `controller.prometheus.enabled` to `true` to configure a `ServiceMonitor` and `PrometheusRule`.
629If you want to further adjust alerting rules you can do so by configuring `controller.prometheus.alertingrules`
630
631If you have implemented Prometheus without using the operator, you can leave `controller.prometheus.enabled` set to `false`.
632
633### Running Behind a Forward Proxy
634
635The controller pod uses an Init Container to install plugins etc. If you are behind a corporate proxy it may be useful to set `controller.initContainerEnv` to add environment variables such as `http_proxy`, so that these can be downloaded.
636
637Additionally, you may want to add env vars for the init container, the Jenkins container, and the JVM (`controller.javaOpts`):
638
639```yaml
640controller:
641 initContainerEnv:
642 - name: http_proxy
643 value: "http://192.168.64.1:3128"
644 - name: https_proxy
645 value: "http://192.168.64.1:3128"
646 - name: no_proxy
647 value: ""
648 - name: JAVA_OPTS
649 value: "-Dhttps.proxyHost=proxy_host_name_without_protocol -Dhttps.proxyPort=3128"
650 containerEnv:
651 - name: http_proxy
652 value: "http://192.168.64.1:3128"
653 - name: https_proxy
654 value: "http://192.168.64.1:3128"
655 javaOpts: >-
656 -Dhttp.proxyHost=192.168.64.1
657 -Dhttp.proxyPort=3128
658 -Dhttps.proxyHost=192.168.64.1
659 -Dhttps.proxyPort=3128
660```
661
662### HTTPS Keystore Configuration
663
664[This configuration](https://wiki.jenkins.io/pages/viewpage.action?pageId=135468777) enables jenkins to use keystore in order to serve HTTPS.
665Here is the [value file section](https://wiki.jenkins.io/pages/viewpage.action?pageId=135468777#RunningJenkinswithnativeSSL/HTTPS-ConfigureJenkinstouseHTTPSandtheJKSkeystore) related to keystore configuration.
666Keystore itself should be placed in front of `jenkinsKeyStoreBase64Encoded` key and in base64 encoded format. To achieve that after having `keystore.jks` file simply do this: `cat keystore.jks | base64` and paste the output in front of `jenkinsKeyStoreBase64Encoded`.
667After enabling `httpsKeyStore.enable` make sure that `httpPort` and `targetPort` are not the same, as `targetPort` will serve HTTPS.
668Do not set `controller.httpsKeyStore.httpPort` to `-1` because it will cause readiness and liveliness prob to fail.
669If you already have a kubernetes secret that has keystore and its password you can specify its' name in front of `jenkinsHttpsJksSecretName`, You need to remember that your secret should have proper data key names `jenkins-jks-file` (or override the key name using `jenkinsHttpsJksSecretKey`)
670and `https-jks-password` (or override the key name using `jenkinsHttpsJksPasswordSecretKey`; additionally you can make it get the password from a different secret using `jenkinsHttpsJksPasswordSecretName`). Example:
671
672```yaml
673controller:
gio20157e82026-07-22 13:10:48 +0400674 httpsKeyStore:
675 enable: true
676 jenkinsHttpsJksSecretName: ""
677 httpPort: 8081
678 path: "/var/jenkins_keystore"
679 fileName: "keystore.jks"
680 password: "changeit"
681 jenkinsKeyStoreBase64Encoded: ""
Giorgi Lekveishvili35982662024-04-05 13:05:40 +0400682```
gio20157e82026-07-22 13:10:48 +0400683
Giorgi Lekveishvili35982662024-04-05 13:05:40 +0400684### AWS Security Group Policies
685
686To create SecurityGroupPolicies set `awsSecurityGroupPolicies.enabled` to true and add your policies. Each policy requires a `name`, array of `securityGroupIds` and a `podSelector`. Example:
687
688```yaml
689awsSecurityGroupPolicies:
690 enabled: true
691 policies:
692 - name: "jenkins-controller"
gio20157e82026-07-22 13:10:48 +0400693 securityGroupIds:
Giorgi Lekveishvili35982662024-04-05 13:05:40 +0400694 - sg-123456789
695 podSelector:
696 matchExpressions:
697 - key: app.kubernetes.io/component
698 operator: In
699 values:
700 - jenkins-controller
701```
702
703### Agent Direct Connection
704
705Set `directConnection` to `true` to allow agents to connect directly to a given TCP port without having to negotiate a HTTP(S) connection. This can allow you to have agent connections without an external HTTP(S) port. Example:
706
707```yaml
708agent:
709 jenkinsTunnel: "jenkinsci-agent:50000"
710 directConnection: true
711```
712
713## Migration Guide
714
715### From stable repository
716
717Upgrade an existing release from `stable/jenkins` to `jenkins/jenkins` seamlessly by ensuring you have the latest [repository info](#get-repository-info) and running the [upgrade commands](#upgrade-chart) specifying the `jenkins/jenkins` chart.
718
719### Major Version Upgrades
720
721Chart release versions follow [SemVer](../../CONTRIBUTING.md#versioning), where a MAJOR version change (example `1.0.0` -> `2.0.0`) indicates an incompatible breaking change needing manual actions.
722
723See [UPGRADING.md](./UPGRADING.md) for a list of breaking changes