Create a Bitnami Jenkins Instance on AWS EC2 with Terraform
The overview of this article is to show you how to deploy a Bitnami Jenkins instance on an Amazon EC2 instance using Terraform. This article is by no means the best way to perform this task or does it include the best terraform script in the world, but it does explain and show how to get you started with creating an EC2 instance on AWS.
Requirements
AWS Account
AWS CLI
Default profile configured with the AWS CLI
Terraform CLI
Why not create the instance on the AWS EC2 Console.
Yes, you could just create your instance on the AWS EC2 Console, it's how I performed this task for years. But, it's a manual step and in the world of DevOps, we have to try to automate where we can and this should be no different.
Steps
- Configure the AWS provider.
This tells terraform which version of the AWS provider to use and also the AWS region to deploy to. In our case, we are deploying to us-east-1
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.0"
}
}
}
# Configure the AWS Provider
provider "aws" {
region = "us-east-1"
}
2. Configure the input parameters
For this use case, there are 2 input parameters/variables.
jenkinsInstanceName: the name of the EC2 instance that is created on AWS
-
public_key: this is the content from your local public key file. This public key will be created on AWS and you can use the associated private key to log onto your EC2 instance once it is created
variable "jenkinsInstanceName" {
type = string
}variable "public_key" {
type = string
}
3. Setup script variables
Three further variables are set up. These differ from the input variables in that the user will not be prompted to enter these values due to the presence of a default value
instance_type: this is the size of the EC2 instance that is created — it defaults to t3.small to keep costs low
ingress_rules: these are used to set up the security groups. These ports define the allowed ports for accepting incoming traffic
-
egress_rules: these are also used to set up the security groups. These ports define the allowed ports for publishing outgoing traffic on
variable "instance_type" {
type = string
default = "t3.small"
}
variable "ingress_rules" {
type = list(number)
default = [22, 80, 443]
}
variable "egress_rules" {
type = list(number)
default = [0]
}
4. Create the AWS EC2 key
This resource will create the key called jenkins-key using the values that were submitted for the input variable of public_key
resource "aws_key_pair" "jenkins_key" {
key_name = "jenkins-key"
public_key = var.public_key
}
5. Lookup the correct AMI id to use
This step used a terraform datasource. A terraform datasource allows you to look up a value to be used elsewhere in your terraform configuration. In this case, we are using the aws_ami_ids datasource.
The datasource will query for AMI Ids that are owned by the aws-marketplace and start with a value called bitnami-jenkins. It is the Bitnami version of Jenkins that we are going to deploy.
By setting sort_ascending to false, this will return a list of all AMI ids starting with the newest. This value will be used further down in our script when creating the EC2 instance.
But why not just set the AMI id and not bother with this terraform datasource?
That is a good question (as I realise I am talking to myself). By not hardcoding the AMI ID, we can deploy this code on any AWS region. The AWS AMI id is unique per region so if we were to deploy this code on us-east-2, the AWS AMI id would be different.
[**Note: **I set the region in the AWS provider block. This could be circumvented by setting a default AWS region when you set up the AWS CLI.]
data "aws_ami_ids" "jenkins_ami" {
sort_ascending = false
owners = ["aws-marketplace"]
filter {
name = "name"
values = ["bitnami-jenkins*"]
}
}
6. Setup the security groups
This step involves setting up the AWS security groups to define the traffic that is allowed in and out of the Jenkins instance.
For this resource, we use dynamic blocks and the ingress_rules and egress_rules variables specified aboce. The dynamic blocks provide a way to avoid repeated code blocks. Think of it as a for loop for setting up the security groups
resource "aws_security_group" "jenkins_security_group" {
name = "Jenkins Security Group"
description = "Allow traffic to access Jenkins instrance"
dynamic "ingress" {
iterator = port
for_each = var.ingress_rules
content {
from_port = port.value
to_port = port.value
protocol = "TCP"
cidr_blocks = ["0.0.0.0/0"]
}
}
dynamic "egress" {
iterator = port
for_each = var.egress_rules
content {
from_port = port.value
to_port = port.value
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
}
7. Create Bitnami Jenkins EC2 instance
This is the main part of this tutorial and where the action happens.
This is where the Amazon EC2 instance is created with the Bitnami Jenkins image. This a breakdown of the options passed into the aws_instance terraform resource
**ami: **This is the AMI id that is used. data.aws_ami_ids.jenkins_ami refers to the datasource where we looked up the Bitnami Jenkins instance ids. We take the first result ([0]), which will correspond to the newest AMI id for Bitnami Jenkins
**instance_type: **The type of instance to create. This value is obtained from the variable called instance_type which was defined at the top of this article
**security_groups: **The security group to assign to this EC2 instance. The security group was created further up in this article and used the Dynamic blocks
**key_name: **The key to use to allow ssh’ing onto this instance. Again, the public key was accepted as user input and the EC2 key was created based on this
**tags: **The tags to apply to this instance. The Name tag is important and this corresponds to the input parameter that was supplied by the user for jenkinsInstanceName
**depends_on: **This block states that the EC2 instance should not be created until the security group jenkins_security_group was created successfully.
resource "aws_instance" "jenkins_instance" {
ami = data.aws_ami_ids.jenkins_ami.ids[0]
instance_type = var.instance_type
security_groups =[aws_security_group.jenkins_security_group.name]
key_name = aws_key_pair.jenkins_key.key_name
tags = {
Name = var.jenkinsInstanceName
}
depends_on = [aws_security_group.jenkins_security_group]
}
8. Output the instance id
The final step in the process involves outputting the instanceid that was created. This instance id will be outputted when the terraform script completes execution.
output "jenkins_public_ip" {
description = "The ip address for the newly created jenkins instance"
value = aws_instance.jenkins_instance.public_ip
}
9. Create the Resources
Run these commands to create the resources on AWS
terraform init — installs the AWS provider and sets up any modules that were created
terraform apply — will apply the configuration. This command prompts the user to enter the jenkinsInstanceName and the public sshKey. It also prompts the user to approve the creation of the resources
terraform apply -var=”jenkinsInstanceName=[NAME OF INSTANCE]” -var=”public_key=[PUBLIC SSH KEY]” -auto-approve — this command will not prompt the user and will create the necessary resources.
e.g. terraform apply -var=”jenkinsInstanceName=JenkinsServer” -var=”public_key=ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD3F6tyPEFEzV0LX3X8BsXdMsQz1x2cEikKDEY0aIj41qgxMCP/iteneqXSIFZBp5vizPvaoIR3Um9xK7PGoW8giupGn+EPuxIA4cDM4vzOqOkiMPhz5XK0whEjkVzTo4+S0puvDZuwIsdiW9mxhJc7tgBNL0cYlWSYVkz4G/fslNfRPW5mYAM49f4fhtxPb5ok4Q2Lg9dPKVHO/Bgeu5woMc7RY0p1ej6D4CKFE6lymSDJpW0YHX/wqE9+cfEauh7xZcG0q9t2ta6F6fmX0agvpFyZo8aFbXeUBr7osSCJNgvavWbM/06niWrOvYX2xwWdhXmXSrbX8ZbabVohBK41 email@example.com” -auto-approve
10. Obtain the password for Bitnami Jenkins
The 1 manual step involves retrieving the password for the Bitnami Jenkins Instance. We need to SSH onto the instance and retrieve the password from a file. The following commands can be used, just substitute your values for the path to the private ssh key and the EC2 instance public IP address
ssh -i [PATH TO PRIVATE SSH KEY] bitnami@[EC2 INSTANCE PUBLIC IP]
sudo cat /home/bitnami/bitnami_credentials
11. Jenkins is installed
When you navigate to the IP address that was retrieved in step 8 after a few moments, you should see the following screen, and Jenkins is set up. Log in with the username user and the password retrieved in step 10 to begin using Jenkins.
12. Destroy infrastructure
If you are just testing this tutorial out or no longer require the Jenkins instance, run the following command to delete the stack.
Note: If you leave the stack running, you may be charged by AWS. It is up to the user to ensure they have the infrastructure running that they are willing to pay for.
Conclusion
This was a quick tutorial showing you how to set up an instance of Bitnami Jenkins on an Amazon EC2 instance. Again, it is not a definitive guide and should be used to get started. Tweaks and improvements can be made and should be made, but hopefully, this article helps you get started on your journey with Jenkins.
The full terraform configuration file for this tutorial can be found here.
Top comments (0)