Update website - 0.5.0 release
This commit is contained in:
parent
fe81e5ab3d
commit
9f261169f0
|
|
@ -1,14 +1,14 @@
|
||||||
---
|
---
|
||||||
title: "Latest (v0.4.x)"
|
title: "Latest (v0.5.x)"
|
||||||
linkTitle: "Latest (v0.4.x)"
|
linkTitle: "Latest (v0.5.x)"
|
||||||
weight: 10
|
weight: 10
|
||||||
date: 2020-04-13
|
date: 2021-01-18
|
||||||
description: >
|
description: >
|
||||||
How to work with jenkins-operator latest version
|
How to work with jenkins-operator latest version
|
||||||
---
|
---
|
||||||
|
|
||||||
{{% pageinfo %}}
|
{{% 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 %}}
|
{{% /pageinfo %}}
|
||||||
|
|
||||||
## First Steps
|
## First Steps
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "AKS"
|
title: "AKS"
|
||||||
linkTitle: "AKS"
|
linkTitle: "AKS"
|
||||||
weight: 10
|
weight: 10
|
||||||
date: 2020-04-13
|
date: 2021-01-18
|
||||||
description: >
|
description: >
|
||||||
Additional configuration for Azure Kubernetes Service
|
Additional configuration for Azure Kubernetes Service
|
||||||
---
|
---
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "Configuration"
|
title: "Configuration"
|
||||||
linkTitle: "Configuration"
|
linkTitle: "Configuration"
|
||||||
weight: 2
|
weight: 2
|
||||||
date: 2020-04-13
|
date: 2021-01-18
|
||||||
description: >
|
description: >
|
||||||
How to configure Jenkins with Operator
|
How to configure Jenkins with Operator
|
||||||
---
|
---
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "Configure backup and restore"
|
title: "Configure backup and restore"
|
||||||
linkTitle: "Configure backup and restore"
|
linkTitle: "Configure backup and restore"
|
||||||
weight: 10
|
weight: 10
|
||||||
date: 2020-04-13
|
date: 2021-01-18
|
||||||
description: >
|
description: >
|
||||||
Prevent loss of job history
|
Prevent loss of job history
|
||||||
---
|
---
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "Custom Backup and Restore Providers"
|
title: "Custom Backup and Restore Providers"
|
||||||
linkTitle: "Custom Backup and Restore Providers"
|
linkTitle: "Custom Backup and Restore Providers"
|
||||||
weight: 10
|
weight: 10
|
||||||
date: 2020-04-13
|
date: 2021-01-18
|
||||||
description: >
|
description: >
|
||||||
Custom backup and restore provider
|
Custom backup and restore provider
|
||||||
---
|
---
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "Customization"
|
title: "Customization"
|
||||||
linkTitle: "Customization"
|
linkTitle: "Customization"
|
||||||
weight: 3
|
weight: 3
|
||||||
date: 2020-04-13
|
date: 2021-01-18
|
||||||
description: >
|
description: >
|
||||||
How to customize Jenkins
|
How to customize Jenkins
|
||||||
---
|
---
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "Deploy Jenkins"
|
title: "Deploy Jenkins"
|
||||||
linkTitle: "Deploy Jenkins"
|
linkTitle: "Deploy Jenkins"
|
||||||
weight: 1
|
weight: 1
|
||||||
date: 2020-04-13
|
date: 2021-01-18
|
||||||
description: >
|
description: >
|
||||||
Deploy production ready Jenkins Operator manifest
|
Deploy production ready Jenkins Operator manifest
|
||||||
---
|
---
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "Diagnostics"
|
title: "Diagnostics"
|
||||||
linkTitle: "Diagnostics"
|
linkTitle: "Diagnostics"
|
||||||
weight: 40
|
weight: 40
|
||||||
date: 2020-04-13
|
date: 2021-01-18
|
||||||
description: >
|
description: >
|
||||||
How to deal with Jenkins Operator problems
|
How to deal with Jenkins Operator problems
|
||||||
---
|
---
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "Notifications"
|
title: "Notifications"
|
||||||
linkTitle: "Notifications"
|
linkTitle: "Notifications"
|
||||||
weight: 10
|
weight: 10
|
||||||
date: 2020-04-13
|
date: 2021-01-18
|
||||||
description: >
|
description: >
|
||||||
How to setup operator notifications.
|
How to setup operator notifications.
|
||||||
---
|
---
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "Schema"
|
title: "Schema"
|
||||||
linkTitle: "Schema"
|
linkTitle: "Schema"
|
||||||
weight: 40
|
weight: 40
|
||||||
date: 2020-04-13
|
date: 2021-01-18
|
||||||
description: >
|
description: >
|
||||||
API Schema definitions for Jenkins CRD
|
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
|
<p>BasePlugins contains plugins required by operator
|
||||||
Defaults to :
|
Defaults to :
|
||||||
- name: kubernetes
|
- name: kubernetes
|
||||||
version: 1.25.2
|
version: “1.28.6”
|
||||||
- name: workflow-job
|
- name: workflow-job
|
||||||
version: “2.39”
|
version: “2.40”
|
||||||
- name: workflow-aggregator
|
- name: workflow-aggregator
|
||||||
version: “2.6”
|
version: “2.6”
|
||||||
- name: git
|
- name: git
|
||||||
version: 4.2.2
|
version: “4.5.0”
|
||||||
- name: job-dsl
|
- name: job-dsl
|
||||||
version: “1.77”
|
version: “1.77”
|
||||||
- name: configuration-as-code
|
- name: configuration-as-code
|
||||||
version: “1.38”
|
version: “1.46”
|
||||||
- name: kubernetes-credentials-provider
|
- name: kubernetes-credentials-provider
|
||||||
version: 0.13</p>
|
version: “0.15”</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
@ -2040,6 +2040,21 @@ Handler
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<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 “-1” should be
|
||||||
|
returned.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
<code>recoveryOnce</code></br>
|
<code>recoveryOnce</code></br>
|
||||||
<em>
|
<em>
|
||||||
uint64
|
uint64
|
||||||
|
|
@ -2623,5 +2638,5 @@ SecretKeySelector
|
||||||
<hr/>
|
<hr/>
|
||||||
<p><em>
|
<p><em>
|
||||||
Generated with <code>gen-crd-api-reference-docs</code>
|
Generated with <code>gen-crd-api-reference-docs</code>
|
||||||
on git commit <code>1c853e69</code>.
|
on git commit <code>fe81e5a</code>.
|
||||||
</em></p>
|
</em></p>
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
You can verify if your pipelines were successfully configured in the Jenkins Seed Job console output.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
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/
|
||||||
|
|
@ -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
|
||||||
|
```
|
||||||
|
|
@ -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
|
||||||
|
```
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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`.
|
||||||
|
|
||||||
|

|
||||||
|
|
@ -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>
|
||||||
|
```
|
||||||
|
|
@ -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>
|
||||||
|
```
|
||||||
|
|
@ -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
Loading…
Reference in New Issue