Open dunefro opened 1 year ago
We at @swisspost have the exact same issue. I analyzed it with some of my colleagues (@hichem-belhocine will ping you @zioproto via MSteams).
We have no auto update mechanism from AKS side in place (Auto Upgrade Type = Disabled), we specify the exact patch version for both:
With TF module version 6.8.0 and the upgrade from 1.25 -> 1.26 a plan looked like this:
Everything went smooth. Then we upgraded to module version 7.5.0 and the upgrade is now triggered via an other TF provider (azapi) and the control plane variable is ignored via a lifecycle { }
block. Ref:
A plan to 1.27 now looks like this (w/ module version 7.5.0):
And of course this will fail as you cannot update the nodepool to a newer version than the control-plane:
│ Error: updating Default Node Pool Agent Pool (Subscription: "<REDACTED>"
│ Resource Group Name: "rg-aks-dev-m98cn0001"
│ Managed Cluster Name: "aks-dev-m98cn0001"
│ Agent Pool Name: "system") performing CreateOrUpdate: agentpools.AgentPoolsClient#CreateOrUpdate: Failure sending request: StatusCode=0 -- Original Error: Code="NodePoolMcVersionIncompatible" Message="Node pool version 1.27.7 and control plane version 1.26.10 are incompatible. Minor version of node pool version 27 is bigger than control plane version 26. For more information, please check https://aka.ms/aks/UpgradeVersionRules"
│
│ with module.aks_post.module.aks.azurerm_kubernetes_cluster.main,
│ on .terraform/modules/aks_post.aks/main.tf line 17, in resource "azurerm_kubernetes_cluster" "main":
│ 17: resource "azurerm_kubernetes_cluster" "main" {
│
@dunefro I understand you are using var.orchestrator_version = var.kubernetes_version
I see the problem where after PR #336 the cluster update is handled like this:
so the Terraform plan will attempt to update just the nodepools, because var.orchestrator_version
is not ignored in the lifecycle.
@dunefro to unblock your work you could set the following values:
kubernetes_version = 1.27
orchestrator_version =1.26
This will update the control plane first to the latest 1.27 patch version. Once Terraform apply completes you can update your values to:
kubernetes_version = 1.27
orchestrator_version =1.27
This will finish the update updating also the node pools.
@dunefro please confirm if this unblocks your work and you can upgrade successfully.
@lonegunmanb @nellyk for the long term solution I see 2 options:
1) Make very visible in the documentation of the module that kubernetes_version
and orchestrator_version
are 2 distinct variables for the reason that first it is necessary to upgrade the control plane and then the node pools.
2) Support the scenario where the user configures kubernetes_version = orchestrator_version
during an upgrade. In this case we should add to the lifecycle
ignore_changes
also the var.orchestrator_version
both in the azurerm_kubernetes_cluster_node_pool
(extra node pools) and azurerm_kubernetes_cluster
(system node pool) and handle those upgrades with a new azapi
resource.
Please everyone give feedback on what is the best option for you.
TODO:
test if the following code: https://github.com/Azure/terraform-azurerm-aks/blob/3851478e869fd5523899b10e0d654d3c9b631b4c/main.tf#L603-L616
will upgrade also the System node pool to var.kubernetes_version
regardless of the value of var.orchestrator_version
.
Please everyone give feedback on what is the best option for you.
I am not a fan of the approach to upgrade everything with the Azapi provider if we do hard pinning and disable autopatch.
The approach of azapi has several caveats, the main one is the non-idempotent behavior. If we rollout only the control plane, nothing seems to happen in the first run. The null_resource with the "version keeper" is updated, but it doesn't trigger the update in the first run. Then if you trigger another run without changing any code, the upgrade finally starts. IMHO non-idempotent behavior is a no-no in the Terraform world.
I was happy with the available approach of 6.8.
Maybe we need two things:
Maybe we need two things:
- behavior of 6.8 for no autopatch
- behavior of 7.5 incase autopatch is active
The challenge is that we cannot have a conditional lifecycle
block that depends on the value of var.automatic_channel_upgrade
.
We would have to create 2 independent azurerm_kubernetes_cluster
resources and create only 1 conditionally. This code would be very hard to maintain because every change must be duplicated to all the azurerm_kubernetes_cluster
resources.
Next step:
The approach of azapi has several caveats, the main one is the non-idempotent behavior. If we rollout only the control plane, nothing seems to happen in the first run. The null_resource with the "version keeper" is updated, but it doesn't trigger the update in the first run. Then if you trigger another run without changing any code, the upgrade finally starts. IMHO non-idempotent behavior is a no-no in the Terraform world.
@mkilchhofer I am not able to reproduce the non-idempotent behavior. I created PR #501 where I extend one of our current CI tests to run the upgrades. As I soon as I change the value of var.kubernetes_version
the upgrade of the control plane is triggered. Could you please test ? Or could you please provide the exact steps to reproduce the non-idempotent behavior ? Thanks
Could you please test ? Or could you please provide the exact steps to reproduce the non-idempotent behavior ? Thanks
Can do some more testing but I am now one week on vacation (⛷️🎿🏔️) . I am back in the office on February 5th.
please confirm if this unblocks your work and you can upgrade successfully.
Yes this works. Thanks @zioproto
@dunefro I understand you are using
var.orchestrator_version = var.kubernetes_version
I see the problem where after PR #336 the cluster update is handled like this:
so the Terraform plan will attempt to update just the nodepools, because
var.orchestrator_version
is not ignored in the lifecycle.@dunefro to unblock your work you could set the following values:
kubernetes_version = 1.27 orchestrator_version =1.26
This will update the control plane first to the latest 1.27 patch version. Once Terraform apply completes you can update your values to:
kubernetes_version = 1.27 orchestrator_version =1.27
This will finish the update updating also the node pools.
@dunefro please confirm if this unblocks your work and you can upgrade successfully.
@lonegunmanb @nellyk for the long term solution I see 2 options:
- Make very visible in the documentation of the module that
kubernetes_version
andorchestrator_version
are 2 distinct variables for the reason that first it is necessary to upgrade the control plane and then the node pools.- Support the scenario where the user configures
kubernetes_version = orchestrator_version
during an upgrade. In this case we should add to thelifecycle
ignore_changes
also thevar.orchestrator_version
both in theazurerm_kubernetes_cluster_node_pool
(extra node pools) andazurerm_kubernetes_cluster
(system node pool) and handle those upgrades with a newazapi
resource.Please everyone give feedback on what is the best option for you.
Hello zioproto. I think it makes sense from a user perspective with both WoW's. Since typically you do upgrade first the control plane before the workers.
For a usability PoV I prefer having to being able to set both versions to the version I want and the module to handle upgrade order. As it once worked in 6.8.0.
However today, there is no documentation over the modules dropped support for handling a seamless upgrade of both orchestrator and worker planes, causing this confusion.
I think it makes sense to be able to upgrade some node pools to a newer version, while some maybe can stay behind a version.
For us who are using the module, just the added documentation and the intended way to upgrade after the 6.8 to 7.5 upgrade is enough for us to be satisfied.
Edit: For us who use PR's to to peer review each others changes, this means we need to do two changes.. one for the controller plane, the second for, node pools... which is a bit more of a hassle.
Could you please test ? Or could you please provide the exact steps to reproduce the non-idempotent behavior ? Thanks
Can do some more testing but I am now one week on vacation (⛷️🎿🏔️) . I am back in the office on February 5th.
@mkilchhofer friendly ping about this pending issue :) thanks
@mkilchhofer friendly ping about this issue :)
@mkilchhofer friendly ping about this issue :)
I cannot test it anymore. We no longer use the module and manage the required TF resources ourself.
/cc: @zioproto
Can anyone else test it?
I was testing out the entire setup once again with the current version being 1.28
and the new_version being 1.29
.
As mentioned by @propyless I started out with updating the variable kubernetes_version
first to 1.29
.
Somehow I am not able to detect any drift for upgrading the kubernetes version. If I try to use orchestrator_version = 1.29
, there is a drift detection but only for the node pools, not the control plane. This is my AKS terraform file.
I have also tried to upgrade to AKS module version 9.0.0
and azurerm version 3.107.0
, still the same results.
One more weird things i have observed in the drift is the node count of the Azure AKS node pool. If I am not specifying the node count, rather specifying the min_count
and max_count
for the node pool, upon each terraform apply, even if there is no manual change in terraform from my side, the terraform detects a drift to reduce the size of the node pool back to 0. This should not happen if I am using cluster_autoscaler.
It would be great if we can get some help in the official documentation on -
they should cover various scenarios where node pools are managed by cluster_autoscaler or not.
- how to use the node pool
Would this example we already test in the CI help to demostrate how to use node pools ?
https://github.com/Azure/terraform-azurerm-aks/tree/main/examples/multiple_node_pools
@lonegunmanb could you please double check this with me ? in the resource azurerm_kubernetes_cluster_node_pool
we have a each.value.node_count
value.
we mark node_count
as optional:
But in the example we have node_count = 1
.
When cluster autoscaler is enabled node_count
should be null
. Is possible that we have an ambiguity here ? I am afraid the value will be 0
instead of null
unless explicitly set.
For the system node pool the variable is called agents_count
and it must be explicitly set to null:
https://github.com/Azure/terraform-azurerm-aks/blob/2c364a6d206f6c546da70fb6b9bd0dd633a83764/variables.tf#L30-L34
@dunefro what happens if you set to null
the node_count
in the node_pools
object ? Does it fix the state drift problem ?
@dunefro To try to reproduce your issue I tested the example in this repo examples/multiple_node_pools
with the following change
resource "azurerm_virtual_network" "test" {
address_space = ["10.52.0.0/16"]
- location = local.resource_group.location
+ location = "eastus"
name = "${random_id.prefix.hex}-vn"
resource_group_name = local.resource_group.name
}
@@ -36,7 +36,10 @@ locals {
for i in range(3) : "worker${i}" => {
name = substr("worker${i}${random_id.prefix.hex}", 0, 8)
vm_size = "Standard_D2s_v3"
- node_count = 1
+ min_count = 1
+ max_count = 3
+ enable_auto_scaling = true
vnet_subnet_id = azurerm_subnet.test.id
create_before_destroy = i % 2 == 0
}
But I dont have Terraform state drift , and I can apply "terraform apply" over and over again without detecting any change.
Could you please provide a code example that shows the problem of terraform trying to force the nodes to 0 ? Thanks
what happens if you set to null the node_count in the node_pools object ? Does it fix the state drift problem ?
@zioproto Yes this gets solved when I set the node_count
to null
, terraform doesn't detect any drift.
Is there an existing issue for this?
Terraform Version
1.6.2
Module Version
7.4.0
AzureRM Provider Version
3.69.0
Affected Resource(s)/Data Source(s)
module.aks.azurerm_kubernetes_cluster.main
Terraform Configuration Files
tfvars variables values
Debug Output/Panic Output
Expected Behaviour
Ideally the control plane should first gets updated and then the node pool. To resolve this issue I have to first update the control plane from the portal and then update the node pool from terraform.
Actual Behaviour
There is no terraform diff for updating control plane and node pool upgrade causes version incompatibility error.
Steps to Reproduce
No response
Important Factoids
No response
References
No response