Jenkins
Jenkins is an automation server. It is geared towards building and deploying software projects. The key theme is CI / CD: continuous integration and continuous delivery.
Jenkins is free and open source. This means that it is not only a lower cost solution but it is flexible and gives you options. It is incredibly popular and can pretty much be thought of as industry standard.
Jenkins is servlet based and runs in servlet containers like JBoss and Tomcat. It can also be run as a standalone application. You can install it practically anywhere you want from huge servers to a tiny laptop. It runs on Linux, OSX, BSD, Solaris, and even Windows. You can download it as a platform specific package or just grab the war file and run it directly. It also runs on Docker which is an excellent way of getting it up and running fast.
One issue I’ve run into is that it can be a bit picky about which Java version you are using. So long as you have the right version of Java, you can run it on just about whatever platform you want though.
Jenkins supports source control such as Git, CVS, and more.
Jenkins Install and Setup
Here we show an example of how we install and setup Jenkins on Ubuntu Linux ( 18.04.3 ).
Install and Run Jenkins
First install Java:
sudo apt install openjdk-8-jre-headless
Next, pull down the latest Jenkins war file.
wget http://mirrors.jenkins.io/war/latest/jenkins.war
Finally, launch the war file:
java -jar jenkins.war
On first startup Jenkins creates an admin user and initial password. The initial password will be output on the console. You can also find it here:
/home/user1/.jenkins/secrets/initialAdminPassword
You can reach the Jenkins web UI by going to port 8080 on your server. If you are connecting to Jenkins on the same system that it is running on ( ex: your laptop ) you can just use the IP for localhost: 127.0.0.1. So you would go to the URL http://127.0.0.1:8080/ using your web browser.
Initial Setup ( From The GUI )
When you initially connect to the Web UI you will need to go through the initial setup.
Go here: http://127.0.0.1:8080/
Unlock Jenkins - Password
Paste in the initial password from the installation steps above. You can find it here:
/home/user1/.jenkins/secrets/initialAdminPassword
Customize Jenkins
The first decision you will need to make is on the customize Jenkins screen. Here you have two options:
- Install suggested plugins
- Select plugins to install
I just went with “Install suggested plugins” but you can customize them if you want.
Create First Admin User
Next you will want to setup an admin user. I just used the name ‘admin’ because I wasn’t feeling creative and because I know I won’t forget it. You might want to pick something less standard for security purposes or just because you like using a different user name. You might want to avoid calling your admin user something like ‘admin’ or ‘root’. Pick a strong password.
Instance Configuration
On this final configuration screen you will have the option to change the Jenkins URL if you want. If you have a good reason to do this, go right ahead. Personally I left the defaults in place for the time being. When running a more elaborate setup with multiple instances or when colocating with other software, it might be good to customize this.
All Set
Click on the button “Start using Jenkins”.
That’s it. You’re all set. You should now be logged into Jenkins on the welcome screen and ready to start creating jobs. From here you can do whatever you want. You can start poking around the interface and getting familiar with things or get down to work right away. You can further customize things or start creating jobs.
Next Steps:
First, we will want to get some test jobs working. Next, we are probably going to want to set Jenkins up to run as a service. You don’t want to just leave it running from a terminal…. or maybe you do if you are just running on your laptop for testing and don’t care. If you’re running this on a centralized server you will almost definitely want to run it as a service that runs in the background and starts automatically on boot.
Video Instruction
If you want more information, here is a video someone else put together:
Kubernetes
For reference, don’t need this:
git clone https://github.com/scriptcamp/kubernetes-jenkins # for reference
Create namespace:
kubectl create namespace devops-tools
Create service account:
serviceAccount.yaml
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: jenkins-admin
rules:
- apiGroups: [""]
resources: ["*"]
verbs: ["*"]
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: jenkins-admin
namespace: devops-tools
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: jenkins-admin
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: jenkins-admin
subjects:
- kind: ServiceAccount
name: jenkins-admin
namespace: devops-tools
Apply it:
kubectl apply -f serviceAccount.yaml
Create volume:
volume.yaml
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: jenkins-pv-volume
labels:
type: local
spec:
storageClassName: local-storage
claimRef:
name: jenkins-pv-claim
namespace: devops-tools
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
local:
path: /mnt
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- worker-node01
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: jenkins-pv-claim
namespace: devops-tools
spec:
storageClassName: local-storage
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 3Gi
- Replace ‘worker-node01’ with any one of your cluster worker nodes hostname.
- creates volume with local storage class
kubectl create -f volume.yaml
Create deployment:
deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: jenkins
namespace: devops-tools
spec:
replicas: 1
selector:
matchLabels:
app: jenkins-server
template:
metadata:
labels:
app: jenkins-server
spec:
securityContext:
fsGroup: 1000
runAsUser: 1000
serviceAccountName: jenkins-admin
containers:
- name: jenkins
image: jenkins/jenkins:lts
resources:
limits:
memory: "2Gi"
cpu: "1000m"
requests:
memory: "500Mi"
cpu: "500m"
ports:
- name: httpport
containerPort: 8080
- name: jnlpport
containerPort: 50000
livenessProbe:
httpGet:
path: "/login"
port: 8080
initialDelaySeconds: 90
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 5
readinessProbe:
httpGet:
path: "/login"
port: 8080
initialDelaySeconds: 60
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
volumeMounts:
- name: jenkins-data
mountPath: /var/jenkins_home
volumes:
- name: jenkins-data
persistentVolumeClaim:
claimName: jenkins-pv-claim
Apply it:
kubectl apply -f deployment.yaml
Show deployments:
kubectl get deployments -n devops-tools
Create service:
service.yaml
apiVersion: v1
kind: Service
metadata:
name: jenkins-service
namespace: devops-tools
annotations:
prometheus.io/scrape: 'true'
prometheus.io/path: /
prometheus.io/port: '8080'
spec:
selector:
app: jenkins-server
type: NodePort
ports:
- port: 8080
targetPort: 8080
nodePort: 32000
Apply it:
kubectl apply -f service.yaml
Access it here: http://
Get password ( at end of logs ):
kubectl get pods --namespace=devops-tools
kubectl logs jenkins-deployment-2539456353-j00w5 --namespace=devops-tools
Usage
These exist:
- script console
- cli
java -jar jenkins-cli.jar -s http://192.168.3.228:32000/ help
For Jenkins running on Kubernetes with local storage:
- Dir used by build: /var/jenkins_home/workspace/Java Test 1
- Mounted on node here: /mnt/workspace/Java\ Test\ 1
- Basically /var/jenkins maps to /mnt
Setup:
- regular build
- pipeline
- agent ( instead of running on master host )
- java 21 ( not java 8 )
- need non-root docker ( and restart agent )
- Creds:
- ssh key for agent ( needs to be 4096 !!!!!!!!!!!!!!!!!!! )
- git hub creds ( same user/pass(token) that I normally use to login )
Jenkins Pipeline
Jenkins pipeline to:
- checkout form git
- compile java
- build docker image
- tag the image
- push it to an internal registry
Later it can be pulled and deployed to kubernetes with ArgoCD.
pipeline {
//agent any
agent {label 'node1'}
stages {
stage('Git Checkout') {
steps {
git branch: 'main',
credentialsId: 'a8e06371-8237-4146-b1fa-2fa788c7c35e',
url: 'https://github.com/low-orbit-flux/java-test1.git'
}
}
stage('Build') {
steps {
sh 'javac HelloWorld.java'
}
}
stage('Check') {
steps {
sh 'pwd; ls -l'
}
}
stage('Dockerize') {
steps {
script {
dockerImage = docker.build( "java-test1" )
}
}
}
stage('Tag Image') {
steps {
script {
sh 'docker image tag java-test1 192.168.3.228:30844/java-test1'
}
}
}
stage('Push image') {
steps {
script {
sh 'docker push 192.168.3.228:30844/app1'
}
}
}
}
}