TerraformPilot

Infrastructure as Code

Terraform Kubernetes Provider v3.5.0: Role Binding Migrations and Breaking Changes

Terraform Kubernetes provider v3.5.0 moves role/cluster role bindings to Plugin Framework, adds breaking null checks, and deprecates HPA v2beta2.

LLuca Berton2 min read

Introduction

#

HashiCorp released v3.5.0 of the hashicorp/terraform-provider-kubernetes provider on Nov 5, 2026. This release migrates kubernetes_cluster_role_binding_v1 and kubernetes_role_binding_v1 from SDKv2 to the Plugin Framework, introduces breaking validation changes for both resources, and deprecates kubernetes_horizontal_pod_autoscaler_v2beta2. Anyone managing RBAC bindings or HPAs with Terraform should read the upgrade notes before running terraform apply.

What Is New

#

Plugin Framework migration for role bindings

#

Both kubernetes_cluster_role_binding_v1 (GH-2976) and kubernetes_role_binding_v1 (GH-2978) are now implemented on the Plugin Framework instead of SDKv2. Configuration syntax is unchanged and existing state does not need to be re-imported. moved blocks from the deprecated (non _v1) resource types are supported, but only on Terraform 1.8 or later:

moved {
 from = kubernetes_role_binding.example
 to   = kubernetes_role_binding_v1.example
}

After upgrading, the release notes call out a one-time, non-destructive in-place update (never a replacement) in these cases:

  • labels or annotations explicitly set to an empty map.
  • A User or Group subject with api_group = "", which will show as:
- api_group = "rbac.authorization.k8s.io" -> null

Only Terraform state changes here, not the actual RoleBinding/ClusterRoleBinding object in the cluster.

  • A binding whose name is set, when planned with -refresh=false.

Expect to see one plan with these diffs the first time you run terraform plan after upgrading; a second apply should produce no further changes.

Deprecation: kubernetes_horizontal_pod_autoscaler_v2beta2

#

kubernetes_horizontal_pod_autoscaler_v2beta2 is deprecated and will be removed in provider v4.0 (GH-3031). Move to kubernetes_horizontal_pod_autoscaler_v2:

resource "kubernetes_horizontal_pod_autoscaler_v2" "example" {
 metadata {
 name = "example"
 }
 
 spec {
 max_replicas = 10
 min_replicas = 1
 
 scale_target_ref {
 api_version = "apps/v1"
 kind        = "Deployment"
 name        = "example"
 }
 }
}

Breaking Changes

#

Two breaking changes apply to kubernetes_cluster_role_binding_v1 and kubernetes_role_binding_v1:

  1. null in metadata.labels / metadata.annotations is rejected. Earlier provider versions silently accepted null values and dropped the entry; the Plugin Framework implementation now errors at plan time. Audit configurations for patterns like:
metadata {
 labels = {
 team = null # now rejected, remove the key instead
 }
}

Fix by removing the key entirely rather than setting it to null.

  1. kubernetes_role_binding_v1: name and generate_name together are now rejected at plan time (GH-2978), including the case where generate_name = "". Previously the Kubernetes API silently ignored generate_name when name was also set. To preserve an existing RoleBinding:
  • If generate_name is empty, remove it and keep name.
  • If generate_name is non-empty and you want to keep it, remove name instead — but note that removing or changing a stored non-empty generate_name prefix will replace the RoleBinding.
resource "kubernetes_role_binding_v1" "example" {
 metadata {
 # keep only one of these two attributes
 name = "example-binding"
 # generate_name = "example-"
 }
 # ... role_ref, subject blocks unchanged
}

Upgrade Steps

#

Pin the provider version and upgrade:

terraform {
 required_providers {
 kubernetes = {
 source  = "hashicorp/kubernetes"
 version = "~> 3.5.0"
 }
 }
}
terraform init -upgrade
terraform plan

Before running terraform apply, review the plan carefully for the kubernetes_cluster_role_binding_v1 and kubernetes_role_binding_v1 resources: expect at most the one-time, non-destructive diffs described above (empty labels/annotations, api_group null/removed, or name-only plans with -refresh=false). If any binding currently sets both name and generate_name, or uses null for a label/annotation value, fix the configuration first — these will fail plan, not just show a diff.

If you use kubernetes_horizontal_pod_autoscaler_v2beta2, start planning migration to kubernetes_horizontal_pod_autoscaler_v2 ahead of provider v4.0.

Verify

#

Confirm the installed provider version and that the plan is clean after the one-time update:

terraform version
# Provider: registry.terraform.io/hashicorp/kubernetes v3.5.0
 
terraform plan
# No changes. Your infrastructure matches the configuration.

For migrated bindings, re-run terraform plan -refresh=false once after the initial apply to confirm no further drift is reported.

Conclusion

#

v3.5.0 completes the Plugin Framework migration for kubernetes_cluster_role_binding_v1 and kubernetes_role_binding_v1, tightens validation around null labels/annotations and conflicting name/generate_name, and starts the deprecation clock on kubernetes_horizontal_pod_autoscaler_v2beta2 ahead of v4.0. Review RBAC binding configurations for the breaking-change patterns above before upgrading in production, and plan the HPA migration early. Full details: release notes.

#Terraform#Kubernetes#Terraform Provider#Plugin Framework#RBAC#HashiCorp

Share this article