This document describes a getting started guide for jenkins-operator and an additional configuration.
- First Steps
- Deploy Jenkins
- Configure Seed Jobs and Pipelines
- Install Plugins
- Configure Backup & Restore
- Debugging
Prepare your Kubernetes cluster and set up access. Once you have running Kubernetes cluster you can focus on installing jenkins-operator according to the Installation guide.
Once jenkins-operator is up and running let's deploy actual Jenkins instance. Let's use example below:
apiVersion: jenkins.io/v1alpha1
kind: Jenkins
metadata:
name: example
spec:
master:
image: jenkins/jenkins
seedJobs:
- id: jenkins-operator
targets: "cicd/jobs/*.jenkins"
description: "Jenkins Operator repository"
repositoryBranch: master
repositoryUrl: https://github.com/jenkinsci/kubernetes-operator.git
Watch Jenkins instance being created:
kubectl get pods -w
Get Jenkins credentials:
kubectl get secret jenkins-operator-credentials-example -o 'jsonpath={.data.user}' | base64 -d
kubectl get secret jenkins-operator-credentials-example -o 'jsonpath={.data.password}' | base64 -d
Connect to Jenkins (minikube):
minikube service jenkins-operator-example --url
Pick up the first URL.
Connect to Jenkins (actual Kubernetes cluster):
kubectl describe svc jenkins-operator-example
kubectl port-forward jenkins-operator-example 8080:8080
Then open browser with address http://localhost:8080.
Jenkins operator uses job-dsl and ssh-credentials plugins for configuring jobs and deploy keys.
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 it's 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/jobs/build.jenkins it's 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/jnlp-slave:alpine'),
containerTemplate(name: 'go', image: 'golang:1-alpine', command: 'cat', ttyEnabled: true),
]) {
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('Build') {
container('go') {
sh 'make build'
}
}
}
}
}
Jenkins Seed Jobs are configured using Jenkins.spec.seedJobs
section from your custom resource manifest:
apiVersion: jenkins.io/v1alpha1
kind: Jenkins
metadata:
name: example
spec:
master:
image: jenkins/jenkins:lts
seedJobs:
- id: jenkins-operator
targets: "cicd/jobs/*.jenkins"
description: "Jenkins Operator repository"
repositoryBranch: master
repositoryUrl: https://github.com/jenkinsci/kubernetes-operator.git
If your GitHub repository is private you have to configure corresponding privateKey and Kubernetes Secret:
apiVersion: jenkins.io/v1alpha1
kind: Jenkins
metadata:
name: example
spec:
master:
image: jenkins/jenkins:lts
seedJobs:
- id: jenkins-operator
targets: "cicd/jobs/*.jenkins"
description: "Jenkins Operator repository"
repositoryBranch: master
repositoryUrl: git@github.com:jenkinsci/kubernetes-operator.git
privateKey:
secretKeyRef:
name: deploy-keys
key: jenkins-operator
And Kubernetes Secret:
apiVersion: v1
kind: Secret
metadata:
name: deploy-keys
data:
jenkins-operator-e2e: |
-----BEGIN RSA PRIVATE KEY-----
MIIJKAIBAAKCAgEAxxDpleJjMCN5nusfW/AtBAZhx8UVVlhhhIKXvQ+dFODQIdzO
oDXybs1zVHWOj31zqbbJnsfsVZ9Uf3p9k6xpJ3WFY9b85WasqTDN1xmSd6swD4N8
...
jenkins-operator will automatically discover and configure all seed jobs.
You can verify if deploy keys were successfully configured in Jenkins Credentials tab.
You can verify if your pipelines were successfully configured in Jenkins Seed Job console output.
Jenkins can be customized using groovy scripts or configuration as code plugin. All custom configuration is stored in the jenkins-operator-user-configuration-example ConfigMap which is automatically created by jenkins-operator.
kubectl get configmap jenkins-operator-user-configuration-example -o yaml
apiVersion: v1
data:
1-configure-theme.groovy: |2
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()
kind: ConfigMap
metadata:
labels:
app: jenkins-operator
jenkins-cr: example
watch: "true"
name: jenkins-operator-user-configuration-example
namespace: default
When jenkins-operator-user-configuration-example ConfigMap is updated Jenkins automatically runs the jenkins-operator-user-configuration Jenkins Job which executes all scripts.
Edit CR under spec.master.plugins
:
apiVersion: jenkins.io/v1alpha1
kind: Jenkins
metadata:
name: example
spec:
master:
image: jenkins/jenkins:lts
plugins:
configuration-as-code:1.4:
- configuration-as-code-support:1.4
Then jenkins-operator will automatically install plugins after Jenkins master pod restart.
To install a plugin please add 2-install-slack-plugin.groovy script to the jenkins-operator-user-configuration-example ConfigMap:
apiVersion: v1
data:
1-configure-theme.groovy: |2
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()
2-install-slack-plugin.groovy: |2
import jenkins.model.*
import java.util.logging.Level
import java.util.logging.Logger
def instance = Jenkins.getInstance()
def plugins = instance.getPluginManager()
def updateCenter = instance.getUpdateCenter()
def hasInstalledPlugins = false
Logger logger = Logger.getLogger('jenkins.instance.restart')
if (!plugins.getPlugin("slack")) {
logger.log(Level.INFO, "Installing plugin: slack")
updateCenter.updateAllSites()
def plugin = updateCenter.getPlugin("slack")
def installResult = plugin.deploy()
while (!installResult.isDone()) sleep(10)
hasInstalledPlugins = true
instance.save()
}
if (hasInstalledPlugins) {
logger.log(Level.INFO, "Successfully installed slack plugin, restarting ...")
// Queue a restart of the instance
instance.save()
instance.doSafeRestart(null)
} else {
logger.log(Level.INFO, "No plugins need installing.")
}
Then jenkins-operator will automatically trigger jenkins-operator-user-configuration Jenkins Job again.
Not implemented yet.
Turn on debug in jenkins-operator deployment:
sed -i 's|\(args:\).*|\1\ ["--debug"\]|' deploy/operator.yaml
kubectl apply -f deploy/operator.yaml
Watch Kubernetes events:
kubectl get events --sort-by='{.lastTimestamp}'
Verify Jenkins master logs:
kubectl logs -f jenkins-master-example
Verify jenkins-operator logs:
kubectl logs deployment/jenkins-operator
Delete Jenkins master pod and wait for the new one to come up:
kubectl delete pod jenkins-operator-example