Introduction
Probably most folks know both of these products by now, but I've ripped a short intro for both.
And also for a bit of a disclosure. I am by no means an expert in any of this. I run though these out of general curiosity, training, and experience. This should not be followed as a production or development environment guide. This is primarily persona lab setup.
This is going to most likely be a two-parter. This first part will be setting up the require infrastructure. Next will be setting up a Packer template and running a couple of builds.
What I liked about this setup is only Multipass needs setup to launch the instances, but nothing else will need installed or configured on your local system.
HashiCorp Packer
Packer lets you create identical machine images for multiple platforms from a single source configuration. A common use case is creating golden images for organizations to use in cloud infrastructure.
Jenkins
Jenkins is a self-contained, open source automation server which can be used to automate all sorts of tasks related to building, testing, and delivering or deploying software.
Jenkins can be installed through native system packages, Docker, or even run standalone by any machine with a Java Runtime Environment (JRE) installed.
Objectives
I have honestly not used Jenkins that much, but it is a heavily used CI/CD solution. There are many more options out there - some much more modern solutions - Jenkins still is very prevalent and will most likely be here to stay for some time.
For this the objects are:
- Use Multipass to create two instances.
- Jenkins
- Packer
- Set up Jenkins.
- Set up Packer instance as a worker node. Agent will only run for Packer jobs.
Prerequisites
- Knowledge of Jenkins and Packer.
-
Multipass
- I love Multipass for quick Ubuntu instances spun up for testing or as a playground. Wish I would have known and used of it sooner.
Instance Setup
Following sections will walk through the necessary setup.
Using Multipass create two virtual machines.
╰─ multipass version
multipass 1.13.1+mac
multipassd 1.13.1+mac
Launch Jenkins-Server
multipass launch -n jenkins-server
Launch Jenkins-Packer Server
multipass launch -n jenkins-packer
Run multipass list to see instances.
multipass list
Name State IPv4
jenkins-packer Running 192.168.64.9
jenkins-server Running 192.168.64.8
And there we go, we have two instances set up for testing. Multipass is great for this since it can easily spin up and down instances for testing.
These were set up with the default Ubuntu image and configuration settings, there is much more which can be done with Multipass, so check out their documentation.
Jenkins
First step will be to connect to the instance you will run Jenkins on.
multipass shell jenkins-server
Once on the server, I will run through the setup necessary for Jenkins.
Note: I will be using root permissions to simplify steps.
Install Jenkins
For full install instructions, please see the following documentation:
sudo wget -O /usr/share/keyrings/jenkins-keyring.asc \
https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key
echo deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc] \
https://pkg.jenkins.io/debian-stable binary/ | sudo tee \
/etc/apt/sources.list.d/jenkins.list > /dev/null
sudo apt-get update
sudo apt-get install jenkins
Error due to not having Java on the instance, this will get corrected:
Job for jenkins.service failed because the control process exited with error code.
Run the following to setup openjdk:
snap install openjdk
openjdk 21.0.3+3 from John Neffenger (jgneff) installed
Run the following three commands to start up Jenkins :
sudo systemctl enable jenkins
sudo systemctl start jenkins
sudo systemctl status jenkins
Should get a confirmation when running status command.
root@jenkins-server:~# sudo systemctl status jenkins
● jenkins.service - Jenkins Continuous Integration Server
Loaded: loaded (/lib/systemd/system/jenkins.service; enabled; vendor preset: enabled)
Active: active (running) since Wed 2024-02-21 12:31:36 EST; 1s ago
Main PID: 7306 (java)
Tasks: 40 (limit: 1069)
Memory: 367.2M
CPU: 9.747s
CGroup: /system.slice/jenkins.service
└─7306 /usr/bin/java -Djava.awt.headless=true -jar /usr/share/java/jenkins.war --webroot=/var/cache/jenkins/war --httpPort=8080
Jenkins - Firewall
Needing to open up the firewall on this host to ensure communication from my personal laptop and the packer instance.
Installing
apt install firewalld
Once installed, run the following commands:
Note: For testing I'm going to have port 50000 open for the agent to connect back to the Jenkins controller
YOURPORT=8080
PERM="--permanent"
SERV="$PERM --service=jenkins"
firewall-cmd $PERM --new-service=jenkins
firewall-cmd $SERV --set-short="Jenkins ports"
firewall-cmd $SERV --set-description="Jenkins port exceptions"
firewall-cmd $SERV --add-port=$YOURPORT/tcp
firewall-cmd $SERV --add-port=50000/tcp
firewall-cmd $PERM --add-service=jenkins
firewall-cmd --zone=public --add-service=http --permanent
firewall-cmd --reload
Most likely will get some warnings, but to verify, I will connect from my laptop to the host. If done correctly, you should see the following:
For Jenkins configuration, I will run through the defaults, without any major changes.
Once set up is complete, you have a clean slate to work with.
Packer Node
Before jumping onto the instance we set up for Packer, I we need to stay on the Jenkins console for a little bit more.
Node Setup
For more detailed instructions and terminology on distributed nodes, see the documentation.
I'll keep this relatively light for prep.
- Install java.
- Create the following directory /home/packer/agent.
Agent Setup - Jenkins Side
Back in the Jenkins UI, go to manage Jenkins and select nodes:
Create a new node:
Configure node:
continued...
Once configured, select status for the node.
Grab the commands and we will use them when we are back on the node.
One last stop, go back to manage Jenkins and go to security.
In security, make the following updates to enable agent connectivity. Using port 50000
, as it is the static port I opened up on the firewall.
Agent Setup - Packer Instance
Make sure you still have the command you copied earlier, we will use it here.
Change directory to - /home/packer/agent
Run the first command to download the agent. Port 8080 should be open to connect to the Jenkins instance.
root@jenkins-packer:/home/packer/agent# curl -sO http://192.168.64.8:8080/jnlpJars/agent.jar
root@jenkins-packer:/home/packer/agent# ls
agent.jar remoting
Run the second command to start the Jenkins agent. In the info, you should see that port 50000 is in use for the connection. I cleared out most of the message and focusing on the connection information.
root@jenkins-packer:/home/packer/agent# java -jar agent.jar -url http://192.168.64.8:8080/ -secret 322747aa59050708e4af27206812443a9556c25ca45b0456ea70799e20f7db23 -name packer -workDir "/home/packer/agent"
...
INFO: Agent discovery successful
Agent address: 192.168.64.8
Agent port: 50000
Identity: 1f:dc:34:23:1b:e1:84:6f:9c:34:72:c7:d1:5f:c2:74
...
If going back to the UI, you can see the Packer agent is now connected. This agent will drop out when no communication is occurring and will come back up when a job is started.
Note: Agent can be run as a service or in a Docker container. For this setup I'm keeping it simple, but both of those are options.
First Job
Now that we have both a Jenkins node and a Packer node with an agent, we will set up our first job.
Select create a job and select pipeline as the type.
After hitting OK, I am going to do a quick hello world to confirm connectivity with the node. Here is a sample that Jenkins provides. I do update to use the packer agent and node:
pipeline {
agent {
label 'packer'
}
stages {
stage('Hello') {
steps {
echo 'Hello World'
}
}
}
}
From the console output :
Started by user [lykins](http://192.168.64.8:8080/user/lykins)
[Pipeline] Start of Pipeline[](http://192.168.64.8:8080/job/packer/2/console#)
[Pipeline] node[](http://192.168.64.8:8080/job/packer/2/console#)
Running on [packer](http://192.168.64.8:8080/computer/packer/) in /home/packer/agent/workspace/packer
[Pipeline] {[](http://192.168.64.8:8080/job/packer/2/console#)
[Pipeline] stage[](http://192.168.64.8:8080/job/packer/2/console#)
[Pipeline] { (Hello)[](http://192.168.64.8:8080/job/packer/2/console#)
[Pipeline] echo[](http://192.168.64.8:8080/job/packer/2/console#)
Hello World
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS
At this point, we are done with setting up the worker node with the agent. Other options would be running it in docker or as a service, but doing a simple setup for now.
Top comments (0)