Standalone Concourse on vSphere with k3s and Terraform
This terraform scripts allows you to deploy a Concourse virtual machine on your vSphere environment.
Why standalone?
Concourse will be the starting point for most of my deployments, the tool used to automate everything else. For that reason, I wanted to minimize the dependencies and the code needed to deploy it.
Most standalone Concourse deployments I have found are usually done with bosh, but, as usual, I wanted to challenge myself and do something different. It is for this reason that I used k3s.
How does the script work?
The script is a simple terraform workflow which deploys a VM, provides it with a few variables, such as the desired ingress url, and deploys a single k3s node on itself. Thereafter, Concourse gets installed (and configured) with Helm and it gets exposed through an ingress object. At the end, you must write an entry in your DNS server list, which correlates the domain you inputed with the IP address of the Concourse VM.
Next to the terraform files (main, outputs and variables), a concourse-setup-k3s.sh file can be found in the repository. This contains the bash code that the VM will execute at startup. This script installs diverse tools on the VM, such as docker, yq, helm and kubectl. After these dependencies have been installed, the Concourse helm chart gets pulled from "https://concourse-charts.storage.googleapis.com/". Once the chart has been pulled, a few variables are edited:
yq e -i '.concourse.web.bindPort= 80' concourse/values.yaml
yq e -i ".concourse.ingress.enabled = true" concourse/values.yaml && concourse_fqdn="$concourse_fqdn" yq e -i ".concourse.ingress.hosts += [ env(concourse_fqdn) ]" concourse/values.yaml
concourse_fqdn="http://$concourse_fqdn" yq e -i ".concourse.web.externalUrl = env(concourse_fqdn)" concourse/values.yaml
These yq commands enable ingress for Concourse and adds the hostname and url from the variable we assign it. Additionally it changes Concourse’s main bind port to the port 80.
Let’s deploy a standalone Concourse VM
The previous code was shown to help the explanation of the workflow, and does not need to be run explicitely. In order to create your standalone Concourse VM you must first pull the repo and create a terraform.tfvars file in the "concourse" directory, containing the following:
vsphere-user = "" # The username of the vSphere user to be used for this deployment
vsphere-password = "" # The password of the vSphere user to be used for this deployment
vsphere-server = "" # The vSphere server (IP address or FQDN)
vsphere-datacenter = "" # The vSphere Datacenter you will deploy this virtual machine to
vsphere-datastore = "" # The datastore you will deploy this virtual machine to
vsphere-resource_pool = "" # The resource pool to be used by this virtual machine
vsphere-host = "" # The ESXi host you will deploy this virtual machine to
vsphere-network = "" # The network segment to be used by this virtual machine
vsphere-network-cidr = "" # The CIDR of the "vsphere-network"
vm-folder = "" # The name of the vSphere folder which will contain the Concourse virtual machine
concourse-fqdn = "" # The FQDN of your Concourse deployment
concourse-username = "" # The Username of the concourse admin
concourse-password = "" # The Password of the concourse admin
dhcp-concourse = true # Assign IP address via DHCP
Once you created your terraform.tfvars file:
- Open a terminal
- Navigate to the "concourse" directory
- Execute
terraform init
- Execute
terraform apply
When the script finishes, it will output the Concourse FQDN (which you assigned) and the virtual machine’s IP address. Add this to your DNS entries, and then you can access Concourse through HTTP. Use the user test with the password test to authenticate.
Deploy Concourse VM with a static IP
The previous workflow will deploy a Concourse VM with a IP address assigned via DHCP. If, in the other hand, you want to assign it a static IP, you must take a couple extra steps:
- In your linux server, download the ubuntu server cloud image OVA (used for the jumpbox VM) and paste it in the /concourse folder. A template VM will be created, which can then be cloned and assigned a static IP address.
- Create a terraform.tfvars, file and fill in these values:
vsphere-user = "" # The username of the vSphere user to be used for this deployment
vsphere-password = "" # The password of the vSphere user to be used for this deployment
vsphere-server = "" # The vSphere server (IP address or FQDN)
vsphere-datacenter = "" # The vSphere Datacenter you will deploy this virtual machine to
vsphere-datastore = "" # The datastore you will deploy this virtual machine to
vsphere-resource_pool = "" # The resource pool to be used by this virtual machine
vsphere-host = "" # The ESXi host you will deploy this virtual machine to
vsphere-network = "" # The network segment to be used by this virtual machine
vsphere-network-cidr = "" # The CIDR of the "vsphere-network"
vm-folder = "" # The name of the vSphere folder which will contain the Concourse virtual machine
concourse-fqdn = "" # The FQDN of your Concourse deployment
concourse-username = "" # The Username of the concourse admin
concourse-password = "" # The Password of the concourse admin
# Variables for static Concourse deployment
concourse-static-ip = "" # The Static IP address to be used by Concourse (not available yet)
focal-ova = "" # The full path to the focal cloud-server image you downloaded
focal-cloudserver-name = "" # The name of the focal cloud server virtual machine that will be deployed
dhcp-concourse = false # Deploy concourse with a static IP address
- Navigate to the "concourse" directory
- Execute
terraform init
- Execute
terraform apply
As with the previous deployment (DHCP), the script will output the Concourse FQDN (which you assigned) and the virtual machine’s IP address, so add this to your DNS entries, and access Concourse through HTTP. Use the user test with the password test to authenticate.
Happy pipelining!
Edit 03-04-2022
I have converted the script described in this blogpost into one to deploy any amount of virtual machines (with static and/or dynamic IP addresses) which will execute a startup script at creation. Check it out the updated repo