infra/terraform/modules/a3/cluster/gke/main.tf (249 lines of code) (raw):

/* Copyright 2024 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at https://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ locals { gke_master_version = var.gke_version != null ? var.gke_version : data.google_container_engine_versions.gkeversion.latest_master_version node_service_account = var.node_service_account == null ? data.google_compute_default_service_account.account.email : var.node_service_account oauth_scopes = [ "https://www.googleapis.com/auth/cloud-platform", "https://www.googleapis.com/auth/dataaccessauditlogging", ] } data "google_compute_default_service_account" "account" { project = var.project_id } data "google_client_config" "current" {} data "google_container_engine_versions" "gkeversion" { location = var.region project = var.project_id } module "network" { source = "../../common/network" nic0_existing = var.network_existing project_id = var.project_id region = var.region resource_prefix = var.resource_prefix } module "dashboard" { source = "../../common/dashboard" count = var.enable_gke_dashboard ? 1 : 0 enable_gce_gke_gpu_utilization_widgets = true enable_nvidia_dcgm_widgets = true enable_nvidia_nvml_widgets = true project_id = var.project_id resource_prefix = var.resource_prefix } module "resource_policy" { source = "../../common/resource_policy" for_each = { for idx, node_pool in var.node_pools : "np-${idx}" => node_pool if node_pool.compact_placement_policy != null } project_id = var.project_id new_resource_policy_name = each.value.compact_placement_policy.new_policy ? "${var.resource_prefix}-${each.key}" : null existing_resource_policy_name = each.value.compact_placement_policy.existing_policy_name region = var.region } # Definition of the private GKE cluster. resource "google_container_cluster" "cluster" { provider = google-beta project = var.project_id name = var.resource_prefix # TODO: Remove region assignment # location = var.region location = var.is_zonal ? var.zone : var.region # We need to explicitly manage the node pool to enable features such as # auto-upgrade and auto-scaling, but we can't create a cluster with no node # pool defined. So we create the smallest possible default node pool and # immediately delete it. This is a best-practice suggested in the Terraform # documentation for the container_cluster resource. remove_default_node_pool = true initial_node_count = 1 min_master_version = local.gke_master_version deletion_protection = false network = module.network.network_self_links[0] subnetwork = module.network.subnetwork_self_links[0] master_authorized_networks_config { } master_auth { client_certificate_config { issue_client_certificate = false } } # Enable shielded nodes to meet go/gke-cluster-pattern#req1.1.5 enable_shielded_nodes = true cluster_autoscaling { autoscaling_profile = "OPTIMIZE_UTILIZATION" # The name of this attribute is very misleading, it controls node # autoprovisioning (NAP), not autoscaling. enabled = false } network_policy { # Enabling NetworkPolicy for clusters with DatapathProvider=ADVANCED_DATAPATH # is not allowed. Dataplane V2 will take care of network policy enforcement # instead. enabled = false # GKE Dataplane V2 support. This must be set to PROVIDER_UNSPECIFIED in # order to let the datapath_provider take effect. # https://github.com/terraform-google-modules/terraform-google-kubernetes-engine/issues/656#issuecomment-720398658 provider = "PROVIDER_UNSPECIFIED" } # This change will also enable the metadata server on nodes. # go/gke-cluster-pattern#req4.1.1#req1.1.5 (parts of, vTPM is another section) workload_identity_config { workload_pool = "${var.project_id}.svc.id.goog" } datapath_provider = "ADVANCED_DATAPATH" networking_mode = "VPC_NATIVE" ip_allocation_policy { cluster_ipv4_cidr_block = "/14" services_ipv4_cidr_block = "/20" } release_channel { channel = "UNSPECIFIED" } addons_config { gce_persistent_disk_csi_driver_config { enabled = true } gcs_fuse_csi_driver_config { enabled = true } gcp_filestore_csi_driver_config { enabled = true } } # enable multi-NIC network enable_multi_networking = true lifecycle { # Ignore all changes to the default node pool. It's being removed # after creation anyway. ignore_changes = [ node_config ] } logging_service = "logging.googleapis.com/kubernetes" monitoring_service = "monitoring.googleapis.com/kubernetes" timeouts { create = "120m" update = "120m" } } # We define explicit node pools, so that it can be modified without # having to destroy the entire cluster. resource "google_container_node_pool" "node-pools" { provider = google-beta count = length(var.node_pools) project = var.project_id name = "np-${count.index}" cluster = google_container_cluster.cluster.id node_locations = [var.node_pools[count.index].zone] node_count = var.node_pools[count.index].node_count upgrade_settings { max_surge = 0 max_unavailable = 1 } management { auto_repair = true # disabling auto_upgrade to stop automatic upgrade during customer workload execution. auto_upgrade = false } node_config { service_account = local.node_service_account machine_type = var.node_pools[count.index].machine_type image_type = "COS_CONTAINERD" disk_size_gb = var.disk_size_gb disk_type = var.disk_type ephemeral_storage_local_ssd_config { local_ssd_count = 16 } shielded_instance_config { enable_secure_boot = true enable_integrity_monitoring = true } gvnic { enabled = true } # Implied by Workload Identity workload_metadata_config { mode = "GKE_METADATA" } # Implied by workload identity. metadata = { "disable-legacy-endpoints" = "true" } labels = { "cloud.google.com/gke-kdump-enabled" = "true" } dynamic "host_maintenance_policy" { for_each = var.host_maintenance_interval != null ? [1] : [] content { maintenance_interval = var.host_maintenance_interval } } dynamic "reservation_affinity" { for_each = try( var.node_pools[count.index].compact_placement_policy.specific_reservation, null ) != null ? [ var.node_pools[count.index].compact_placement_policy.specific_reservation ] : [] content { consume_reservation_type = "SPECIFIC_RESERVATION" key = "compute.googleapis.com/reservation-name" values = [reservation_affinity.value] } } oauth_scopes = local.oauth_scopes } network_config { dynamic "additional_node_network_configs" { for_each = toset(range(1, length(module.network.network_names))) iterator = id content { network = module.network.network_names[id.value] subnetwork = module.network.subnetwork_names[id.value] } } } dynamic "placement_policy" { for_each = var.node_pools[count.index].compact_placement_policy != null ? [1] : [] content { type = "COMPACT" policy_name = module.resource_policy["np-${count.index}"].resource_name } } lifecycle { ignore_changes = [ node_config[0].labels, node_config[0].taint, ] } timeouts { create = "10m" update = "10m" } } resource "google_container_node_pool" "default_pool" { name = "np-default" cluster = google_container_cluster.cluster.id project = var.project_id location = var.default_node_pool.zone node_count = var.default_node_pool.node_count node_config { service_account = local.node_service_account machine_type = var.default_node_pool.machine_type oauth_scopes = local.oauth_scopes } depends_on = [google_container_cluster.cluster] } # For container logs to show up under Cloud Logging and GKE metrics to show up # on Cloud Monitoring console, some project level roles are needed for the # node_service_account resource "google_project_iam_member" "node_service_account_logWriter" { project = var.project_id role = "roles/logging.logWriter" member = "serviceAccount:${local.node_service_account}" } resource "google_project_iam_member" "node_service_account_metricWriter" { project = var.project_id role = "roles/monitoring.metricWriter" member = "serviceAccount:${local.node_service_account}" } resource "google_project_iam_member" "node_service_account_monitoringViewer" { project = var.project_id role = "roles/monitoring.viewer" member = "serviceAccount:${local.node_service_account}" } module "kubectl-apply" { source = "./kubectl-apply" cluster_id = resource.google_container_cluster.cluster.id daemonsets = { device_plugin = "https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/master/cmd/nvidia_gpu/device-plugin.yaml" nvidia_driver = "https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/master/nvidia-driver-installer/cos/daemonset-preloaded-latest.yaml" nccl_plugin = "https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/master/gpudirect-tcpx/nccl-tcpx-installer.yaml" } enable = var.ksa != null ksa = var.ksa gcp_sa = local.node_service_account project_id = var.project_id }