Update website - 0.5.0 release

This commit is contained in:
Tomasz Sęk 2021-01-18 15:41:30 +01:00
parent fe81e5ab3d
commit 9f261169f0
No known key found for this signature in database
GPG Key ID: DC356D23F6A644D0
21 changed files with 3858 additions and 20 deletions

View File

@ -1,14 +1,14 @@
---
title: "Latest (v0.4.x)"
linkTitle: "Latest (v0.4.x)"
title: "Latest (v0.5.x)"
linkTitle: "Latest (v0.5.x)"
weight: 10
date: 2020-04-13
date: 2021-01-18
description: >
How to work with jenkins-operator latest version
---
{{% pageinfo %}}
This document describes a getting started guide for **Jenkins Operator** `v0.4.x` and an additional configuration.
This document describes a getting started guide for **Jenkins Operator** `v0.5.x` and an additional configuration.
{{% /pageinfo %}}
## First Steps

View File

@ -2,7 +2,7 @@
title: "AKS"
linkTitle: "AKS"
weight: 10
date: 2020-04-13
date: 2021-01-18
description: >
Additional configuration for Azure Kubernetes Service
---

View File

@ -2,7 +2,7 @@
title: "Configuration"
linkTitle: "Configuration"
weight: 2
date: 2020-04-13
date: 2021-01-18
description: >
How to configure Jenkins with Operator
---

View File

@ -2,7 +2,7 @@
title: "Configure backup and restore"
linkTitle: "Configure backup and restore"
weight: 10
date: 2020-04-13
date: 2021-01-18
description: >
Prevent loss of job history
---

View File

@ -2,7 +2,7 @@
title: "Custom Backup and Restore Providers"
linkTitle: "Custom Backup and Restore Providers"
weight: 10
date: 2020-04-13
date: 2021-01-18
description: >
Custom backup and restore provider
---

View File

@ -2,7 +2,7 @@
title: "Customization"
linkTitle: "Customization"
weight: 3
date: 2020-04-13
date: 2021-01-18
description: >
How to customize Jenkins
---

View File

@ -2,7 +2,7 @@
title: "Deploy Jenkins"
linkTitle: "Deploy Jenkins"
weight: 1
date: 2020-04-13
date: 2021-01-18
description: >
Deploy production ready Jenkins Operator manifest
---

View File

@ -2,7 +2,7 @@
title: "Diagnostics"
linkTitle: "Diagnostics"
weight: 40
date: 2020-04-13
date: 2021-01-18
description: >
How to deal with Jenkins Operator problems
---

View File

@ -2,7 +2,7 @@
title: "Notifications"
linkTitle: "Notifications"
weight: 10
date: 2020-04-13
date: 2021-01-18
description: >
How to setup operator notifications.
---

View File

@ -2,7 +2,7 @@
title: "Schema"
linkTitle: "Schema"
weight: 40
date: 2020-04-13
date: 2021-01-18
description: >
API Schema definitions for Jenkins CRD
---
@ -1295,19 +1295,19 @@ More info: <a href="https://kubernetes.io/docs/concepts/storage/volumes">https:/
<p>BasePlugins contains plugins required by operator
Defaults to :
- name: kubernetes
version: 1.25.2
version: &ldquo;1.28.6&rdquo;
- name: workflow-job
version: &ldquo;2.39&rdquo;
version: &ldquo;2.40&rdquo;
- name: workflow-aggregator
version: &ldquo;2.6&rdquo;
- name: git
version: 4.2.2
version: &ldquo;4.5.0&rdquo;
- name: job-dsl
version: &ldquo;1.77&rdquo;
- name: configuration-as-code
version: &ldquo;1.38&rdquo;
version: &ldquo;1.46&rdquo;
- name: kubernetes-credentials-provider
version: 0.13</p>
version: &ldquo;0.15&rdquo;</p>
</td>
</tr>
<tr>
@ -2040,6 +2040,21 @@ Handler
</tr>
<tr>
<td>
<code>getLatestAction</code></br>
<em>
<a href="#github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2.Handler">
Handler
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>GetLatestAction defines action which returns the latest backup number. If there is no backup &ldquo;-1&rdquo; should be
returned.</p>
</td>
</tr>
<tr>
<td>
<code>recoveryOnce</code></br>
<em>
uint64
@ -2623,5 +2638,5 @@ SecretKeySelector
<hr/>
<p><em>
Generated with <code>gen-crd-api-reference-docs</code>
on git commit <code>1c853e69</code>.
</em></p>
on git commit <code>fe81e5a</code>.
</em></p>

View File

