diff --git a/openstack-tf/modules/cassandra/cassandra-outputs.tf b/openstack-tf/modules/cassandra/cassandra-outputs.tf new file mode 100644 index 0000000..422c305 --- /dev/null +++ b/openstack-tf/modules/cassandra/cassandra-outputs.tf @@ -0,0 +1,15 @@ +output "cassandra_data" { + value = var.cassandra_server_data +} + +output "cassandra_ip_addrs" { + value = var.cassandra_ip +} + +output "cassandra_network" { + value = var.cassandra_net +} + +output "cassandra_tcp_ports" { + value = var.cassandra_tcp_ports_map +} diff --git a/openstack-tf/modules/cassandra/cassandra.tf b/openstack-tf/modules/cassandra/cassandra.tf new file mode 100644 index 0000000..f67d340 --- /dev/null +++ b/openstack-tf/modules/cassandra/cassandra.tf @@ -0,0 +1,116 @@ +# +# Cassandra shared server +# Network +resource "openstack_networking_network_v2" "cassandra_net" { + name = var.cassandra_net.network_name + admin_state_up = "true" + external = "false" + description = var.cassandra_net.network_description + dns_domain = data.terraform_remote_state.privnet_dns_router.outputs.dns_zone.zone_name + mtu = module.common_variables.mtu_size + port_security_enabled = true + shared = false + region = module.common_variables.main_region +} + +# Subnet +resource "openstack_networking_subnet_v2" "cassandra_subnet" { + name = "cassandra-subnet" + description = "subnet used to connect to the shared Cassandra service" + network_id = openstack_networking_network_v2.cassandra_net.id + cidr = var.cassandra_net.network_cidr + dns_nameservers = module.common_variables.resolvers_ip + ip_version = 4 + enable_dhcp = true + no_gateway = true + allocation_pool { + start = var.cassandra_net.allocation_pool_start + end = var.cassandra_net.allocation_pool_end + } +} + +# Security group +resource "openstack_networking_secgroup_v2" "cassandra_access" { + name = "access_to_the_cassandra_service" + delete_default_rules = "true" + description = "Access the shared Cassandra service using the dedicated network" +} + +resource "openstack_networking_secgroup_rule_v2" "cassandra_access_from_dedicated_subnet" { + for_each = var.cassandra_tcp_ports_map + security_group_id = openstack_networking_secgroup_v2.cassandra_access.id + description = each.value.description + direction = "ingress" + ethertype = "IPv4" + protocol = "tcp" + port_range_min = each.value.port_min + port_range_max = each.value.port_max + remote_ip_prefix = var.cassandra_net.network_cidr +} + +resource "openstack_networking_secgroup_rule_v2" "cassandra_metrics" { + security_group_id = openstack_networking_secgroup_v2.cassandra_access.id + description = "JMX, used to export metrics" + direction = "ingress" + ethertype = "IPv4" + protocol = "tcp" + port_range_min = 7199 + port_range_max = 7199 + remote_ip_prefix = data.terraform_remote_state.privnet_dns_router.outputs.basic_services_ip.prometheus_cidr +} + +resource "openstack_compute_servergroup_v2" "cassandra_cluster" { + name = "cassandra_cluster" + policies = [var.cassandra_affinity_policy] +} + +# Instances with an additional block device +resource "openstack_compute_instance_v2" "cassandra_server" { + count = var.cassandra_nodes_count + name = format("%s-%02d", var.cassandra_server_data.node_name, count.index + 1) + availability_zone_hints = module.common_variables.availability_zones_names.availability_zone_no_gpu + image_name = module.common_variables.ubuntu_2204.name + flavor_name = var.cassandra_node_flavor + key_pair = module.ssh_settings.ssh_key_name + security_groups = [data.terraform_remote_state.privnet_dns_router.outputs.default_security_group_name, openstack_networking_secgroup_v2.cassandra_access.name] + scheduler_hints { + group = openstack_compute_servergroup_v2.cassandra_cluster.id + } + block_device { + uuid = module.common_variables.ubuntu_2204.uuid + source_type = "image" + volume_size = 10 + boot_index = 0 + destination_type = "volume" + delete_on_termination = true + } + + block_device { + source_type = "blank" + volume_size = var.cassandra_server_data.node_data_disk_size + boot_index = -1 + destination_type = "volume" + delete_on_termination = false + } + + network { + name = data.terraform_remote_state.privnet_dns_router.outputs.main_private_network.name + } + network { + name = var.cassandra_net.network_name + fixed_ip_v4 = var.cassandra_ip.* [count.index] + } + + user_data = file("${module.common_variables.ubuntu_2204.user_data_file}") + depends_on = [openstack_networking_subnet_v2.cassandra_subnet] + # Do not replace the instance when the ssh key changes + lifecycle { + ignore_changes = [ + # Ignore changes to tags, e.g. because a management agent + # updates these based on some ruleset managed elsewhere. + key_pair, user_data, network + ] + } +} + + diff --git a/openstack-tf/modules/cassandra/terraform-provider.tf b/openstack-tf/modules/cassandra/terraform-provider.tf new file mode 100644 index 0000000..f3678ce --- /dev/null +++ b/openstack-tf/modules/cassandra/terraform-provider.tf @@ -0,0 +1,29 @@ +# Define required providers +terraform { + required_version = ">= 0.14.0" + required_providers { + openstack = { + source = "terraform-provider-openstack/openstack" + version = "~> 1.53.0" + } + } +} + +data "terraform_remote_state" "privnet_dns_router" { + backend = "local" + + config = { + path = "../project-setup/terraform.tfstate" + } +} + +# SSH settings +module "ssh_settings" { + source = "../../modules/ssh-key-ref" +} + +# Global variables (constants, really) +module "common_variables" { + source = "../../modules/common_variables" +} + diff --git a/openstack-tf/modules/cassandra/variables-cassandra.tf b/openstack-tf/modules/cassandra/variables-cassandra.tf new file mode 100644 index 0000000..8471e4d --- /dev/null +++ b/openstack-tf/modules/cassandra/variables-cassandra.tf @@ -0,0 +1,56 @@ +variable "cassandra_server_data" { + type = map(string) + default = { + node_name = "cassandra" + node_data_disk_size = 20 + node_data_disk_device = "/dev/vdb" + } +} + +variable "cassandra_affinity_policy" { + default = "soft-anti-affinity" +} + +variable "cassandra_node_flavor" { + default = "" +} + +variable "cassandra_nodes_count" { + default = 0 +} + +variable "cassandra_ip" { + type = list(string) + default = ["192.168.13.5", "192.168.13.6", "192.168.13.7"] +} + +variable "cassandra_cidr" { + type = list(string) + default = ["192.168.13.5/32", "192.168.13.6/32", "192.168.13.7/32"] +} + +variable "cassandra_net" { + type = map(string) + default = { + network_name = "cassandra-net" + network_description = "Network used by the Cassandra cluster and clients to access the service" + network_cidr = "192.168.13.0/24" + allocation_pool_start = "192.168.13.20" + allocation_pool_end = "192.168.13.254" + } +} + +variable "cassandra_tcp_ports_map" { + type = map(object({ + description = string + port_min = number + port_max = number + })) + default = { + "cassandra_ports" = { + description = "" + port_min = 7000 + port_max = 7000 + } + } +}