-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
google_container_cluster.node_pool
should be a Set.
#780
Comments
So it turns out that because of the way the code is structured, this isn't actually possible right now. We allow generating a random name at node pool creation time, which is during apply. This means that at plan time, we don't know what the name will hash to. We can't just use a random value for plan (and then let apply decide what it'll actually be) because Terraform has safeguards to make sure the diffs for plan and apply match. One fix would be to make The alternative is to just go ahead with #779, which would allow having the feature sooner, but with a whole bunch of caveats about using it correctly. Another point to keep in mind is that adding/removing node pools from a cluster is already possible with the I'd love to get some feedback from anyone who was hoping to be able to add/remove nodepools from a
Paging a few people who have been active in issues/PRs relating to node pools: @sl1pm4t @davidquarles @rochdev @drzero42 @glindste @georgespalding @burdiyan @birdayz |
Bummer! My 2¢:
|
Thanks for taking a thorough look at this!
|
Great to see work being done here :)
I doubt anybody actually wants to remove the default-pool. My guess from my own use-case is that users want to be able to specify the configuration of the default-pool as richly as can be done for any additional node pools that are added. Just spitballing here, but based on my current level of experience with this subject, maybe instead of having some of the attributes from node_pool/node_config exist directly on |
Totally stoked about this, by the way! |
Here is how I do it right now with terraform-provider-google 1.2.0:
|
Sorry for the late response
The current functionality is working for us, and isn't causing any pain - but this is a greenfield deployment and we haven't attempting any the upgrade / maintenance scenarios yet.
We just recently moved to using the name_prefix field, in conjunction with
Currently 2 - 3 pools per cluster.
We exclusively use the separate node pool resource, for the flexibility. |
@danawillow is this still part of the |
Removed, thanks. |
Any updates on this one? Since milestone was removed it's unclear what is the plan for it. |
We're not planning on doing anything with it right now. Here's the very long technical writeup of why it just can't be done. If you need to be able to add/remove node pools, do it via the separate node pool resource. Why we can't convert Node Pools to be a setBackgroundNode pools can currently be created in two ways: via the Currently, if a user attempts to add or remove a node pool on the cluster resource, it'll recreate the cluster. This document outlines the different approaches attempted to allow adding/removing node pools from the cluster, eventually culminating in a decision not to do so. The criteria for a successful solution are:
Attempt 1: Leave the Node Pools as a listThis work was started in #779. Leaving the node pools as a list allows adding to / removing from the end of the list. However, if you try to modify the middle of the list, Terraform tries to merge whatever was in that spot before with whatever is in that spot now. For example, take the config: resource "google_container_cluster" "is-780" {
name = "is-780"
zone = "us-central1-a"
node_pool {
name = "first"
initial_node_count = 1
node_config {
disk_size_gb = 50
}
}
} This will lead to a state that has the following in it:
Now, I update my config to add a second node pool: resource "google_container_cluster" "is-780" {
name = "is-780"
zone = "us-central1-a"
node_pool {
name = "second"
initial_node_count = 2
}
node_pool {
name = "first"
initial_node_count = 1
node_config {
disk_size_gb = 50
}
}
} The plan output, though a bit confusing, looks reasonable. It's shifting the first node pool over to the second slot, and putting the second node pool in at the beginning:
However, because of the way that Terraform merges config and state, doing a
Since we can't tell for sure what the correct value is for all of the fields, we can't leave the Node Pools as a list. Attempt 2: Make the Node Pools a Set using the default SchemaSetFuncLet's take that same config from earlier: resource "google_container_cluster" "is-780" {
name = "is-780"
zone = "us-central1-a"
node_pool {
name = "first"
initial_node_count = 1
node_config {
disk_size_gb = 50
}
}
} Our state now has the following in it:
Unfortunately, if we run terraform plan without changing anything, we get this output:
This plan output shows that the hash is different when we run plan than when we write the value to state. This happens because of fields that are both Optional and Computed. Take Attempt 3: Use a custom SchemaSetFuncThis has the same problems as attempt 2. If our custom function includes fields that are Optional+Computed, the hashes will change between when we write to state and when we run our next plan. If we don't include these fields, then we can't detect drift in them if they are set by a user. Attempt 4: Use customizediff to diff based on the fields instead of a hash functionThe issue with using a SchemaSetFunc for diffing is that our resource has a different value when we pass it into the hash function at the time we write state and the time we do our next plan. If we can diff on the resource only at plan time and not worry about the hash, then we don't have that same problem. We have the ability to diff on the resource at plan time by using customizediff. If we go through every field, we can check if the values in state and the new values are equivalent, ignoring changes to fields that are optional+computed and don't have a value set in the new config. If we introduce a new field that we change the value of if we find a diff, then we can make that field into our hash and remove everything else from the SchemaSetFunc. However, this approach fails when we try to diff two fields that have a DiffSuppressFunc. These functions take a func taintDiffSuppress(k, old, new string, d *schema.ResourceData) bool {
if strings.HasSuffix(k, "#") {
oldCount, oldErr := strconv.Atoi(old)
newCount, newErr := strconv.Atoi(new)
// If either of them isn't a number somehow, or if there's one that we didn't have before.
return oldErr != nil || newErr != nil || oldCount == newCount+1
} else {
lastDot := strings.LastIndex(k, ".")
taintKey := d.Get(k[:lastDot] + ".key").(string)
if taintKey == "nvidia.com/gpu" {
return true
} else {
return false
}
}
} This DiffSuppress needs to suppress the diff on an entire nested object based on the value of one of its fields, so it needs the ability to read a specific field out of the This gist contains the code for this attempt as well as some commented-out code from other attempts. |
I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. If you feel this issue should be reopened, we encourage creating a new issue linking back to this one for added context. If you feel I made an error 🤖 🙉 , please reach out to my human friends 👉 hashibot-feedback@hashicorp.com. Thanks! |
As mentioned in both #665 and #779, adding/removing node pools will be easier to do if it's a Set. Though it's possible to add/remove node pools in a List, it ends up not being possible to add node pools anywhere but the end of the list, and also leads to unintuitive plans, where attributes are showing as being changed rather than just moved elsewhere in the list.
We can hash on the name of the node pool since those are unique in a cluster, though we'll probably have to add some special handling for node pools that are specified using a name prefix or not specified at all (left to be random).
The text was updated successfully, but these errors were encountered: