From ca97d36f8c747365c3a595eb340986421911326b Mon Sep 17 00:00:00 2001 From: Modular Magician Date: Wed, 28 Aug 2024 23:11:47 +0000 Subject: [PATCH] container: add support for kubelet read only port (#11272) Co-authored-by: Stephen Lewis (Burrows) [upstream:fcc529c34fcf793400595d5ad3df8924915a5976] Signed-off-by: Modular Magician --- .changelog/11272.txt | 6 + google-beta/services/container/node_config.go | 49 +++- .../container/resource_container_cluster.go | 83 ++++++- .../resource_container_cluster_test.go | 218 ++++++++++++++++++ .../resource_container_node_pool_test.go | 34 ++- .../docs/r/container_cluster.html.markdown | 4 + 6 files changed, 378 insertions(+), 16 deletions(-) create mode 100644 .changelog/11272.txt diff --git a/.changelog/11272.txt b/.changelog/11272.txt new file mode 100644 index 0000000000..e93200d578 --- /dev/null +++ b/.changelog/11272.txt @@ -0,0 +1,6 @@ +```release-note:enhancement +container: added `insecure_kubelet_readonly_port_enabled` to `node_pool.node_config.kubelet_config` and `node_config.kubelet_config` in `google_container_node_pool` resource. +``` +```release-note:enhancement +container: added `insecure_kubelet_readonly_port_enabled` to `node_pool_defaults.node_config_defaults`, `node_pool.node_config.kubelet_config`, and `node_config.kubelet_config` in `google_container_cluster` resource. +``` \ No newline at end of file diff --git a/google-beta/services/container/node_config.go b/google-beta/services/container/node_config.go index 58c92427a7..2938daf562 100644 --- a/google-beta/services/container/node_config.go +++ b/google-beta/services/container/node_config.go @@ -73,6 +73,18 @@ func schemaContainerdConfig() *schema.Schema { } } +// Note: this is a bool internally, but implementing as an enum internally to +// make it easier to accept API level defaults. +func schemaInsecureKubeletReadonlyPortEnabled() *schema.Schema { + return &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "Controls whether the kubelet read-only port is enabled. It is strongly recommended to set this to `FALSE`. Possible values: `TRUE`, `FALSE`.", + ValidateFunc: validation.StringInSlice([]string{"FALSE", "TRUE"}, false), + } +} + func schemaLoggingVariant() *schema.Schema { return &schema.Schema{ Type: schema.TypeString, @@ -586,6 +598,7 @@ func schemaNodeConfig() *schema.Schema { Optional: true, Description: `Set the CPU CFS quota period value 'cpu.cfs_period_us'.`, }, + "insecure_kubelet_readonly_port_enabled": schemaInsecureKubeletReadonlyPortEnabled(), "pod_pids_limit": { Type: schema.TypeInt, Optional: true, @@ -766,6 +779,12 @@ func expandNodeConfigDefaults(configured interface{}) *container.NodeConfigDefau nodeConfigDefaults := &container.NodeConfigDefaults{} nodeConfigDefaults.ContainerdConfig = expandContainerdConfig(config["containerd_config"]) + if v, ok := config["insecure_kubelet_readonly_port_enabled"]; ok { + nodeConfigDefaults.NodeKubeletConfig = &container.NodeKubeletConfig{ + InsecureKubeletReadonlyPortEnabled: expandInsecureKubeletReadonlyPortEnabled(v), + ForceSendFields: []string{"InsecureKubeletReadonlyPortEnabled"}, + } + } if variant, ok := config["logging_variant"]; ok { nodeConfigDefaults.LoggingConfig = &container.NodePoolLoggingConfig{ VariantConfig: &container.LoggingVariantConfig{ @@ -1115,6 +1134,13 @@ func expandWorkloadMetadataConfig(v interface{}) *container.WorkloadMetadataConf return wmc } +func expandInsecureKubeletReadonlyPortEnabled(v interface{}) bool { + if v == "TRUE" { + return true + } + return false +} + func expandKubeletConfig(v interface{}) *container.NodeKubeletConfig { if v == nil { return nil @@ -1135,6 +1161,10 @@ func expandKubeletConfig(v interface{}) *container.NodeKubeletConfig { if cpuCfsQuotaPeriod, ok := cfg["cpu_cfs_quota_period"]; ok { kConfig.CpuCfsQuotaPeriod = cpuCfsQuotaPeriod.(string) } + if insecureKubeletReadonlyPortEnabled, ok := cfg["insecure_kubelet_readonly_port_enabled"]; ok { + kConfig.InsecureKubeletReadonlyPortEnabled = expandInsecureKubeletReadonlyPortEnabled(insecureKubeletReadonlyPortEnabled) + kConfig.ForceSendFields = append(kConfig.ForceSendFields, "InsecureKubeletReadonlyPortEnabled") + } if podPidsLimit, ok := cfg["pod_pids_limit"]; ok { kConfig.PodPidsLimit = int64(podPidsLimit.(int)) } @@ -1341,6 +1371,8 @@ func flattenNodeConfigDefaults(c *container.NodeConfigDefaults) []map[string]int result[0]["containerd_config"] = flattenContainerdConfig(c.ContainerdConfig) + result[0]["insecure_kubelet_readonly_port_enabled"] = flattenInsecureKubeletReadonlyPortEnabled(c.NodeKubeletConfig) + result[0]["logging_variant"] = flattenLoggingVariant(c.LoggingConfig) result[0]["gcfs_config"] = flattenGcfsConfig(c.GcfsConfig) @@ -1524,6 +1556,14 @@ func flattenSecondaryBootDisks(c []*container.SecondaryBootDisk) []map[string]in return result } +func flattenInsecureKubeletReadonlyPortEnabled(c *container.NodeKubeletConfig) string { + // Convert bool from the API to the enum values used internally + if c != nil && c.InsecureKubeletReadonlyPortEnabled { + return "TRUE" + } + return "FALSE" +} + func flattenLoggingVariant(c *container.NodePoolLoggingConfig) string { variant := "DEFAULT" if c != nil && c.VariantConfig != nil && c.VariantConfig.Variant != "" { @@ -1671,10 +1711,11 @@ func flattenKubeletConfig(c *container.NodeKubeletConfig) []map[string]interface result := []map[string]interface{}{} if c != nil { result = append(result, map[string]interface{}{ - "cpu_cfs_quota": c.CpuCfsQuota, - "cpu_cfs_quota_period": c.CpuCfsQuotaPeriod, - "cpu_manager_policy": c.CpuManagerPolicy, - "pod_pids_limit": c.PodPidsLimit, + "cpu_cfs_quota": c.CpuCfsQuota, + "cpu_cfs_quota_period": c.CpuCfsQuotaPeriod, + "cpu_manager_policy": c.CpuManagerPolicy, + "insecure_kubelet_readonly_port_enabled": flattenInsecureKubeletReadonlyPortEnabled(c), + "pod_pids_limit": c.PodPidsLimit, }) } return result diff --git a/google-beta/services/container/resource_container_cluster.go b/google-beta/services/container/resource_container_cluster.go index 12e296f181..56d3724aaf 100644 --- a/google-beta/services/container/resource_container_cluster.go +++ b/google-beta/services/container/resource_container_cluster.go @@ -153,9 +153,10 @@ func clusterSchemaNodePoolDefaults() *schema.Schema { MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "containerd_config": schemaContainerdConfig(), - "gcfs_config": schemaGcfsConfig(false), - "logging_variant": schemaLoggingVariant(), + "containerd_config": schemaContainerdConfig(), + "gcfs_config": schemaGcfsConfig(false), + "insecure_kubelet_readonly_port_enabled": schemaInsecureKubeletReadonlyPortEnabled(), + "logging_variant": schemaLoggingVariant(), }, }, }, @@ -3772,6 +3773,60 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er log.Printf("[INFO] GKE cluster %s: image type has been updated to %s", d.Id(), it) } + + if d.HasChange("node_config.0.kubelet_config") { + + defaultPool := "default-pool" + + timeout := d.Timeout(schema.TimeoutCreate) + + nodePoolInfo, err := extractNodePoolInformationFromCluster(d, config, clusterName) + if err != nil { + return err + } + + // Acquire write-lock on nodepool. + npLockKey := nodePoolInfo.nodePoolLockKey(defaultPool) + + // Note: probably long term this should be handled broadly for all the + // items in kubelet_config in a simpler / DRYer way. + // See b/361634104 + if d.HasChange("node_config.0.kubelet_config.0.insecure_kubelet_readonly_port_enabled") { + it := d.Get("node_config.0.kubelet_config.0.insecure_kubelet_readonly_port_enabled").(string) + + // While we're getting the value from the drepcated field in + // node_config.kubelet_config, the actual setting that needs to be updated + // is on the default nodepool. + req := &container.UpdateNodePoolRequest{ + Name: defaultPool, + KubeletConfig: &container.NodeKubeletConfig{ + InsecureKubeletReadonlyPortEnabled: expandInsecureKubeletReadonlyPortEnabled(it), + ForceSendFields: []string{"InsecureKubeletReadonlyPortEnabled"}, + }, + } + + updateF := func() error { + clusterNodePoolsUpdateCall := config.NewContainerClient(userAgent).Projects.Locations.Clusters.NodePools.Update(nodePoolInfo.fullyQualifiedName(defaultPool), req) + if config.UserProjectOverride { + clusterNodePoolsUpdateCall.Header().Add("X-Goog-User-Project", nodePoolInfo.project) + } + op, err := clusterNodePoolsUpdateCall.Do() + if err != nil { + return err + } + + // Wait until it's updated + return ContainerOperationWait(config, op, nodePoolInfo.project, nodePoolInfo.location, + "updating GKE node pool insecure_kubelet_readonly_port_enabled", userAgent, timeout) + } + + if err := retryWhileIncompatibleOperation(timeout, npLockKey, updateF); err != nil { + return err + } + + log.Printf("[INFO] GKE cluster %s: default-pool setting for insecure_kubelet_readonly_port_enabled updated to %s", d.Id(), it) + } + } } if d.HasChange("notification_config") { @@ -4194,6 +4249,28 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er } } + if d.HasChange("node_pool_defaults") && d.HasChange("node_pool_defaults.0.node_config_defaults.0.insecure_kubelet_readonly_port_enabled") { + if v, ok := d.GetOk("node_pool_defaults.0.node_config_defaults.0.insecure_kubelet_readonly_port_enabled"); ok { + insecureKubeletReadonlyPortEnabled := v.(string) + req := &container.UpdateClusterRequest{ + Update: &container.ClusterUpdate{ + DesiredNodeKubeletConfig: &container.NodeKubeletConfig{ + InsecureKubeletReadonlyPortEnabled: expandInsecureKubeletReadonlyPortEnabled(insecureKubeletReadonlyPortEnabled), + ForceSendFields: []string{"InsecureKubeletReadonlyPortEnabled"}, + }, + }, + } + + updateF := updateFunc(req, "updating GKE cluster desired node pool insecure kubelet readonly port configuration defaults.") + // Call update serially. + if err := transport_tpg.LockedCall(lockKey, updateF); err != nil { + return err + } + + log.Printf("[INFO] GKE cluster %s node pool insecure_kubelet_readonly_port_enabled default has been updated", d.Id()) + } + } + if d.HasChange("node_pool_defaults") && d.HasChange("node_pool_defaults.0.node_config_defaults.0.logging_variant") { if v, ok := d.GetOk("node_pool_defaults.0.node_config_defaults.0.logging_variant"); ok { loggingVariant := v.(string) diff --git a/google-beta/services/container/resource_container_cluster_test.go b/google-beta/services/container/resource_container_cluster_test.go index 922de6a258..354936284b 100644 --- a/google-beta/services/container/resource_container_cluster_test.go +++ b/google-beta/services/container/resource_container_cluster_test.go @@ -9,6 +9,7 @@ import ( "testing" "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/plancheck" "github.com/hashicorp/terraform-plugin-testing/terraform" "github.com/hashicorp/terraform-provider-google-beta/google-beta/acctest" "github.com/hashicorp/terraform-provider-google-beta/google-beta/envvar" @@ -1524,6 +1525,145 @@ func TestAccContainerCluster_withNodeConfig(t *testing.T) { }) } +// This is for node_config.kubelet_config, which affects the default node-pool +// (default-pool) when created via the google_container_cluster resource +func TestAccContainerCluster_withInsecureKubeletReadonlyPortEnabledInNodeConfigUpdates(t *testing.T) { + t.Parallel() + clusterName := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10)) + networkName := acctest.BootstrapSharedTestNetwork(t, "gke-cluster") + subnetworkName := acctest.BootstrapSubnet(t, "gke-cluster", networkName) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckContainerClusterDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccContainerCluster_withInsecureKubeletReadonlyPortEnabledInNodeConfig(clusterName, networkName, subnetworkName, "TRUE"), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + acctest.ExpectNoDelete(), + }, + }, + }, + { + ResourceName: "google_container_cluster.with_insecure_kubelet_readonly_port_enabled_in_node_config", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, + }, + { + Config: testAccContainerCluster_withInsecureKubeletReadonlyPortEnabledInNodeConfig(clusterName, networkName, subnetworkName, "FALSE"), + }, + { + ResourceName: "google_container_cluster.with_insecure_kubelet_readonly_port_enabled_in_node_config", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, + }, + }, + }) +} + +func TestAccContainerCluster_withInsecureKubeletReadonlyPortEnabledInNodePool(t *testing.T) { + t.Parallel() + clusterName := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10)) + nodePoolName := fmt.Sprintf("tf-test-nodepool-%s", acctest.RandString(t, 10)) + networkName := acctest.BootstrapSharedTestNetwork(t, "gke-cluster") + subnetworkName := acctest.BootstrapSubnet(t, "gke-cluster", networkName) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckContainerClusterDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccContainerCluster_withInsecureKubeletReadonlyPortEnabledInNodePool(clusterName, nodePoolName, networkName, subnetworkName, "TRUE"), + }, + { + ResourceName: "google_container_cluster.with_insecure_kubelet_readonly_port_enabled_in_node_pool", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, + }, + }, + }) +} + +// This is for `node_pool_defaults.node_config_defaults` - the default settings +// for newly created nodepools +func TestAccContainerCluster_withInsecureKubeletReadonlyPortEnabledDefaultsUpdates(t *testing.T) { + t.Parallel() + clusterName := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10)) + networkName := acctest.BootstrapSharedTestNetwork(t, "gke-cluster") + subnetworkName := acctest.BootstrapSubnet(t, "gke-cluster", networkName) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckContainerClusterDestroyProducer(t), + Steps: []resource.TestStep{ + // Test API default (no value set in config) first + { + Config: testAccContainerCluster_withInsecureKubeletReadonlyPortEnabledDefaultsUpdateBaseline(clusterName, networkName, subnetworkName), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + acctest.ExpectNoDelete(), + }, + }, + }, + { + ResourceName: "google_container_cluster.with_insecure_kubelet_readonly_port_enabled_node_pool_update", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, + }, + { + Config: testAccContainerCluster_withInsecureKubeletReadonlyPortEnabledDefaultsUpdate(clusterName, networkName, subnetworkName, "TRUE"), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + acctest.ExpectNoDelete(), + }, + }, + }, + { + ResourceName: "google_container_cluster.with_insecure_kubelet_readonly_port_enabled_node_pool_update", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, + }, + { + Config: testAccContainerCluster_withInsecureKubeletReadonlyPortEnabledDefaultsUpdate(clusterName, networkName, subnetworkName, "FALSE"), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + acctest.ExpectNoDelete(), + }, + }, + }, + { + ResourceName: "google_container_cluster.with_insecure_kubelet_readonly_port_enabled_node_pool_update", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, + }, + { + Config: testAccContainerCluster_withInsecureKubeletReadonlyPortEnabledDefaultsUpdate(clusterName, networkName, subnetworkName, "TRUE"), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + acctest.ExpectNoDelete(), + }, + }, + }, + { + ResourceName: "google_container_cluster.with_insecure_kubelet_readonly_port_enabled_node_pool_update", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, + }, + }, + }) +} + func TestAccContainerCluster_withLoggingVariantInNodeConfig(t *testing.T) { t.Parallel() clusterName := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10)) @@ -6435,6 +6575,84 @@ resource "google_container_cluster" "with_node_config" { `, clusterName, networkName, subnetworkName) } +func testAccContainerCluster_withInsecureKubeletReadonlyPortEnabledInNodeConfig(clusterName, networkName, subnetworkName, insecureKubeletReadonlyPortEnabled string) string { + return fmt.Sprintf(` +resource "google_container_cluster" "with_insecure_kubelet_readonly_port_enabled_in_node_config" { + name = "%s" + location = "us-central1-f" + initial_node_count = 1 + + node_config { + kubelet_config { + # Must be set when kubelet_config is, but causes permadrift unless set to + # undocumented empty value + cpu_manager_policy = "" + insecure_kubelet_readonly_port_enabled = "%s" + } + } + deletion_protection = false + network = "%s" + subnetwork = "%s" +} +`, clusterName, insecureKubeletReadonlyPortEnabled, networkName, subnetworkName) +} + +func testAccContainerCluster_withInsecureKubeletReadonlyPortEnabledInNodePool(clusterName, nodePoolName, networkName, subnetworkName, insecureKubeletReadonlyPortEnabled string) string { + return fmt.Sprintf(` +resource "google_container_cluster" "with_insecure_kubelet_readonly_port_enabled_in_node_pool" { + name = "%s" + location = "us-central1-f" + + node_pool { + name = "%s" + initial_node_count = 1 + node_config { + kubelet_config { + cpu_manager_policy = "static" + insecure_kubelet_readonly_port_enabled = "%s" + } + } + } + deletion_protection = false + network = "%s" + subnetwork = "%s" +} +`, clusterName, nodePoolName, insecureKubeletReadonlyPortEnabled, networkName, subnetworkName) +} + +func testAccContainerCluster_withInsecureKubeletReadonlyPortEnabledDefaultsUpdateBaseline(clusterName, networkName, subnetworkName string) string { + return fmt.Sprintf(` +resource "google_container_cluster" "with_insecure_kubelet_readonly_port_enabled_node_pool_update" { + name = "%s" + location = "us-central1-f" + initial_node_count = 1 + + deletion_protection = false + network = "%s" + subnetwork = "%s" +} +`, clusterName, networkName, subnetworkName) +} + +func testAccContainerCluster_withInsecureKubeletReadonlyPortEnabledDefaultsUpdate(clusterName, networkName, subnetworkName, insecureKubeletReadonlyPortEnabled string) string { + return fmt.Sprintf(` +resource "google_container_cluster" "with_insecure_kubelet_readonly_port_enabled_node_pool_update" { + name = "%s" + location = "us-central1-f" + initial_node_count = 1 + + node_pool_defaults { + node_config_defaults { + insecure_kubelet_readonly_port_enabled = "%s" + } + } + deletion_protection = false + network = "%s" + subnetwork = "%s" +} +`, clusterName, insecureKubeletReadonlyPortEnabled, networkName, subnetworkName) +} + func testAccContainerCluster_withLoggingVariantInNodeConfig(clusterName, loggingVariant, networkName, subnetworkName string) string { return fmt.Sprintf(` resource "google_container_cluster" "with_logging_variant_in_node_config" { diff --git a/google-beta/services/container/resource_container_node_pool_test.go b/google-beta/services/container/resource_container_node_pool_test.go index eb0cec9d44..7348bc239c 100644 --- a/google-beta/services/container/resource_container_node_pool_test.go +++ b/google-beta/services/container/resource_container_node_pool_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/plancheck" "github.com/hashicorp/terraform-plugin-testing/terraform" "github.com/hashicorp/terraform-provider-google-beta/google-beta/acctest" "github.com/hashicorp/terraform-provider-google-beta/google-beta/envvar" @@ -526,10 +527,17 @@ func TestAccContainerNodePool_withKubeletConfig(t *testing.T) { CheckDestroy: testAccCheckContainerClusterDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccContainerNodePool_withKubeletConfig(cluster, np, "static", "100ms", networkName, subnetworkName, true, 2048), + Config: testAccContainerNodePool_withKubeletConfig(cluster, np, "static", "100ms", networkName, subnetworkName, "TRUE", true, 2048), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + acctest.ExpectNoDelete(), + }, + }, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("google_container_node_pool.with_kubelet_config", "node_config.0.kubelet_config.0.cpu_cfs_quota", "true"), + resource.TestCheckResourceAttr("google_container_node_pool.with_kubelet_config", + "node_config.0.kubelet_config.0.insecure_kubelet_readonly_port_enabled", "TRUE"), resource.TestCheckResourceAttr("google_container_node_pool.with_kubelet_config", "node_config.0.kubelet_config.0.pod_pids_limit", "2048"), ), @@ -540,10 +548,17 @@ func TestAccContainerNodePool_withKubeletConfig(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccContainerNodePool_withKubeletConfig(cluster, np, "", "", networkName, subnetworkName, false, 1024), + Config: testAccContainerNodePool_withKubeletConfig(cluster, np, "", "", networkName, subnetworkName, "FALSE", false, 1024), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + acctest.ExpectNoDelete(), + }, + }, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("google_container_node_pool.with_kubelet_config", "node_config.0.kubelet_config.0.cpu_cfs_quota", "false"), + resource.TestCheckResourceAttr("google_container_node_pool.with_kubelet_config", + "node_config.0.kubelet_config.0.insecure_kubelet_readonly_port_enabled", "FALSE"), ), }, { @@ -571,7 +586,7 @@ func TestAccContainerNodePool_withInvalidKubeletCpuManagerPolicy(t *testing.T) { CheckDestroy: testAccCheckContainerClusterDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccContainerNodePool_withKubeletConfig(cluster, np, "dontexist", "100us", networkName, subnetworkName, true, 1024), + Config: testAccContainerNodePool_withKubeletConfig(cluster, np, "dontexist", "100us", networkName, subnetworkName, "TRUE", false, 1024), ExpectError: regexp.MustCompile(`.*to be one of \["?static"? "?none"? "?"?\].*`), }, }, @@ -3090,7 +3105,7 @@ resource "google_container_node_pool" "with_sandbox_config" { `, cluster, networkName, subnetworkName, np) } -func testAccContainerNodePool_withKubeletConfig(cluster, np, policy, period, networkName, subnetworkName string, quota bool, podPidsLimit int) string { +func testAccContainerNodePool_withKubeletConfig(cluster, np, policy, period, networkName, subnetworkName, insecureKubeletReadonlyPortEnabled string, quota bool, podPidsLimit int) string { return fmt.Sprintf(` data "google_container_engine_versions" "central1a" { location = "us-central1-a" @@ -3116,10 +3131,11 @@ resource "google_container_node_pool" "with_kubelet_config" { node_config { image_type = "COS_CONTAINERD" kubelet_config { - cpu_manager_policy = %q - cpu_cfs_quota = %v - cpu_cfs_quota_period = %q - pod_pids_limit = %d + cpu_manager_policy = %q + cpu_cfs_quota = %v + cpu_cfs_quota_period = %q + insecure_kubelet_readonly_port_enabled = "%s" + pod_pids_limit = %d } oauth_scopes = [ "https://www.googleapis.com/auth/logging.write", @@ -3128,7 +3144,7 @@ resource "google_container_node_pool" "with_kubelet_config" { logging_variant = "DEFAULT" } } -`, cluster, networkName, subnetworkName, np, policy, quota, period, podPidsLimit) +`, cluster, networkName, subnetworkName, np, policy, quota, period, insecureKubeletReadonlyPortEnabled, podPidsLimit) } func testAccContainerNodePool_withLinuxNodeConfig(cluster, np, tcpMem, networkName, subnetworkName string) string { diff --git a/website/docs/r/container_cluster.html.markdown b/website/docs/r/container_cluster.html.markdown index b410e60da8..15c610a3d8 100644 --- a/website/docs/r/container_cluster.html.markdown +++ b/website/docs/r/container_cluster.html.markdown @@ -1105,6 +1105,8 @@ node_pool_auto_config { The `node_config_defaults` block supports: +* `insecure_kubelet_readonly_port_enabled` (Optional) Controls whether the kubelet read-only port is enabled for newly created node pools in the cluster. It is strongly recommended to set this to `FALSE`. Possible values: `TRUE`, `FALSE`. + * `logging_variant` (Optional) The type of logging agent that is deployed by default for newly created node pools in the cluster. Valid values include DEFAULT and MAX_THROUGHPUT. See [Increasing logging agent throughput](https://cloud.google.com/stackdriver/docs/solutions/gke/managing-logs#throughput) for more information. * `gcfs_config` (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html)) The default Google Container Filesystem (GCFS) configuration at the cluster level. e.g. enable [image streaming](https://cloud.google.com/kubernetes-engine/docs/how-to/image-streaming) across all the node pools within the cluster. Structure is [documented below](#nested_gcfs_config). @@ -1296,6 +1298,8 @@ value and accepts an invalid `default` value instead. While this remains true, not specifying the `kubelet_config` block should be the equivalent of specifying `none`. +* `insecure_kubelet_readonly_port_enabled` - (Optional) Controls whether the kubelet read-only port is enabled. It is strongly recommended to set this to `FALSE`. Possible values: `TRUE`, `FALSE`. + * `pod_pids_limit` - (Optional) Controls the maximum number of processes allowed to run in a pod. The value must be greater than or equal to 1024 and less than 4194304. The `linux_node_config` block supports: