|
| 1 | +# Copyright (c) 2022, 2025 Oracle Corporation and/or its affiliates. |
| 2 | +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl |
| 3 | + |
| 4 | +# Create the shared compute clusters defined in workers_compute_clusters |
| 5 | + |
| 6 | +resource "oci_core_compute_cluster" "shared" { |
| 7 | + # Create an OCI Compute Cluster resource for each enabled entry of the worker_pools map with that mode. |
| 8 | + for_each = var.compute_clusters |
| 9 | + compartment_id = lookup(each.value, "compartment_id", var.compartment_id) |
| 10 | + display_name = each.key |
| 11 | + defined_tags = merge( |
| 12 | + var.defined_tags, |
| 13 | + lookup(each.value, "defined_tags", {}) |
| 14 | + ) |
| 15 | + freeform_tags = merge( |
| 16 | + var.freeform_tags, |
| 17 | + lookup(each.value, "freeform_tags", {}) |
| 18 | + ) |
| 19 | + |
| 20 | + availability_domain = lookup(var.ad_numbers_to_names, lookup(each.value, "placement_ad", 1)) |
| 21 | + |
| 22 | + lifecycle { |
| 23 | + ignore_changes = [ |
| 24 | + display_name, defined_tags, freeform_tags, |
| 25 | + ] |
| 26 | + } |
| 27 | +} |
| 28 | + |
| 29 | +# Dynamic resource block for Compute Cluster groups defined in worker_pools |
| 30 | +resource "oci_core_compute_cluster" "workers" { |
| 31 | + # Create an OCI Compute Cluster resource for each enabled entry of the worker_pools map with that mode. |
| 32 | + for_each = { for k, v in local.enabled_compute_clusters : k => v if length(lookup(v, "instance_ids", [])) > 0 && lookup(v, "compute_cluster", null) == null } |
| 33 | + compartment_id = each.value.compartment_id |
| 34 | + display_name = each.key |
| 35 | + defined_tags = each.value.defined_tags |
| 36 | + freeform_tags = each.value.freeform_tags |
| 37 | + availability_domain = lookup(each.value, "placement_ad", null) != null ? lookup(var.ad_numbers_to_names, lookup(each.value, "placement_ad")) : element(each.value.availability_domains, 0) |
| 38 | + |
| 39 | + lifecycle { |
| 40 | + ignore_changes = [ |
| 41 | + display_name, defined_tags, freeform_tags, |
| 42 | + ] |
| 43 | + } |
| 44 | +} |
| 45 | + |
| 46 | +resource "oci_core_instance" "compute_cluster_workers" { |
| 47 | + for_each = local.compute_cluster_instance_map |
| 48 | + |
| 49 | + availability_domain = (lookup(oci_core_compute_cluster.shared, lookup(each.value, "compute_cluster", ""), null) != null ? |
| 50 | + oci_core_compute_cluster.shared[lookup(each.value, "compute_cluster", "")].availability_domain : |
| 51 | + lookup(each.value, "placement_ad", null) != null ? lookup(var.ad_numbers_to_names, lookup(each.value, "placement_ad")) : element(each.value.availability_domains, 0) |
| 52 | + ) |
| 53 | + fault_domain = try(each.value.placement_fds[0], null) |
| 54 | + compartment_id = each.value.compartment_id |
| 55 | + display_name = format("%s-%s", element(split("###", each.key), 0), element(split("###", each.key), 1)) |
| 56 | + preserve_boot_volume = false |
| 57 | + shape = each.value.shape |
| 58 | + |
| 59 | + defined_tags = each.value.defined_tags |
| 60 | + freeform_tags = each.value.freeform_tags |
| 61 | + extended_metadata = each.value.extended_metadata |
| 62 | + capacity_reservation_id = each.value.capacity_reservation_id |
| 63 | + compute_cluster_id = (lookup(oci_core_compute_cluster.shared, lookup(each.value, "compute_cluster", ""), null) != null ? |
| 64 | + oci_core_compute_cluster.shared[lookup(each.value, "compute_cluster", "")].id : |
| 65 | + (lookup(oci_core_compute_cluster.workers, element(split("###", each.key), 0), null) != null ? |
| 66 | + oci_core_compute_cluster.workers[element(split("###", each.key), 0)].id : |
| 67 | + lookup(each.value, "compute_cluster", "") |
| 68 | + ) |
| 69 | + ) |
| 70 | + |
| 71 | + dynamic "platform_config" { |
| 72 | + for_each = each.value.platform_config != null ? [1] : [] |
| 73 | + content { |
| 74 | + type = lookup( |
| 75 | + # Attempt lookup against data source for the associated 'type' of configured worker shape |
| 76 | + lookup(local.platform_config_by_shape, each.value.shape, {}), "type", |
| 77 | + # Fall back to 'type' on pool with custom platform_config, or INTEL_VM default |
| 78 | + lookup(each.value.platform_config, "type", "INTEL_VM") |
| 79 | + ) |
| 80 | + # Remaining parameters as configured, validated by instance/instance config resource |
| 81 | + are_virtual_instructions_enabled = lookup(each.value.platform_config, "are_virtual_instructions_enabled", null) |
| 82 | + is_access_control_service_enabled = lookup(each.value.platform_config, "is_access_control_service_enabled", null) |
| 83 | + is_input_output_memory_management_unit_enabled = lookup(each.value.platform_config, "is_input_output_memory_management_unit_enabled", null) |
| 84 | + is_measured_boot_enabled = lookup(each.value.platform_config, "is_measured_boot_enabled", null) |
| 85 | + is_memory_encryption_enabled = lookup(each.value.platform_config, "is_memory_encryption_enabled", null) |
| 86 | + is_secure_boot_enabled = lookup(each.value.platform_config, "is_secure_boot_enabled", null) |
| 87 | + is_symmetric_multi_threading_enabled = lookup(each.value.platform_config, "is_symmetric_multi_threading_enabled", null) |
| 88 | + is_trusted_platform_module_enabled = lookup(each.value.platform_config, "is_trusted_platform_module_enabled", null) |
| 89 | + numa_nodes_per_socket = lookup(each.value.platform_config, "numa_nodes_per_socket", null) |
| 90 | + percentage_of_cores_enabled = lookup(each.value.platform_config, "percentage_of_cores_enabled", null) |
| 91 | + } |
| 92 | + } |
| 93 | + |
| 94 | + agent_config { |
| 95 | + are_all_plugins_disabled = each.value.agent_config.are_all_plugins_disabled |
| 96 | + is_management_disabled = each.value.agent_config.is_management_disabled |
| 97 | + is_monitoring_disabled = each.value.agent_config.is_monitoring_disabled |
| 98 | + dynamic "plugins_config" { |
| 99 | + for_each = merge( |
| 100 | + { |
| 101 | + "Compute HPC RDMA Authentication" : "ENABLED", |
| 102 | + "Compute HPC RDMA Auto-Configuration" : "ENABLED" |
| 103 | + }, |
| 104 | + each.value.agent_config.plugins_config |
| 105 | + ) |
| 106 | + content { |
| 107 | + name = plugins_config.key |
| 108 | + desired_state = plugins_config.value |
| 109 | + } |
| 110 | + } |
| 111 | + } |
| 112 | + |
| 113 | + create_vnic_details { |
| 114 | + assign_private_dns_record = var.assign_dns |
| 115 | + assign_public_ip = each.value.assign_public_ip |
| 116 | + nsg_ids = each.value.nsg_ids |
| 117 | + subnet_id = each.value.subnet_id |
| 118 | + defined_tags = each.value.defined_tags |
| 119 | + freeform_tags = each.value.freeform_tags |
| 120 | + } |
| 121 | + |
| 122 | + instance_options { |
| 123 | + are_legacy_imds_endpoints_disabled = false |
| 124 | + } |
| 125 | + |
| 126 | + metadata = merge( |
| 127 | + { |
| 128 | + apiserver_host = var.apiserver_private_host |
| 129 | + cluster_ca_cert = var.cluster_ca_cert |
| 130 | + oke-k8version = var.kubernetes_version |
| 131 | + oke-kubeproxy-proxy-mode = var.kubeproxy_mode |
| 132 | + oke-tenancy-id = var.tenancy_id |
| 133 | + oke-initial-node-labels = join(",", [for k, v in each.value.node_labels : format("%v=%v", k, v)]) |
| 134 | + secondary_vnics = jsonencode(lookup(each.value, "secondary_vnics", {})) |
| 135 | + ssh_authorized_keys = var.ssh_public_key |
| 136 | + user_data = lookup(lookup(data.cloudinit_config.workers, element(split("###", each.key), 0), {}), "rendered", "") |
| 137 | + }, |
| 138 | + |
| 139 | + # Add labels required for NPN CNI. |
| 140 | + var.cni_type == "npn" ? { |
| 141 | + oke-native-pod-networking = true |
| 142 | + oke-max-pods = var.max_pods_per_node |
| 143 | + pod-subnets = coalesce(var.pod_subnet_id, var.worker_subnet_id, "none") |
| 144 | + pod-nsgids = join(",", each.value.pod_nsg_ids) |
| 145 | + } : {}, |
| 146 | + |
| 147 | + # Only provide cluster DNS service address if set explicitly; determined automatically in practice. |
| 148 | + coalesce(var.cluster_dns, "none") == "none" ? {} : { kubedns_svc_ip = var.cluster_dns }, |
| 149 | + |
| 150 | + # Extra user-defined fields merged last |
| 151 | + var.node_metadata, # global |
| 152 | + lookup(each.value, "node_metadata", {}), # pool-specific |
| 153 | + ) |
| 154 | + |
| 155 | + source_details { |
| 156 | + boot_volume_size_in_gbs = each.value.boot_volume_size |
| 157 | + boot_volume_vpus_per_gb = each.value.boot_volume_vpus_per_gb |
| 158 | + source_id = each.value.image_id |
| 159 | + source_type = "image" |
| 160 | + } |
| 161 | + |
| 162 | + lifecycle { |
| 163 | + precondition { |
| 164 | + condition = coalesce(each.value.image_id, "none") != "none" |
| 165 | + error_message = <<-EOT |
| 166 | + Missing image_id; check provided value if image_type is 'custom', or image_os/image_os_version if image_type is 'oke' or 'platform'. |
| 167 | + pool: ${element(split("###", each.key), 0)} |
| 168 | + image_type: ${coalesce(each.value.image_type, "none")} |
| 169 | + image_id: ${coalesce(each.value.image_id, "none")} |
| 170 | + EOT |
| 171 | + } |
| 172 | + |
| 173 | + ignore_changes = [ |
| 174 | + agent_config, # TODO Not updateable; remove when supported |
| 175 | + defined_tags, freeform_tags, display_name, |
| 176 | + metadata["cluster_ca_cert"], metadata["user_data"], |
| 177 | + create_vnic_details[0].defined_tags, |
| 178 | + create_vnic_details[0].freeform_tags, |
| 179 | + ] |
| 180 | + } |
| 181 | +} |
0 commit comments