Skip to content

Permanent diff: plan always wants to strip the Talos-managed alias IP (VIP) from control planes #550

Description

@betida-svc

Summary

With enable_alias_ip = true (the default), every terraform plan wants to remove the private VIP from the control plane that currently holds it. The diff never goes away, and applying it briefly removes the address that every node resolves the internal API hostname to.

Why it happens

The module configures Talos to own the VIP — talos_patch_control_plane.tf:

vip = var.enable_alias_ip ? {
  ip = local.control_plane_private_vip_ipv4
  hcloud = { apiToken = var.hcloud_token }
} : null

So the node holding the VIP calls the hcloud API and assigns the alias IP to its own private interface, moving it on failover.

But server.tf also declares the same attribute as empty:

network {
  network_id = local.network_id
  ip         = each.value.ipv4_private
  alias_ips  = [] # fix for https://github.com/hetznercloud/terraform-provider-hcloud/issues/650
}

alias_ips = [] tells the provider the list is empty, not that it is unmanaged. So Terraform sees drift as soon as Talos claims the VIP:

~ resource "hcloud_server" "control_planes" {
    ~ network {
        ~ alias_ips = ["10.0.10.100"] -> []
      }
  }

lifecycle.ignore_changes currently covers only user_data, image and iso, so nothing suppresses it.

Impact

The internal API hostname is mapped to the VIP on every node via extraHostEntries:

network:
  extraHostEntries:
    - ip: 10.0.10.100
      aliases: [kube.cluster.local]

and cluster_endpoint is https://kube.cluster.local:6443. So applying the diff removes the address every kubelet in the cluster uses to reach the API server, until Talos re-announces the VIP. Running pods keep serving, but nothing can be scheduled or reported in that window.

The practical effect is worse than the window itself: the plan is never clean, so terraform apply stops being safe to run for any unrelated change.

Environment

  • module v3.4.12 (also verified unchanged in v3.4.14)
  • hcloud provider 1.66.0, Terraform 1.15.7
  • 3 control planes, enable_alias_ip = true (default), kubeconfig_endpoint_mode = "public_ip"
  • Present since the cluster's first apply; not triggered by any config change on our side

Suggested fix

Add the network block to ignore_changes:

lifecycle {
  ignore_changes = [
    user_data,
    image,
    iso,
    network
  ]
}

Note network is a set block, so network[0].alias_ips is not addressable — terraform validate rejects it with "set elements do not have addressable keys". The whole block has to be ignored, which seems acceptable since its other attributes (network_id, ip) are fixed at creation.

Verified with terraform validate against v3.4.12. Branch with the change: https://github.com/betidaprod-org/terraform-hcloud-talos/tree/fix/ignore-alias-ips — happy to open it as a PR if the approach looks right, or to test an alternative you prefer.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions