Skip to content

Commit 87f7166

Browse files
Add blue green upgrade settings. (#6618) (#12984)
fixes #12045 Signed-off-by: Modular Magician <[email protected]> Signed-off-by: Modular Magician <[email protected]>
1 parent b42214f commit 87f7166

File tree

4 files changed

+264
-26
lines changed

4 files changed

+264
-26
lines changed

.changelog/6618.txt

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
```release-note:enhancement
2+
container: added field `strategy` to `google_container_node_pool`
3+
```
4+
```release-note:enhancement
5+
container: added field `blue_green_settings` to `google_container_node_pool`
6+
```

google/resource_container_node_pool.go

+194-14
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,53 @@ func resourceContainerNodePool() *schema.Resource {
7474
}
7575
}
7676

77+
var schemaBlueGreenSettings = &schema.Schema{
78+
Type: schema.TypeList,
79+
Optional: true,
80+
Computed: true,
81+
MaxItems: 1,
82+
Elem: &schema.Resource{
83+
Schema: map[string]*schema.Schema{
84+
"standard_rollout_policy": {
85+
Type: schema.TypeList,
86+
Required: true,
87+
MaxItems: 1,
88+
Description: `Standard rollout policy is the default policy for blue-green.`,
89+
Elem: &schema.Resource{
90+
Schema: map[string]*schema.Schema{
91+
"batch_percentage": {
92+
Type: schema.TypeFloat,
93+
Optional: true,
94+
Computed: true,
95+
Description: `Percentage of the blue pool nodes to drain in a batch.`,
96+
ValidateFunc: validation.FloatBetween(0.0, 1.0),
97+
},
98+
"batch_node_count": {
99+
Type: schema.TypeInt,
100+
Optional: true,
101+
Computed: true,
102+
Description: `Number of blue nodes to drain in a batch.`,
103+
},
104+
"batch_soak_duration": {
105+
Type: schema.TypeString,
106+
Optional: true,
107+
Computed: true,
108+
Description: `Soak time after each batch gets drained.`,
109+
},
110+
},
111+
},
112+
},
113+
"node_pool_soak_duration": {
114+
Type: schema.TypeString,
115+
Optional: true,
116+
Computed: true,
117+
Description: `Time needed after draining entire blue pool. After this period, blue pool will be cleaned up.`,
118+
},
119+
},
120+
},
121+
Description: `Settings for BlueGreen node pool upgrade.`,
122+
}
123+
77124
var schemaNodePool = map[string]*schema.Schema{
78125
"autoscaling": {
79126
Type: schema.TypeList,
@@ -146,17 +193,29 @@ var schemaNodePool = map[string]*schema.Schema{
146193
Schema: map[string]*schema.Schema{
147194
"max_surge": {
148195
Type: schema.TypeInt,
149-
Required: true,
196+
Optional: true,
197+
Computed: true,
150198
ValidateFunc: validation.IntAtLeast(0),
151199
Description: `The number of additional nodes that can be added to the node pool during an upgrade. Increasing max_surge raises the number of nodes that can be upgraded simultaneously. Can be set to 0 or greater.`,
152200
},
153201

154202
"max_unavailable": {
155203
Type: schema.TypeInt,
156-
Required: true,
204+
Optional: true,
205+
Computed: true,
157206
ValidateFunc: validation.IntAtLeast(0),
158207
Description: `The number of nodes that can be simultaneously unavailable during an upgrade. Increasing max_unavailable raises the number of nodes that can be upgraded in parallel. Can be set to 0 or greater.`,
159208
},
209+
210+
"strategy": {
211+
Type: schema.TypeString,
212+
Optional: true,
213+
Default: "SURGE",
214+
ValidateFunc: validation.StringInSlice([]string{"SURGE", "BLUE_GREEN"}, false),
215+
Description: `Update strategy for the given nodepool.`,
216+
},
217+
218+
"blue_green_settings": schemaBlueGreenSettings,
160219
},
161220
},
162221
},
@@ -749,18 +808,103 @@ func expandNodePool(d *schema.ResourceData, prefix string) (*container.NodePool,
749808
upgradeSettingsConfig := v.([]interface{})[0].(map[string]interface{})
750809
np.UpgradeSettings = &container.UpgradeSettings{}
751810

752-
if v, ok := upgradeSettingsConfig["max_surge"]; ok {
753-
np.UpgradeSettings.MaxSurge = int64(v.(int))
811+
if v, ok := upgradeSettingsConfig["strategy"]; ok {
812+
np.UpgradeSettings.Strategy = v.(string)
754813
}
755814

756-
if v, ok := upgradeSettingsConfig["max_unavailable"]; ok {
757-
np.UpgradeSettings.MaxUnavailable = int64(v.(int))
815+
if d.HasChange(prefix + "upgrade_settings.0.max_surge") {
816+
if np.UpgradeSettings.Strategy != "SURGE" {
817+
return nil, fmt.Errorf("Surge upgrade settings may not be changed when surge strategy is not enabled")
818+
}
819+
if v, ok := upgradeSettingsConfig["max_surge"]; ok {
820+
np.UpgradeSettings.MaxSurge = int64(v.(int))
821+
}
822+
}
823+
824+
if d.HasChange(prefix + "upgrade_settings.0.max_unavailable") {
825+
if np.UpgradeSettings.Strategy != "SURGE" {
826+
return nil, fmt.Errorf("Surge upgrade settings may not be changed when surge strategy is not enabled")
827+
}
828+
if v, ok := upgradeSettingsConfig["max_unavailable"]; ok {
829+
np.UpgradeSettings.MaxUnavailable = int64(v.(int))
830+
}
831+
}
832+
833+
if v, ok := upgradeSettingsConfig["blue_green_settings"]; ok && len(v.([]interface{})) > 0 {
834+
blueGreenSettingsConfig := v.([]interface{})[0].(map[string]interface{})
835+
np.UpgradeSettings.BlueGreenSettings = &container.BlueGreenSettings{}
836+
837+
if np.UpgradeSettings.Strategy != "BLUE_GREEN" {
838+
return nil, fmt.Errorf("Blue-green upgrade settings may not be changed when blue-green strategy is not enabled")
839+
}
840+
841+
if v, ok := blueGreenSettingsConfig["node_pool_soak_duration"]; ok {
842+
np.UpgradeSettings.BlueGreenSettings.NodePoolSoakDuration = v.(string)
843+
}
844+
845+
if v, ok := blueGreenSettingsConfig["standard_rollout_policy"]; ok && len(v.([]interface{})) > 0 {
846+
standardRolloutPolicyConfig := v.([]interface{})[0].(map[string]interface{})
847+
standardRolloutPolicy := &container.StandardRolloutPolicy{}
848+
849+
if v, ok := standardRolloutPolicyConfig["batch_soak_duration"]; ok {
850+
standardRolloutPolicy.BatchSoakDuration = v.(string)
851+
}
852+
if v, ok := standardRolloutPolicyConfig["batch_node_count"]; ok {
853+
standardRolloutPolicy.BatchNodeCount = int64(v.(int))
854+
}
855+
if v, ok := standardRolloutPolicyConfig["batch_percentage"]; ok {
856+
standardRolloutPolicy.BatchPercentage = v.(float64)
857+
}
858+
859+
np.UpgradeSettings.BlueGreenSettings.StandardRolloutPolicy = standardRolloutPolicy
860+
}
758861
}
759862
}
760863

761864
return np, nil
762865
}
763866

867+
func flattenNodePoolStandardRolloutPolicy(rp *container.StandardRolloutPolicy) []map[string]interface{} {
868+
if rp == nil {
869+
return nil
870+
}
871+
872+
return []map[string]interface{}{
873+
{
874+
"batch_node_count": rp.BatchNodeCount,
875+
"batch_percentage": rp.BatchPercentage,
876+
"batch_soak_duration": rp.BatchSoakDuration,
877+
},
878+
}
879+
}
880+
881+
func flattenNodePoolBlueGreenSettings(bg *container.BlueGreenSettings) []map[string]interface{} {
882+
if bg == nil {
883+
return nil
884+
}
885+
return []map[string]interface{}{
886+
{
887+
"node_pool_soak_duration": bg.NodePoolSoakDuration,
888+
"standard_rollout_policy": flattenNodePoolStandardRolloutPolicy(bg.StandardRolloutPolicy),
889+
},
890+
}
891+
}
892+
893+
func flattenNodePoolUpgradeSettings(us *container.UpgradeSettings) []map[string]interface{} {
894+
if us == nil {
895+
return nil
896+
}
897+
898+
upgradeSettings := make(map[string]interface{})
899+
900+
upgradeSettings["blue_green_settings"] = flattenNodePoolBlueGreenSettings(us.BlueGreenSettings)
901+
upgradeSettings["max_surge"] = us.MaxSurge
902+
upgradeSettings["max_unavailable"] = us.MaxUnavailable
903+
904+
upgradeSettings["strategy"] = us.Strategy
905+
return []map[string]interface{}{upgradeSettings}
906+
}
907+
764908
func flattenNodePool(d *schema.ResourceData, config *Config, np *container.NodePool, prefix string) (map[string]interface{}, error) {
765909
userAgent, err := generateUserAgentString(d, config.userAgent)
766910
if err != nil {
@@ -835,12 +979,7 @@ func flattenNodePool(d *schema.ResourceData, config *Config, np *container.NodeP
835979
}
836980

837981
if np.UpgradeSettings != nil {
838-
nodePool["upgrade_settings"] = []map[string]interface{}{
839-
{
840-
"max_surge": np.UpgradeSettings.MaxSurge,
841-
"max_unavailable": np.UpgradeSettings.MaxUnavailable,
842-
},
843-
}
982+
nodePool["upgrade_settings"] = flattenNodePoolUpgradeSettings(np.UpgradeSettings)
844983
} else {
845984
delete(nodePool, "upgrade_settings")
846985
}
@@ -1165,8 +1304,49 @@ func nodePoolUpdate(d *schema.ResourceData, meta interface{}, nodePoolInfo *Node
11651304
upgradeSettings := &container.UpgradeSettings{}
11661305
if v, ok := d.GetOk(prefix + "upgrade_settings"); ok {
11671306
upgradeSettingsConfig := v.([]interface{})[0].(map[string]interface{})
1168-
upgradeSettings.MaxSurge = int64(upgradeSettingsConfig["max_surge"].(int))
1169-
upgradeSettings.MaxUnavailable = int64(upgradeSettingsConfig["max_unavailable"].(int))
1307+
upgradeSettings.Strategy = upgradeSettingsConfig["strategy"].(string)
1308+
1309+
if d.HasChange(prefix + "upgrade_settings.0.max_surge") {
1310+
if upgradeSettings.Strategy != "SURGE" {
1311+
return fmt.Errorf("Surge upgrade settings may not be changed when surge strategy is not enabled")
1312+
}
1313+
if v, ok := upgradeSettingsConfig["max_surge"]; ok {
1314+
upgradeSettings.MaxSurge = int64(v.(int))
1315+
}
1316+
}
1317+
1318+
if d.HasChange(prefix + "upgrade_settings.0.max_unavailable") {
1319+
if upgradeSettings.Strategy != "SURGE" {
1320+
return fmt.Errorf("Surge upgrade settings may not be changed when surge strategy is not enabled")
1321+
}
1322+
if v, ok := upgradeSettingsConfig["max_unavailable"]; ok {
1323+
upgradeSettings.MaxUnavailable = int64(v.(int))
1324+
}
1325+
}
1326+
1327+
if d.HasChange(prefix + "upgrade_settings.0.blue_green_settings") {
1328+
if upgradeSettings.Strategy != "BLUE_GREEN" {
1329+
return fmt.Errorf("Blue-green upgrade settings may not be changed when blue-green strategy is not enabled")
1330+
}
1331+
1332+
blueGreenSettings := &container.BlueGreenSettings{}
1333+
blueGreenSettingsConfig := upgradeSettingsConfig["blue_green_settings"].([]interface{})[0].(map[string]interface{})
1334+
blueGreenSettings.NodePoolSoakDuration = blueGreenSettingsConfig["node_pool_soak_duration"].(string)
1335+
1336+
if v, ok := blueGreenSettingsConfig["standard_rollout_policy"]; ok && len(v.([]interface{})) > 0 {
1337+
standardRolloutPolicy := &container.StandardRolloutPolicy{}
1338+
standardRolloutPolicyConfig := v.([]interface{})[0].(map[string]interface{})
1339+
standardRolloutPolicy.BatchSoakDuration = standardRolloutPolicyConfig["batch_soak_duration"].(string)
1340+
if v, ok := standardRolloutPolicyConfig["batch_node_count"]; ok {
1341+
standardRolloutPolicy.BatchNodeCount = int64(v.(int))
1342+
}
1343+
if v, ok := standardRolloutPolicyConfig["batch_percentage"]; ok {
1344+
standardRolloutPolicy.BatchPercentage = v.(float64)
1345+
}
1346+
blueGreenSettings.StandardRolloutPolicy = standardRolloutPolicy
1347+
}
1348+
upgradeSettings.BlueGreenSettings = blueGreenSettings
1349+
}
11701350
}
11711351
req := &container.UpdateNodePoolRequest{
11721352
UpgradeSettings: upgradeSettings,

google/resource_container_node_pool_test.go

+46-8
Original file line numberDiff line numberDiff line change
@@ -306,15 +306,31 @@ func TestAccContainerNodePool_withUpgradeSettings(t *testing.T) {
306306
CheckDestroy: testAccCheckContainerClusterDestroyProducer(t),
307307
Steps: []resource.TestStep{
308308
{
309-
Config: testAccContainerNodePool_withUpgradeSettings(cluster, np, 2, 3),
309+
Config: testAccContainerNodePool_withUpgradeSettings(cluster, np, 2, 3, "SURGE", "", 0, 0.0, ""),
310310
},
311311
{
312312
ResourceName: "google_container_node_pool.with_upgrade_settings",
313313
ImportState: true,
314314
ImportStateVerify: true,
315315
},
316316
{
317-
Config: testAccContainerNodePool_withUpgradeSettings(cluster, np, 1, 1),
317+
Config: testAccContainerNodePool_withUpgradeSettings(cluster, np, 1, 1, "SURGE", "", 0, 0.0, ""),
318+
},
319+
{
320+
ResourceName: "google_container_node_pool.with_upgrade_settings",
321+
ImportState: true,
322+
ImportStateVerify: true,
323+
},
324+
{
325+
Config: testAccContainerNodePool_withUpgradeSettings(cluster, np, 0, 0, "BLUE_GREEN", "100s", 1, 0.0, "0s"),
326+
},
327+
{
328+
ResourceName: "google_container_node_pool.with_upgrade_settings",
329+
ImportState: true,
330+
ImportStateVerify: true,
331+
},
332+
{
333+
Config: testAccContainerNodePool_withUpgradeSettings(cluster, np, 0, 0, "BLUE_GREEN", "100s", 0, 0.5, "1s"),
318334
},
319335
{
320336
ResourceName: "google_container_node_pool.with_upgrade_settings",
@@ -1572,7 +1588,32 @@ resource "google_container_node_pool" "with_workload_metadata_config" {
15721588
`, projectID, cluster, np)
15731589
}
15741590

1575-
func testAccContainerNodePool_withUpgradeSettings(clusterName string, nodePoolName string, maxSurge int, maxUnavailable int) string {
1591+
func makeUpgradeSettings(maxSurge int, maxUnavailable int, strategy string, nodePoolSoakDuration string, batchNodeCount int, batchPercentage float64, batchSoakDuration string) string {
1592+
if strategy == "BLUE_GREEN" {
1593+
return fmt.Sprintf(`
1594+
upgrade_settings {
1595+
strategy = "%s"
1596+
blue_green_settings {
1597+
node_pool_soak_duration = "%s"
1598+
standard_rollout_policy {
1599+
batch_node_count = %d
1600+
batch_percentage = %f
1601+
batch_soak_duration = "%s"
1602+
}
1603+
}
1604+
}
1605+
`, strategy, nodePoolSoakDuration, batchNodeCount, batchPercentage, batchSoakDuration)
1606+
}
1607+
return fmt.Sprintf(`
1608+
upgrade_settings {
1609+
max_surge = %d
1610+
max_unavailable = %d
1611+
strategy = "%s"
1612+
}
1613+
`, maxSurge, maxUnavailable, strategy)
1614+
}
1615+
1616+
func testAccContainerNodePool_withUpgradeSettings(clusterName string, nodePoolName string, maxSurge int, maxUnavailable int, strategy string, nodePoolSoakDuration string, batchNodeCount int, batchPercentage float64, batchSoakDuration string) string {
15761617
return fmt.Sprintf(`
15771618
data "google_container_engine_versions" "central1" {
15781619
location = "us-central1"
@@ -1590,12 +1631,9 @@ resource "google_container_node_pool" "with_upgrade_settings" {
15901631
location = "us-central1"
15911632
cluster = "${google_container_cluster.cluster.name}"
15921633
initial_node_count = 1
1593-
upgrade_settings {
1594-
max_surge = %d
1595-
max_unavailable = %d
1596-
}
1634+
%s
15971635
}
1598-
`, clusterName, nodePoolName, maxSurge, maxUnavailable)
1636+
`, clusterName, nodePoolName, makeUpgradeSettings(maxSurge, maxUnavailable, strategy, nodePoolSoakDuration, batchNodeCount, batchPercentage, batchSoakDuration))
15991637
}
16001638

16011639
func testAccContainerNodePool_withGPU(cluster, np string) string {

website/docs/r/container_node_pool.html.markdown

+18-4
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,7 @@ cluster.
157157
* `project` - (Optional) The ID of the project in which to create the node pool. If blank,
158158
the provider-configured project will be used.
159159

160-
* `upgrade_settings` (Optional) Specify node upgrade settings to change how many nodes GKE attempts to
161-
upgrade at once. The number of nodes upgraded simultaneously is the sum of `max_surge` and `max_unavailable`.
160+
* `upgrade_settings` (Optional) Specify node upgrade settings to change how GKE upgrades nodes.
162161
The maximum number of nodes upgraded simultaneously is limited to 20. Structure is [documented below](#nested_upgrade_settings).
163162

164163
* `version` - (Optional) The Kubernetes version for the nodes in this pool. Note that if this field
@@ -201,16 +200,31 @@ cluster.
201200

202201
<a name="nested_upgrade_settings"></a>The `upgrade_settings` block supports:
203202

204-
* `max_surge` - (Required) The number of additional nodes that can be added to the node pool during
203+
* `max_surge` - (Optional) The number of additional nodes that can be added to the node pool during
205204
an upgrade. Increasing `max_surge` raises the number of nodes that can be upgraded simultaneously.
206205
Can be set to 0 or greater.
207206

208-
* `max_unavailable` - (Required) The number of nodes that can be simultaneously unavailable during
207+
* `max_unavailable` - (Optional) The number of nodes that can be simultaneously unavailable during
209208
an upgrade. Increasing `max_unavailable` raises the number of nodes that can be upgraded in
210209
parallel. Can be set to 0 or greater.
211210

212211
`max_surge` and `max_unavailable` must not be negative and at least one of them must be greater than zero.
213212

213+
* `strategy` - (Default `SURGE`) The upgrade stragey to be used for upgrading the nodes.
214+
215+
* `blue_green_settings` - (Optional) The settings to adjust [blue green upgrades](https://cloud.google.com/kubernetes-engine/docs/concepts/node-pool-upgrade-strategies#blue-green-upgrade-strategy).
216+
Structure is [documented below](#nested_blue_green_settings)
217+
218+
<a name="nested_blue_green_settings"></a>The `blue_green_settings` block supports:
219+
220+
* `standard_rollout_policy` - (Required) Specifies the standard policy settings for blue-green upgrades.
221+
* `batch_percentage` - (Optional) Percentage of the blue pool nodes to drain in a batch.
222+
* `batch_node_count` - (Optional) Number of blue nodes to drain in a batch.
223+
* `batch_soak_duration` - (Optionial) Soak time after each batch gets drained.
224+
225+
* `node_pool_soak_duration` - (Optional) Time needed after draining the entire blue pool.
226+
After this period, the blue pool will be cleaned up.
227+
214228
<a name="nested_placement_policy"></a>The `placement_policy` block supports:
215229

216230
* `type` - (Required) The type of the policy. Supports a single value: COMPACT.

0 commit comments

Comments
 (0)