@ -0,0 +1,18 @@
---
title: "v0.4.x"
linkTitle: "v0.4.x"
weight: 10
date: 2020-04-13
description: >
How to work with jenkins-operator latest version
---
{{% pageinfo %}}
This document describes a getting started guide for **Jenkins Operator** `v0.4.x` and an additional configuration.
{{% /pageinfo %}}
## First Steps
Prepare your Kubernetes cluster and set up your `kubectl` access.
Once you have running Kubernetes cluster you can focus on installing **Jenkins Operator** according to the [Installation](/kubernetes-operator/docs/installation/) guide.

View File

@ -0,0 +1,24 @@
---
title: "AKS"
linkTitle: "AKS"
weight: 10
date: 2020-04-13
description: >
Additional configuration for Azure Kubernetes Service
---
Azure AKS managed Kubernetes service adds to every pod the following environment variables:
```yaml
- name: KUBERNETES_PORT_443_TCP_ADDR
value:
- name: KUBERNETES_PORT
value: tcp://
- name: KUBERNETES_PORT_443_TCP
value: tcp://
- name: KUBERNETES_SERVICE_HOST
value:
```
The operator is aware of it and omits these environment variables when checking if a Jenkins pod environment has been changed. It prevents the
restart of a Jenkins pod over and over again.

View File

@ -0,0 +1,332 @@
---
title: "Configuration"
linkTitle: "Configuration"
weight: 2
date: 2020-04-13
description: >
How to configure Jenkins with Operator
---
## Configure Seed Jobs and Pipelines
Jenkins operator uses [job-dsl][job-dsl] and [kubernetes-credentials-provider][kubernetes-credentials-provider] plugins for configuring jobs
and deploy keys.
## Prepare job definitions and pipelines
First you have to prepare pipelines and job definition in your GitHub repository using the following structure:
```
cicd/
├── jobs
│   └── build.jenkins
└── pipelines
└── build.jenkins
```
**`cicd/jobs/build.jenkins`** is a job definition:
```
#!/usr/bin/env groovy
pipelineJob('build-jenkins-operator') {
displayName('Build jenkins-operator')
definition {
cpsScm {
scm {
git {
remote {
url('https://github.com/jenkinsci/kubernetes-operator.git')
credentials('jenkins-operator')
}
branches('*/master')
}
}
scriptPath('cicd/pipelines/build.jenkins')
}
}
}
```
**`cicd/pipelines/build.jenkins`** is an actual Jenkins pipeline:
```
#!/usr/bin/env groovy
def label = "build-jenkins-operator-${UUID.randomUUID().toString()}"
def home = "/home/jenkins"
def workspace = "${home}/workspace/build-jenkins-operator"
def workdir = "${workspace}/src/github.com/jenkinsci/kubernetes-operator/"
podTemplate(label: label,
containers: [
containerTemplate(name: 'jnlp', image: 'jenkins/inbound-agent:alpine'),
containerTemplate(name: 'go', image: 'golang:1-alpine', command: 'cat', ttyEnabled: true),
],
envVars: [
envVar(key: 'GOPATH', value: workspace),
],
) {
node(label) {
dir(workdir) {
stage('Init') {
timeout(time: 3, unit: 'MINUTES') {
checkout scm
}
container('go') {
sh 'apk --no-cache --update add make git gcc libc-dev'
}
}
stage('Dep') {
container('go') {
sh 'make dep'
}
}
stage('Test') {
container('go') {
sh 'make test'
}
}
stage('Build') {
container('go') {
sh 'make build'
}
}
}
}
}
```
## Configure Seed Jobs
Jenkins Seed Jobs are configured using `Jenkins.spec.seedJobs` section from your custom resource manifest:
```
apiVersion: jenkins.io/v1alpha2
kind: Jenkins
metadata:
name: example
spec:
seedJobs:
- id: jenkins-operator
targets: "cicd/jobs/*.jenkins"
description: "Jenkins Operator repository"
repositoryBranch: master
repositoryUrl: https://github.com/jenkinsci/kubernetes-operator.git
```
**Jenkins Operator** will automatically discover and configure all the seed jobs.
You can verify if deploy keys were successfully configured in the Jenkins **Credentials** tab.
![jenkins](/kubernetes-operator/img/jenkins-credentials.png)
You can verify if your pipelines were successfully configured in the Jenkins Seed Job console output.
![jenkins](/kubernetes-operator/img/jenkins-seed.png)
If your GitHub repository is **private** you have to configure SSH or username/password authentication.
### SSH authentication
#### Generate SSH Keys
There are two methods of SSH private key generation:
```bash
$ openssl genrsa -out <filename> 2048
```
or
```bash
$ ssh-keygen -t rsa -b 2048
$ ssh-keygen -p -f <filename> -m pem
```
Then copy content from generated file.
#### Public key
If you want to upload your public key to your Git server you need to extract it.
If key was generated by `openssl` then you need to type this to extract public key:
```bash
$ openssl rsa -in <filename> -pubout > <filename>.pub
```
If key was generated by `ssh-keygen` the public key content is located in <filename>.pub and there is no need to extract public key
#### Configure SSH authentication
Configure a seed job like this:
```
apiVersion: jenkins.io/v1alpha2
kind: Jenkins
metadata:
name: example
spec:
seedJobs:
- id: jenkins-operator-ssh
credentialType: basicSSHUserPrivateKey
credentialID: k8s-ssh
targets: "cicd/jobs/*.jenkins"
description: "Jenkins Operator repository"
repositoryBranch: master
repositoryUrl: ssh://git@github.com:jenkinsci/kubernetes-operator.git
```
and create a Kubernetes Secret (name of secret should be the same from `credentialID` field):
```
apiVersion: v1
kind: Secret
metadata:
name: k8s-ssh
labels:
"jenkins.io/credentials-type": "basicSSHUserPrivateKey"
annotations:
"jenkins.io/credentials-description" : "ssh github.com:jenkinsci/kubernetes-operator"
stringData:
privateKey: |
-----BEGIN RSA PRIVATE KEY-----
MIIJKAIBAAKCAgEAxxDpleJjMCN5nusfW/AtBAZhx8UVVlhhhIKXvQ+dFODQIdzO
oDXybs1zVHWOj31zqbbJnsfsVZ9Uf3p9k6xpJ3WFY9b85WasqTDN1xmSd6swD4N8
...
username: github_user_name
```
### Username & password authentication
Configure the seed job like:
```
apiVersion: jenkins.io/v1alpha2
kind: Jenkins
metadata:
name: example
spec:
seedJobs:
- id: jenkins-operator-user-pass
credentialType: usernamePassword
credentialID: k8s-user-pass
targets: "cicd/jobs/*.jenkins"
description: "Jenkins Operator repository"
repositoryBranch: master
repositoryUrl: https://github.com/jenkinsci/kubernetes-operator.git
```
and create a Kubernetes Secret (name of secret should be the same from `credentialID` field):
```
apiVersion: v1
kind: Secret
metadata:
name: k8s-user-pass
stringData:
username: github_user_name
password: password_or_token
```
### External authentication
You can use `external` credential type if you want to configure authentication using Configuration As Code or Groovy Script.
## HTTP Proxy for downloading plugins
To use forwarding proxy with an operator to download plugins you need to add the following environment variable to Jenkins Custom Resource (CR), e.g.:
```yaml
spec:
master:
containers:
- name: jenkins-master
env:
- name: CURL_OPTIONS
value: -L -x <proxy_url>
```
In `CURL_OPTIONS` var you can set additional arguments to `curl` command.
## Pulling Docker images from private repositories
To pull a Docker Image from private repository you can use `imagePullSecrets`.
Please follow the instructions on [creating a secret with a docker config](https://kubernetes.io/docs/concepts/containers/images/?origin_team=T42NTAGHM#creating-a-secret-with-a-docker-config).
### Docker Hub Configuration
To use Docker Hub additional steps are required.
Edit the previously created secret:
```bash
kubectl -n <namespace> edit secret <name>
```
The `.dockerconfigjson` key's value needs to be replaced with a modified version.
After modifications, it needs to be encoded as a Base64 value before setting the `.dockerconfigjson` key.
Example config file to modify and use:
```
{
"auths":{
"https://index.docker.io/v1/":{
"username":"user",
"password":"password",
"email":"yourdockeremail@gmail.com",
"auth":"base64 of string user:password"
},
"auth.docker.io":{
"username":"user",
"password":"password",
"email":"yourdockeremail@gmail.com",
"auth":"base64 of string user:password"
},
"registry.docker.io":{
"username":"user",
"password":"password",
"email":"yourdockeremail@gmail.com",
"auth":"base64 of string user:password"
},
"docker.io":{
"username":"user",
"password":"password",
"email":"yourdockeremail@gmail.com",
"auth":"base64 of string user:password"
},
"https://registry-1.docker.io/v2/": {
"username":"user",
"password":"password",
"email":"yourdockeremail@gmail.com",
"auth":"base64 of string user:password"
},
"registry-1.docker.io/v2/": {
"username":"user",
"password":"password",
"email":"yourdockeremail@gmail.com",
"auth":"base64 of string user:password"
},
"registry-1.docker.io": {
"username":"user",
"password":"password",
"email":"yourdockeremail@gmail.com",
"auth":"base64 of string user:password"
},
"https://registry-1.docker.io": {
"username":"user",
"password":"password",
"email":"yourdockeremail@gmail.com",
"auth":"base64 of string user:password"
}
}
}
```
[job-dsl]:https://github.com/jenkinsci/job-dsl-plugin
[kubernetes-credentials-provider]:https://jenkinsci.github.io/kubernetes-credentials-provider-plugin/

View File

@ -0,0 +1,86 @@
---
title: "Configure backup and restore"
linkTitle: "Configure backup and restore"
weight: 10
date: 2020-04-13
description: >
Prevent loss of job history
---
Backup and restore is done by a container sidecar.
### PVC
#### Create PVC
Save to the file named pvc.yaml:
```yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: <pvc_name>
namespace: <namespace>
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 500Gi
```
Run the following command:
```bash
$ kubectl -n <namespace> create -f pvc.yaml
```
#### Configure Jenkins CR
```yaml
apiVersion: jenkins.io/v1alpha2
kind: Jenkins
metadata:
name: <cr_name>
namespace: <namespace>
spec:
master:
securityContext:
runAsUser: 1000
fsGroup: 1000
containers:
- name: jenkins-master
image: jenkins/jenkins:lts
- name: backup # container responsible for the backup and restore
env:
- name: BACKUP_DIR
value: /backup
- name: JENKINS_HOME
value: /jenkins-home
- name: BACKUP_COUNT
value: "3" # keep only the 2 most recent backups
image: virtuslab/jenkins-operator-backup-pvc:v0.0.8 # look at backup/pvc directory
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /jenkins-home # Jenkins home volume
name: jenkins-home
- mountPath: /backup # backup volume
name: backup
volumes:
- name: backup # PVC volume where backups will be stored
persistentVolumeClaim:
claimName: <pvc_name>
backup:
containerName: backup # container name is responsible for backup
action:
exec:
command:
- /home/user/bin/backup.sh # this command is invoked on "backup" container to make backup, for example /home/user/bin/backup.sh <backup_number>, <backup_number> is passed by operator
interval: 30 # how often make backup in seconds
makeBackupBeforePodDeletion: true # make a backup before pod deletion
restore:
containerName: backup # container name is responsible for restore backup
action:
exec:
command:
- /home/user/bin/restore.sh # this command is invoked on "backup" container to make restore backup, for example /home/user/bin/restore.sh <backup_number>, <backup_number> is passed by operator
#recoveryOnce: <backup_number> # if want to restore specific backup configure this field and then Jenkins will be restarted and desired backup will be restored
```

View File

@ -0,0 +1,184 @@
---
title: "Custom Backup and Restore Providers"
linkTitle: "Custom Backup and Restore Providers"
weight: 10
date: 2020-04-13
description: >
Custom backup and restore provider
---
With enough effort one can create a custom backup and restore provider
for the Jenkins Operator.
## Requirements
Two commands (e.g. scripts) are required:
- a backup command, e.g. `backup.sh` that takes one argument, a **backup number**
- a restore command, e.g. `backup.sh` that takes one argument, a **backup number**
Both scripts need to return an exit code of `0` on success and `1` or greater for failure.
One of those scripts (or the entry point of the container) needs to be responsible
for backup cleanup or rotation if required, or an external system.
## How it works
The mechanism relies on basic Kubernetes and UNIX functionalities.
The backup (and restore) container runs as a sidecar in the same
Kubernetes pod as the Jenkins master.
Name of the backup and restore containers can be set as necessary using
`spec.backup.containerName` and `spec.restore.containerName`.
In most cases it will be the same container, but we allow for less common use cases.
The operator will call a backup or restore commands inside a sidecar container when necessary:
- backup command (defined in `spec.backup.action.exec.command`)
will be called every `N` seconds configurable in: `spec.backup.interval`
and on pod shutdown (if enabled in `spec.backup.makeBackupBeforePodDeletion`)
with an integer representing the current backup number as first and only argument
- restore command (defined in `spec.restore.action.exec.command`)
will be called at Jenkins startup
with an integer representing the backup number to restore as first and only argument
(can be overridden using `spec.restore.recoveryOnce`)
## Example AWS S3 backup using the CLI
This example shows abbreviated version of a simple AWS S3 backup implementation
using: `aws-cli`, `bash` and `kube2iam`.
In addition to your normal `Jenkins` `CustomResource` some additional settings
for backup and restore are required, e.g.:
```yaml
kind: Jenkins
apiVersion: jenkins.io/v1alpha1
metadata:
name: example
namespace: jenkins
spec:
master:
masterAnnotations:
iam.amazonaws.com/role: "my-example-backup-role" # tell kube2iam where the AWS IAM role is
containers:
- name: jenkins-master
...
- name: backup # container responsible for backup and restore
image: quay.io/virtuslab/aws-cli:1.16.263-2
workingDir: /home/user/bin/
command: # our container entry point
- sleep
- infinity
env:
- name: BACKUP_BUCKET
value: my-example-bucket # the S3 bucket name to use
- name: BACKUP_PATH
value: my-backup-path # the S3 bucket path prefix to use
- name: JENKINS_HOME
value: /jenkins-home # the path to mount jenkins home dir in the backup container
volumeMounts:
- mountPath: /jenkins-home # Jenkins home volume
name: jenkins-home
- mountPath: /home/user/bin/backup.sh
name: backup-scripts
subPath: backup.sh
readOnly: true
- mountPath: /home/user/bin/restore.sh
name: backup-scripts
subPath: restore.sh
readOnly: true
volumes:
- name: backup-scripts
configMap:
defaultMode: 0754
name: jenkins-operator-backup-s3
securityContext: # make sure both containers use the same UID and GUID
runAsUser: 1000
fsGroup: 1000
...
backup:
containerName: backup # container name responsible for backup
interval: 3600 # how often make a backup in seconds
makeBackupBeforePodDeletion: true # trigger backup just before deleting the pod
action:
exec:
command:
# this command is invoked on "backup" container to create a backup,
# <backup_number> is passed by operator,
# for example /home/user/bin/backup.sh <backup_number>
- /home/user/bin/backup.sh
restore:
containerName: backup # container name is responsible for restore backup
action:
exec:
command:
# this command is invoked on "backup" container to restore a backup,
# <backup_number> is passed by operator
# for example /home/user/bin/restore.sh <backup_number>
- /home/user/bin/restore.sh
# recoveryOnce: <backup_number> # if want to restore specific backup configure this field and then Jenkins will be restarted and desired backup will be restored
```
The actual backup and restore scripts will be provided in a `ConfigMap`:
```yaml
kind: ConfigMap
apiVersion: v1
metadata:
name: jenkins-operator-backup-s3
namespace: jenkins
labels:
app: jenkins-operator
data:
backup.sh: |-
#!/bin/bash -xeu
[[ ! $# -eq 1 ]] && echo "Usage: $0 backup_number" && exit 1;
[[ -z "${BACKUP_BUCKET}" ]] && echo "Required 'BACKUP_BUCKET' env not set" && exit 1;
[[ -z "${BACKUP_PATH}" ]] && echo "Required 'BACKUP_PATH' env not set" && exit 1;
[[ -z "${JENKINS_HOME}" ]] && echo "Required 'JENKINS_HOME' env not set" && exit 1;
backup_number=$1
echo "Running backup #${backup_number}"
BACKUP_TMP_DIR=$(mktemp -d)
tar -C ${JENKINS_HOME} -czf "${BACKUP_TMP_DIR}/${backup_number}.tar.gz" --exclude jobs/*/workspace* -c jobs && \
aws s3 cp ${BACKUP_TMP_DIR}/${backup_number}.tar.gz s3://${BACKUP_BUCKET}/${BACKUP_PATH}/${backup_number}.tar.gz
echo Done
restore.sh: |-
#!/bin/bash -xeu
[[ ! $# -eq 1 ]] && echo "Usage: $0 backup_number" && exit 1
[[ -z "${BACKUP_BUCKET}" ]] && echo "Required 'BACKUP_BUCKET' env not set" && exit 1;
[[ -z "${BACKUP_PATH}" ]] && echo "Required 'BACKUP_PATH' env not set" && exit 1;
[[ -z "${JENKINS_HOME}" ]] && echo "Required 'JENKINS_HOME' env not set" && exit 1;
backup_number=$1
echo "Running restore #${backup_number}"
BACKUP_TMP_DIR=$(mktemp -d)
aws s3 cp s3://${BACKUP_BUCKET}/${BACKUP_PATH}/${backup_number}.tar.gz ${BACKUP_TMP_DIR}/${backup_number}.tar.gz
tar -C ${JENKINS_HOME} -zxf "${BACKUP_TMP_DIR}/${backup_number}.tar.gz"
echo Done
```
In our example we will use S3 bucket lifecycle policy to keep
the number of backups under control, e.g. Cloud Formation fragment:
```yaml
Type: AWS::S3::Bucket
Properties:
BucketName: my-example-bucket
...
LifecycleConfiguration:
Rules:
- Id: BackupCleanup
Status: Enabled
Prefix: my-backup-path
ExpirationInDays: 7
NoncurrentVersionExpirationInDays: 14
AbortIncompleteMultipartUpload:
DaysAfterInitiation: 3
```

View File

@ -0,0 +1,202 @@
---
title: "Customization"
linkTitle: "Customization"
weight: 3
date: 2020-04-13
description: >
How to customize Jenkins
---
## How to customize Jenkins
Jenkins can be customized with plugins.
Plugin's configuration is applied as groovy scripts or the [configuration as code plugin](https://github.com/jenkinsci/configuration-as-code-plugin).
Any plugin working for Jenkins can be installed by the Jenkins Operator.
Pre-installed plugins:
* configuration-as-code v1.38
* git v4.2.2
* job-dsl v1.77
* kubernetes-credentials-provider v0.13
* kubernetes v1.25.2
* workflow-aggregator v2.6
* workflow-job v2.38
Rest of the plugins can be found in [plugins repository](https://plugins.jenkins.io/).
#### Install plugins
Edit Custom Resource under `spec.master.plugins`:
```
apiVersion: jenkins.io/v1alpha2
kind: Jenkins
metadata:
name: example
spec:
master:
plugins:
- name: simple-theme-plugin
version: 0.5.1
```
Under `spec.master.basePlugins` you can find plugins for a valid **Jenkins Operator**:
```yaml
apiVersion: jenkins.io/v1alpha2
kind: Jenkins
metadata:
name: example
spec:
master:
basePlugins:
- name: kubernetes
version: 1.18.3
- name: workflow-job
version: "2.34"
- name: workflow-aggregator
version: "2.6"
- name: git
version: 3.12.0
- name: job-dsl
version: "1.76"
- name: configuration-as-code
version: "1.29"
- name: kubernetes-credentials-provider
version: 0.12.1
```
You can change their versions.
The **Jenkins Operator** will then automatically install plugins after the Jenkins master pod restart.
#### Apply plugin's config
By using a [ConfigMap](https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/) you can create your own **Jenkins** customized configuration.
Then you must reference the **`ConfigMap`** in the **Jenkins** pod customization file in `spec.groovyScripts` or `spec.configurationAsCode`
Create a **`ConfigMap`** with specific name (eg. `jenkins-operator-user-configuration`). Then, modify the **Jenkins** manifest:
```yaml
apiVersion: jenkins.io/v1alpha2
kind: Jenkins
metadata:
name: example
spec:
configurationAsCode:
configurations:
- name: jenkins-operator-user-configuration
groovyScripts:
configurations:
- name: jenkins-operator-user-configuration
```
Here is an example of `jenkins-operator-user-configuration`:
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: jenkins-operator-user-configuration
data:
1-configure-theme.groovy: |
import jenkins.*
import jenkins.model.*
import hudson.*
import hudson.model.*
import org.jenkinsci.plugins.simpletheme.ThemeElement
import org.jenkinsci.plugins.simpletheme.CssTextThemeElement
import org.jenkinsci.plugins.simpletheme.CssUrlThemeElement
Jenkins jenkins = Jenkins.getInstance()
def decorator = Jenkins.instance.getDescriptorByType(org.codefirst.SimpleThemeDecorator.class)
List<ThemeElement> configElements = new ArrayList<>();
configElements.add(new CssTextThemeElement("DEFAULT"));
configElements.add(new CssUrlThemeElement("https://cdn.rawgit.com/afonsof/jenkins-material-theme/gh-pages/dist/material-light-green.css"));
decorator.setElements(configElements);
decorator.save();
jenkins.save()
1-system-message.yaml: |
jenkins:
systemMessage: "Configuration as Code integration works!!!"
```
* `*.groovy` is Groovy script configuration
* `*.yaml is` configuration as code
If you want to correct your configuration you can edit it while the **Jenkins Operator** is running.
Jenkins will reconcile and apply the new configuration.
## How to use secrets from a Groovy scripts
If you configured `spec.groovyScripts.secret.name`, then this secret is available to use from map Groovy scripts.
The secrets are loaded to `secrets` map.
Create a [secret](https://kubernetes.io/docs/concepts/configuration/secret/) with for example the name `jenkins-conf-secrets`.
```yaml
kind: Secret
apiVersion: v1
type: Opaque
metadata:
name: jenkins-conf-secrets
namespace: default
data:
SYSTEM_MESSAGE: SGVsbG8gd29ybGQ=
```
Then modify the **Jenkins** pod manifest by changing `spec.groovyScripts.secret.name` to `jenkins-conf-secrets`.
```yaml
apiVersion: jenkins.io/v1alpha2
kind: Jenkins
metadata:
name: example
spec:
configurationAsCode:
configurations:
- name: jenkins-operator-user-configuration
secret:
name: jenkins-conf-secrets
groovyScripts:
configurations:
- name: jenkins-operator-user-configuration
secret:
name: jenkins-conf-secrets
```
Now you can test that the secret is mounted by applying this `ConfigMap` for Groovy script:
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: jenkins-operator-user-configuration
data:
1-system-message.groovy: |
import jenkins.*
import jenkins.model.*
import hudson.*
import hudson.model.*
Jenkins jenkins = Jenkins.getInstance()
jenkins.setSystemMessage(secrets["SYSTEM_MESSAGE"])
jenkins.save()
```
Or by applying this configuration as code:
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: jenkins-operator-user-configuration
data:
1-system-message.yaml: |
jenkins:
systemMessage: ${SYSTEM_MESSAGE}
```
After this, you should see the `Hello world` system message from the **Jenkins** homepage.

View File

@ -0,0 +1,90 @@
---
title: "Deploy Jenkins"
linkTitle: "Deploy Jenkins"
weight: 1
date: 2020-04-13
description: >
Deploy production ready Jenkins Operator manifest
---
Once Jenkins Operator is up and running let's deploy actual Jenkins instance.
Create manifest e.g. **`jenkins_instance.yaml`** with following data and save it on drive.
```bash
apiVersion: jenkins.io/v1alpha2
kind: Jenkins
metadata:
name: example
spec:
master:
containers:
- name: jenkins-master
image: jenkins/jenkins:lts
imagePullPolicy: Always
livenessProbe:
failureThreshold: 12
httpGet:
path: /login
port: http
scheme: HTTP
initialDelaySeconds: 80
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 5
readinessProbe:
failureThreshold: 3
httpGet:
path: /login
port: http
scheme: HTTP
initialDelaySeconds: 30
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
resources:
limits:
cpu: 1500m
memory: 3Gi
requests:
cpu: "1"
memory: 500Mi
seedJobs:
- id: jenkins-operator
targets: "cicd/jobs/*.jenkins"
description: "Jenkins Operator repository"
repositoryBranch: master
repositoryUrl: https://github.com/jenkinsci/kubernetes-operator.git
```
Deploy a Jenkins to Kubernetes:
```bash
kubectl create -f jenkins_instance.yaml
```
Watch the Jenkins instance being created:
```bash
kubectl get pods -w
```
Get the Jenkins credentials:
```bash
kubectl get secret jenkins-operator-credentials-<cr_name> -o 'jsonpath={.data.user}' | base64 -d
kubectl get secret jenkins-operator-credentials-<cr_name> -o 'jsonpath={.data.password}' | base64 -d
```
Connect to the Jenkins instance (minikube):
```bash
minikube service jenkins-operator-http-<cr_name> --url
```
Connect to the Jenkins instance (actual Kubernetes cluster):
```bash
kubectl port-forward jenkins-<cr_name> 8080:8080
```
Then open browser with address `http://localhost:8080`.
![jenkins](/kubernetes-operator/img/jenkins.png)

View File

@ -0,0 +1,42 @@
---
title: "Diagnostics"
linkTitle: "Diagnostics"
weight: 40
date: 2020-04-13
description: >
How to deal with Jenkins Operator problems
---
Turn on debug in **Jenkins Operator** deployment:
```bash
sed -i 's|\(args:\).*|\1\ ["--debug"\]|' deploy/operator.yaml
kubectl apply -f deploy/operator.yaml
```
Watch Kubernetes events:
```bash
kubectl get events --sort-by='{.lastTimestamp}'
```
Verify Jenkins master logs:
```bash
kubectl logs -f jenkins-<cr_name>
```
Verify the `jenkins-operator` logs:
```bash
kubectl logs deployment/jenkins-operator
```
## Troubleshooting
Delete the Jenkins master pod and wait for the new one to come up:
```bash
kubectl delete pod jenkins-<cr_name>
```

View File

@ -0,0 +1,114 @@
---
title: "Notifications"
linkTitle: "Notifications"
weight: 10
date: 2020-04-13
description: >
How to setup operator notifications.
---
## Slack
Please follow [this](https://api.slack.com/incoming-webhooks) instructions to get web hook URL.
Create web hook secret with name `jenkins-operator-notification-data`. Contains key `url` with provided web hook URL.
```bash
$ kubectl create secret generic jenkins-operator-notification-data --from-literal=url=<webhook_url>
```
Example configuration for Slack:
```
kind: Jenkins
spec:
master:
notifications:
- level: info
verbose: true
name: <name>
slack:
webHookURLSecretKeySelector:
secret:
name: <secret_name>
key: <key>
```
## Microsoft Teams
Please follow [this](https://docs.microsoft.com/en-gb/outlook/actionable-messages/send-via-connectors) instructions to get web hook URL.
Example configuration for Microsoft Teams:
```
kind: Jenkins
spec:
master:
notifications:
- level: info
verbose: true
name: <name>
teams:
webHookURLSecretKeySelector:
secret:
name: <secret_name>
key: <key>
```
## Mailgun
Example configuration for Mailgun:
```
kind: Jenkins
spec:
master:
notifications:
- level: info
verbose: true
name: <name>
mailgun:
domain: <domain>
apiKeySecretKeySelector:
secret:
name: <secret_name>
key: <key>
recipient: <your_email>
from: <mailgun_email>
```
## Debug options
As you see there is two debugging options:
* `level` (warning/info) - Set level of messages to send.
* `verbose` - Print stacktrace and additional error messages
## Multiple providers
You can use multiple providers to send notification to another communication channels at the same time.
For example you will send notifications to Slack and Teams.
```
kind: Jenkins
spec:
master:
notifications:
- level: info
verbose: true
name: nslack
slack:
webHookURLSecretKeySelector:
secret:
name: <secret_name>
key: <key>
- level: info
verbose: true
name: nteams
teams:
webHookURLSecretKeySelector:
secret:
name: <secret_name>
key: <key>
```

View File

@ -0,0 +1,104 @@
---
title: "OpenShift"
linkTitle: "OpenShift"
weight: 20
date: 2020-04-29
description: >
Additional configuration for OpenShift
---
## SecurityContext
OpenShift enforces Security Constraints Context (scc) when deploying an image.
By default, container images run in restricted scc which prevents from setting
a fixed user id to run with. You need to have ensure that you do not provide a
securityContext with a runAsUser and that your image does not use a hardcoded user.
```yaml
securityContext: {}
```
## OpenShift Jenkins image
OpenShift provides a pre-configured Jenkins image containing 3 openshift plugins for
jenkins (openshift-login-plugin, openshift-sync-plugin and openshift-client-plugin)
which allows better jenkins integration with kubernetes and OpenShift.
The OpenShift Jenkins image requires additional configuration to be fully enabled.
### Sample OpenShift CR
The following Custom Resource can be used to create a Jenkins instance using the
OpenShift Jenkins image and sets values for:
- `image: 'quay.io/openshift/origin-jenkins:latest' : This is the OpenShift Jenkins image.
- serviceAccount: to allow oauth authentication to work, the service account needs
a specific annotation pointing to the route exposing the jenkins service. Here,
the route is named `jenkins-route`
- `OPENSHIFT_ENABLE_OAUTH` environment variable for the master container is set to true.
Here is a complete Jenkins CR allowing the deployment of the Jenkins OpenShift image.
```yaml
apiVersion: jenkins.io/v1alpha2
kind: Jenkins
metadata:
annotations:
jenkins.io/openshift-mode: 'true'
name: jenkins
spec:
serviceAccount:
annotations:
serviceaccounts.openshift.io/oauth-redirectreference.jenkins: '{"kind":"OAuthRedirectReference","apiVersion":"v1","reference":{"kind":"Route","name":"jenkins-route"}}'
master:
containers:
- name: jenkins-master
image: 'quay.io/openshift/origin-jenkins:latest'
command:
- /usr/bin/go-init
- '-main'
- /usr/libexec/s2i/run
env:
- name: OPENSHIFT_ENABLE_OAUTH
value: 'true'
- name: OPENSHIFT_ENABLE_REDIRECT_PROMPT
value: 'true'
- name: DISABLE_ADMINISTRATIVE_MONITORS
value: 'false'
- name: KUBERNETES_MASTER
value: 'https://kubernetes.default:443'
- name: KUBERNETES_TRUST_CERTIFICATES
value: 'true'
- name: JENKINS_SERVICE_NAME
value: jenkins-operator-http-jenkins
- name: JNLP_SERVICE_NAME
value: jenkins-operator-slave-jenkins
- name: JENKINS_UC_INSECURE
value: 'false'
- name: JENKINS_HOME
value: /var/lib/jenkins
- name: JAVA_OPTS
value: >-
-XX:+UnlockExperimentalVMOptions -XX:+UnlockExperimentalVMOptions
-XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1
-Djenkins.install.runSetupWizard=false -Djava.awt.headless=true
imagePullPolicy: Always
service:
port: 8080
type: ClusterIP
slaveService:
port: 50000
type: ClusterIP
```
### OpenShift OAuth integration
The creation of a Route is required for the integraiton of Jenkins with
OpenShift oauth authentication. By default, the jenkins http service is named
`jenkins-operator-http-${jenkins-cr-name}`
```bash
oc create route edge jenkins-route --service=jenkins-operator-http-jenkins
```
Note: the route name (jenkins-route) must match the pointed route on the serviceaccount annotation.
After the creation of the Route. It can be used to navigate to the Jenkins Login Page and login with your Openshift Credentials.

File diff suppressed because it is too large Load Diff