Prerequisites

Before you embark on this exciting journey, make sure you have the following:

  • 🛠️ make installed on your machine
  • 📄 A valid clouds.yaml file in the ~/.config/openstack directory
  • Terraform/OpenTofu installed on your machine
  • 🌐 An available network, subnet, router, and security group. Use the Terraform file below to create these resources:
locals {
  resources_base_name = "packer"
  dns_servers = [
    "8.8.8.8"
  ]
  cidr = "10.0.50.0/24"
  whitelisted_ips = [
    "0.0.0.0/0"
  ]
}

data "openstack_networking_network_v2" "external" {
  name = "public"
}

resource "openstack_networking_network_v2" "net" {
  name           = local.resources_base_name
  admin_state_up = true
  mtu            = 1442
}

resource "openstack_networking_subnet_v2" "subnet" {
  name            = local.resources_base_name
  network_id      = openstack_networking_network_v2.net.id
  cidr            = local.cidr
  ip_version      = 4
  dns_nameservers = local.dns_servers
}

resource "openstack_networking_router_v2" "router" {
  name                = local.resources_base_name
  admin_state_up      = true
  external_network_id = data.openstack_networking_network_v2.external.id
}

resource "openstack_networking_router_interface_v2" "iface" {
  router_id = openstack_networking_router_v2.router.id
  subnet_id = openstack_networking_subnet_v2.subnet.id
}

resource "openstack_networking_secgroup_v2" "runners-secgroup" {
  name        = local.resources_base_name
  description = "Packer security group"
}

// Allow SSH from the whitelisted IPs
resource "openstack_networking_secgroup_rule_v2" "runners-secgroup-rule-ssh" {
  direction         = "ingress"
  ethertype         = "IPv4"
  protocol          = "tcp"
  port_range_min    = 22
  port_range_max    = 22
  remote_ip_prefix  = join(",", local.whitelisted_ips)
  security_group_id = openstack_networking_secgroup_v2.runners-se
  cgroup.id
}

output "public_network_id" {
  value = data.openstack_networking_network_v2.external.id
  description = "Public network ID"
}
output "network_id" {
  value = openstack_networking_network_v2.net.id
  description = "Packer network ID"
}

Before running the Terraform file, set the OS_CLOUD environment variable to the name of the cloud in your clouds.yaml file. For example:

export OS_CLOUD=your-cloud-name

Build the CAPI Image

Before building the CAPI image, check the compatibility matrix of Cluster API and Kubernetes versions. You can find it in the release notes of the Cluster API repository here.

Pull the Image-Builder Repository

git clone [email protected]:kubernetes-sigs/image-builder.git
cd image-builder

Create Your Packer Custom Variables File

Using this template, fill in the fields based on your Openstack configuration:

{
  "image_name": "<image_name>",
  "source_image": "<image_id>",
  "networks": "<packer_network_id>",
  "flavor": "<desired_flavor_name>",
  "floating_ip_network": "<public_network_id>",
  "use_floating_ip": "true",
  "image_visibility": "private",
  "image_disk_format": "qcow2",
  "volume_type": "silver",
  "volume_size": "50",
  "use_blockstorage_volume": "true",
  "kubernetes_semver": "<kubernetes_version>",
  "kubernetes_series": "<kubernetes_series>",
  "kubernetes_deb_version": "<kubernetes_deb_version>",
  "security_groups": "<packer_security_group_name>"
}

Attributes Explanation

  • Image name: The name of the image that will be created.
  • Source image: The ID of the image that will be used as a base image. Get this ID by running openstack image list.
  • Networks: The ID of the network where the image will be created. Get this ID by running openstack network list.
  • Flavor: The flavor that will be used to create the image.
  • Floating IP network: The ID of the public network. Get this ID by running openstack network list (copy the ID of the public network).
  • Kubernetes semver: The Kubernetes version that will be installed on the image, e.g., v1.29.6.
  • Kubernetes series: The Kubernetes series that will be installed on the image, e.g., 1.29.
  • Kubernetes deb version: The Kubernetes deb version that will be installed on the image, e.g., 1.29.6-1.1. Obtain the series and deb by running a local Ubuntu container and following the official Kubernetes install documentation here.

Build the CAPI Image

cd images/capi
PACKER_VAR_FILES=<path_to_your_packer_variables_file> make build-openstack-ubuntu-2404 # For Ubuntu 24.04