diff --git a/CHANGELOG.md b/CHANGELOG.md index f4e6f7c8a..d05dbb75f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ All notable changes to this project will be documented in this file. ### MODULES +- [[#3316](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/3316)] Add support for upgrade notification filters to GKE cluster modules ([ludoo](https://github.com/ludoo)) - [[#3315](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/3315)] Refactor secret manager module ([ludoo](https://github.com/ludoo)) - [[#3313](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/3313)] Add support for startup script to compute-vm module ([ludoo](https://github.com/ludoo)) - [[#3286](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/3286)] Added support for cross-project NEGs in net-lb-app-int module ([avh01](https://github.com/avh01)) diff --git a/modules/gke-cluster-autopilot/README.md b/modules/gke-cluster-autopilot/README.md index 46868b7d9..60f8b72ce 100644 --- a/modules/gke-cluster-autopilot/README.md +++ b/modules/gke-cluster-autopilot/README.md @@ -268,25 +268,25 @@ module "cluster-1" { | name | description | type | required | default | |---|---|:---:|:---:|:---:| -| [location](variables.tf#L149) | Autopilot clusters are always regional. | string | ✓ | | -| [name](variables.tf#L228) | Cluster name. | string | ✓ | | -| [project_id](variables.tf#L260) | Cluster project ID. | string | ✓ | | -| [vpc_config](variables.tf#L276) | VPC-level configuration. | object({…}) | ✓ | | +| [location](variables.tf#L161) | Autopilot clusters are always regional. | string | ✓ | | +| [name](variables.tf#L240) | Cluster name. | string | ✓ | | +| [project_id](variables.tf#L272) | Cluster project ID. | string | ✓ | | +| [vpc_config](variables.tf#L288) | VPC-level configuration. | object({…}) | ✓ | | | [access_config](variables.tf#L17) | Control plane endpoint and nodes access configurations. | object({…}) | | {} | | [backup_configs](variables.tf#L45) | Configuration for Backup for GKE. | object({…}) | | {} | | [deletion_protection](variables.tf#L66) | Whether or not to allow Terraform to destroy the cluster. Unless this field is set to false in Terraform state, a terraform destroy or terraform apply that would delete the cluster will fail. | bool | | true | | [description](variables.tf#L73) | Cluster description. | string | | null | | [enable_addons](variables.tf#L79) | Addons enabled in the cluster (true means enabled). | object({…}) | | {} | -| [enable_features](variables.tf#L93) | Enable cluster-level features. Certain features allow configuration. | object({…}) | | {} | -| [issue_client_certificate](variables.tf#L137) | Enable issuing client certificate. | bool | | false | -| [labels](variables.tf#L143) | Cluster resource labels. | map(string) | | null | -| [logging_config](variables.tf#L154) | Logging configuration. | object({…}) | | {} | -| [maintenance_config](variables.tf#L165) | Maintenance window configuration. | object({…}) | | {…} | -| [min_master_version](variables.tf#L188) | Minimum version of the master, defaults to the version of the most recent official release. | string | | null | -| [monitoring_config](variables.tf#L194) | Monitoring configuration. System metrics collection cannot be disabled. Control plane metrics are optional. Kube state metrics are optional. Google Cloud Managed Service for Prometheus is enabled by default. | object({…}) | | {} | -| [node_config](variables.tf#L233) | Configuration for nodes and nodepools. | object({…}) | | {} | -| [node_locations](variables.tf#L253) | Zones in which the cluster's nodes are located. | list(string) | | [] | -| [release_channel](variables.tf#L265) | Release channel for GKE upgrades. Clusters created in the Autopilot mode must use a release channel. Choose between \"RAPID\", \"REGULAR\", and \"STABLE\". | string | | "REGULAR" | +| [enable_features](variables.tf#L93) | Enable cluster-level features. Certain features allow configuration. | object({…}) | | {} | +| [issue_client_certificate](variables.tf#L149) | Enable issuing client certificate. | bool | | false | +| [labels](variables.tf#L155) | Cluster resource labels. | map(string) | | null | +| [logging_config](variables.tf#L166) | Logging configuration. | object({…}) | | {} | +| [maintenance_config](variables.tf#L177) | Maintenance window configuration. | object({…}) | | {…} | +| [min_master_version](variables.tf#L200) | Minimum version of the master, defaults to the version of the most recent official release. | string | | null | +| [monitoring_config](variables.tf#L206) | Monitoring configuration. System metrics collection cannot be disabled. Control plane metrics are optional. Kube state metrics are optional. Google Cloud Managed Service for Prometheus is enabled by default. | object({…}) | | {} | +| [node_config](variables.tf#L245) | Configuration for nodes and nodepools. | object({…}) | | {} | +| [node_locations](variables.tf#L265) | Zones in which the cluster's nodes are located. | list(string) | | [] | +| [release_channel](variables.tf#L277) | Release channel for GKE upgrades. Clusters created in the Autopilot mode must use a release channel. Choose between \"RAPID\", \"REGULAR\", and \"STABLE\". | string | | "REGULAR" | ## Outputs diff --git a/modules/gke-cluster-autopilot/main.tf b/modules/gke-cluster-autopilot/main.tf index c3ae19680..9cc7ec7b9 100644 --- a/modules/gke-cluster-autopilot/main.tf +++ b/modules/gke-cluster-autopilot/main.tf @@ -265,7 +265,13 @@ resource "google_container_cluster" "cluster" { for_each = var.enable_features.upgrade_notifications != null ? [""] : [] content { pubsub { - enabled = true + enabled = var.enable_features.upgrade_notifications.enabled + dynamic "filter" { + for_each = var.enable_features.upgrade_notifications.event_types != null ? [""] : [] + content { + event_type = var.enable_features.upgrade_notifications.event_types + } + } topic = ( try(var.enable_features.upgrade_notifications.topic_id, null) != null ? var.enable_features.upgrade_notifications.topic_id diff --git a/modules/gke-cluster-autopilot/variables.tf b/modules/gke-cluster-autopilot/variables.tf index a08ab9c8b..bbeb90e06 100644 --- a/modules/gke-cluster-autopilot/variables.tf +++ b/modules/gke-cluster-autopilot/variables.tf @@ -126,12 +126,24 @@ variable "enable_features" { service_external_ips = optional(bool, true) tpu = optional(bool, false) upgrade_notifications = optional(object({ - topic_id = optional(string) + enabled = optional(bool, true) + event_types = optional(list(string), []) + topic_id = optional(string) })) vertical_pod_autoscaling = optional(bool, false) enterprise_cluster = optional(bool) }) default = {} + validation { + condition = alltrue([ + for e in try(var.enable_features.upgrade_notifications.event_types, []) : + contains([ + "UPGRADE_AVAILABLE_EVENT", "UPGRADE_EVENT", + "SECURITY_BULLETIN_EVENT", "UPGRADE_INFO_EVENT" + ], e) + ]) + error_message = "Invalid upgrade notification event type." + } } variable "issue_client_certificate" { diff --git a/modules/gke-cluster-standard/README.md b/modules/gke-cluster-standard/README.md index fca8d922b..ec711568c 100644 --- a/modules/gke-cluster-standard/README.md +++ b/modules/gke-cluster-standard/README.md @@ -13,6 +13,7 @@ This module offers a way to create and manage Google Kubernetes Engine (GKE) [St - [Regional cluster](#regional-cluster) - [Enable Dataplane V2](#enable-dataplane-v2) - [Managing GKE logs](#managing-gke-logs) +- [Upgrade notifications](#upgrade-notifications) - [Monitoring configuration](#monitoring-configuration) - [Disable GKE logs or metrics collection](#disable-gke-logs-or-metrics-collection) - [Cloud DNS](#cloud-dns) @@ -222,6 +223,30 @@ module "cluster-1" { # tftest modules=1 resources=1 inventory=logging-config-enable-all.yaml ``` +## Upgrade notifications + +Upgrade notifications are configured via the `enable_features.upgrade_notifications`. An existing PubSub topic can be defined via its `topic` attribute, or a new one can be created if the attribute is not set. The `event_types` attribute can be used to control which event types are sent. + +```hcl +module "cluster-1" { + source = "./fabric/modules/gke-cluster-standard" + project_id = "myproject" + name = "cluster-1" + location = "europe-west1-b" + vpc_config = { + network = var.vpc.self_link + subnetwork = var.subnet.self_link + secondary_range_names = {} + } + enable_features = { + upgrade_notifications = { + event_types = ["SECURITY_BULLETIN_EVENT", "UPGRADE_EVENT"] + } + } +} +# tftest modules=1 resources=2 inventory=notifications.yaml +``` + ## Monitoring configuration This example shows how to [configure collection of Kubernetes control plane metrics](https://cloud.google.com/stackdriver/docs/solutions/gke/managing-metrics#enable-control-plane-metrics). These metrics are optional and are not collected by default. @@ -416,7 +441,6 @@ module "cluster-1" { You can use `var.cluster_autoscaling` block to configure node auto-provisioning for the GKE cluster. The example below configures limits for CPU, memory, GPUs and TPUs. - ```hcl module "cluster-1" { source = "./fabric/modules/gke-cluster-standard" @@ -486,10 +510,10 @@ module "cluster-1" { | name | description | type | required | default | |---|---|:---:|:---:|:---:| -| [location](variables.tf#L269) | Cluster zone or region. | string | ✓ | | -| [name](variables.tf#L384) | Cluster name. | string | ✓ | | -| [project_id](variables.tf#L435) | Cluster project id. | string | ✓ | | -| [vpc_config](variables.tf#L446) | VPC-level configuration. | object({…}) | ✓ | | +| [location](variables.tf#L281) | Cluster zone or region. | string | ✓ | | +| [name](variables.tf#L396) | Cluster name. | string | ✓ | | +| [project_id](variables.tf#L447) | Cluster project id. | string | ✓ | | +| [vpc_config](variables.tf#L458) | VPC-level configuration. | object({…}) | ✓ | | | [access_config](variables.tf#L17) | Control plane endpoint and nodes access configurations. | object({…}) | | {} | | [backup_configs](variables.tf#L45) | Configuration for Backup for GKE. | object({…}) | | {} | | [cluster_autoscaling](variables.tf#L67) | Enable and configure limits for Node Auto-Provisioning with Cluster Autoscaler. | object({…}) | | null | @@ -497,18 +521,18 @@ module "cluster-1" { | [deletion_protection](variables.tf#L165) | Whether or not to allow Terraform to destroy the cluster. Unless this field is set to false in Terraform state, a terraform destroy or terraform apply that would delete the cluster will fail. | bool | | true | | [description](variables.tf#L172) | Cluster description. | string | | null | | [enable_addons](variables.tf#L178) | Addons enabled in the cluster (true means enabled). | object({…}) | | {} | -| [enable_features](variables.tf#L200) | Enable cluster-level features. Certain features allow configuration. | object({…}) | | {} | -| [issue_client_certificate](variables.tf#L256) | Enable issuing client certificate. | bool | | false | -| [labels](variables.tf#L262) | Cluster resource labels. | map(string) | | {} | -| [logging_config](variables.tf#L274) | Logging configuration. | object({…}) | | {} | -| [maintenance_config](variables.tf#L295) | Maintenance window configuration. | object({…}) | | {…} | -| [max_pods_per_node](variables.tf#L318) | Maximum number of pods per node in this cluster. | number | | 110 | -| [min_master_version](variables.tf#L324) | Minimum version of the master, defaults to the version of the most recent official release. | string | | null | -| [monitoring_config](variables.tf#L330) | Monitoring configuration. Google Cloud Managed Service for Prometheus is enabled by default. | object({…}) | | {} | -| [node_config](variables.tf#L389) | Node-level configuration. | object({…}) | | {} | -| [node_locations](variables.tf#L411) | Zones in which the cluster's nodes are located. | list(string) | | [] | -| [node_pool_auto_config](variables.tf#L418) | Node pool configs that apply to auto-provisioned node pools in autopilot clusters and node auto-provisioning-enabled clusters. | object({…}) | | {} | -| [release_channel](variables.tf#L440) | Release channel for GKE upgrades. | string | | null | +| [enable_features](variables.tf#L200) | Enable cluster-level features. Certain features allow configuration. | object({…}) | | {} | +| [issue_client_certificate](variables.tf#L268) | Enable issuing client certificate. | bool | | false | +| [labels](variables.tf#L274) | Cluster resource labels. | map(string) | | {} | +| [logging_config](variables.tf#L286) | Logging configuration. | object({…}) | | {} | +| [maintenance_config](variables.tf#L307) | Maintenance window configuration. | object({…}) | | {…} | +| [max_pods_per_node](variables.tf#L330) | Maximum number of pods per node in this cluster. | number | | 110 | +| [min_master_version](variables.tf#L336) | Minimum version of the master, defaults to the version of the most recent official release. | string | | null | +| [monitoring_config](variables.tf#L342) | Monitoring configuration. Google Cloud Managed Service for Prometheus is enabled by default. | object({…}) | | {} | +| [node_config](variables.tf#L401) | Node-level configuration. | object({…}) | | {} | +| [node_locations](variables.tf#L423) | Zones in which the cluster's nodes are located. | list(string) | | [] | +| [node_pool_auto_config](variables.tf#L430) | Node pool configs that apply to auto-provisioned node pools in autopilot clusters and node auto-provisioning-enabled clusters. | object({…}) | | {} | +| [release_channel](variables.tf#L452) | Release channel for GKE upgrades. | string | | null | ## Outputs diff --git a/modules/gke-cluster-standard/main.tf b/modules/gke-cluster-standard/main.tf index c6ca4e573..8c194b177 100644 --- a/modules/gke-cluster-standard/main.tf +++ b/modules/gke-cluster-standard/main.tf @@ -494,7 +494,13 @@ resource "google_container_cluster" "cluster" { for_each = var.enable_features.upgrade_notifications != null ? [""] : [] content { pubsub { - enabled = true + enabled = var.enable_features.upgrade_notifications.enabled + dynamic "filter" { + for_each = var.enable_features.upgrade_notifications.event_types != null ? [""] : [] + content { + event_type = var.enable_features.upgrade_notifications.event_types + } + } topic = ( try(var.enable_features.upgrade_notifications.topic_id, null) != null ? var.enable_features.upgrade_notifications.topic_id diff --git a/modules/gke-cluster-standard/variables.tf b/modules/gke-cluster-standard/variables.tf index 4d33815f2..c2b146278 100644 --- a/modules/gke-cluster-standard/variables.tf +++ b/modules/gke-cluster-standard/variables.tf @@ -238,7 +238,9 @@ variable "enable_features" { shielded_nodes = optional(bool, false) tpu = optional(bool, false) upgrade_notifications = optional(object({ - topic_id = optional(string) + enabled = optional(bool, true) + event_types = optional(list(string), []) + topic_id = optional(string) })) vertical_pod_autoscaling = optional(bool, false) workload_identity = optional(bool, true) @@ -251,6 +253,16 @@ variable "enable_features" { ) error_message = "FQDN network policy is only supported for clusters with Dataplane v2." } + validation { + condition = alltrue([ + for e in try(var.enable_features.upgrade_notifications.event_types, []) : + contains([ + "UPGRADE_AVAILABLE_EVENT", "UPGRADE_EVENT", + "SECURITY_BULLETIN_EVENT", "UPGRADE_INFO_EVENT" + ], e) + ]) + error_message = "Invalid upgrade notification event type." + } } variable "issue_client_certificate" { diff --git a/tests/modules/gke_cluster_standard/examples/notifications.yaml b/tests/modules/gke_cluster_standard/examples/notifications.yaml new file mode 100644 index 000000000..e53440c1d --- /dev/null +++ b/tests/modules/gke_cluster_standard/examples/notifications.yaml @@ -0,0 +1,181 @@ +# Copyright 2025 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 +# +# http://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. + +values: + module.cluster-1.google_container_cluster.cluster: + addons_config: + - cloudrun_config: + - disabled: true + load_balancer_type: null + config_connector_config: + - enabled: false + dns_cache_config: + - enabled: true + gce_persistent_disk_csi_driver_config: + - enabled: true + gcp_filestore_csi_driver_config: + - enabled: true + gcs_fuse_csi_driver_config: + - enabled: true + gke_backup_agent_config: + - enabled: false + horizontal_pod_autoscaling: + - disabled: false + http_load_balancing: + - disabled: false + istio_config: + - auth: null + disabled: true + kalm_config: + - enabled: false + network_policy_config: + - disabled: true + stateful_ha_config: + - enabled: false + allow_net_admin: null + binary_authorization: [] + control_plane_endpoints_config: + - dns_endpoint_config: + - allow_external_traffic: true + ip_endpoints_config: + - enabled: false + cost_management_config: + - enabled: true + datapath_provider: ADVANCED_DATAPATH + default_max_pods_per_node: 110 + deletion_protection: true + description: null + disable_l4_lb_firewall_reconciliation: false + dns_config: [] + effective_labels: + goog-terraform-provisioned: 'true' + enable_autopilot: null + enable_cilium_clusterwide_network_policy: false + enable_fqdn_network_policy: true + enable_intranode_visibility: false + enable_k8s_beta_apis: [] + enable_kubernetes_alpha: false + enable_l4_ilb_subsetting: false + enable_legacy_abac: false + enable_multi_networking: false + enable_shielded_nodes: false + enable_tpu: false + fleet: [] + in_transit_encryption_config: null + initial_node_count: 1 + ip_allocation_policy: + - additional_ip_ranges_config: [] + additional_pod_ranges_config: [] + stack_type: IPV4 + location: europe-west1-b + logging_config: + - enable_components: + - SYSTEM_COMPONENTS + maintenance_policy: + - daily_maintenance_window: + - start_time: 03:00 + maintenance_exclusion: [] + recurring_window: [] + master_auth: + - client_certificate_config: + - issue_client_certificate: false + min_master_version: null + monitoring_config: + - enable_components: + - SYSTEM_COMPONENTS + managed_prometheus: + - enabled: true + name: cluster-1 + network: projects/xxx/global/networks/aaa + network_performance_config: [] + network_policy: [] + node_config: + - advanced_machine_features: [] + boot_disk_kms_key: null + containerd_config: [] + enable_confidential_storage: null + ephemeral_storage_config: [] + ephemeral_storage_local_ssd_config: [] + fast_socket: [] + flex_start: null + gvnic: [] + host_maintenance_policy: [] + local_nvme_ssd_block_config: [] + local_ssd_encryption_mode: null + max_run_duration: null + node_group: null + preemptible: false + reservation_affinity: [] + resource_labels: null + resource_manager_tags: null + sandbox_config: [] + secondary_boot_disks: [] + sole_tenant_config: [] + spot: false + storage_pools: null + tags: null + taint: [] + node_pool_defaults: + - node_config_defaults: + - containerd_config: [] + gcfs_config: + - enabled: false + insecure_kubelet_readonly_port_enabled: 'TRUE' + notification_config: + - pubsub: + - enabled: true + filter: + - event_type: + - SECURITY_BULLETIN_EVENT + - UPGRADE_EVENT + pod_security_policy_config: [] + private_cluster_config: + - enable_private_endpoint: true + enable_private_nodes: true + private_endpoint_subnetwork: null + project: myproject + remove_default_node_pool: true + resource_labels: null + resource_usage_export_config: [] + secret_manager_config: [] + subnetwork: subnet_self_link + terraform_labels: + goog-terraform-provisioned: 'true' + timeouts: null + user_managed_keys_config: [] + workload_identity_config: + - workload_pool: myproject.svc.id.goog + module.cluster-1.google_pubsub_topic.notifications[0]: + effective_labels: + content: gke-notifications + goog-terraform-provisioned: 'true' + ingestion_data_source_settings: [] + kms_key_name: null + labels: + content: gke-notifications + message_retention_duration: null + message_transforms: [] + name: gke-pubsub-notifications + project: myproject + schema_settings: [] + terraform_labels: + content: gke-notifications + goog-terraform-provisioned: 'true' + timeouts: null + +counts: + google_container_cluster: 1 + google_pubsub_topic: 1 + modules: 1 + resources: 2