The Terraform Kubernetes provider manages Kubernetes resources directly. Errors typically stem from cluster connectivity, authentication, RBAC permissions, and API version mismatches.
Understanding Kubernetes Provider Errors
Common errors include:
``
Error: Kubernetes cluster unreachable: connection refused
Error: Forbidden: unauthorized to create resource
Error: Resource version mismatch: object has been modified
Error: API version "extensions/v1beta1" not found
Issue 1: Cluster Connectivity Failures
Cannot connect to Kubernetes API server.
Error Example:
``
Error: Kubernetes cluster unreachable: Get "https://CLUSTER_ENDPOINT/version":
dial tcp: connection refused
Solution:
Configure proper authentication for different cluster types:
For EKS clusters: ```hcl data "aws_eks_cluster" "cluster" { name = var.cluster_name }
data "aws_eks_cluster_auth" "cluster" { name = var.cluster_name }
provider "kubernetes" { host = data.aws_eks_cluster.cluster.endpoint cluster_ca_certificate = base64decode(data.aws_eks_cluster.cluster.certificate_authority[0].data) token = data.aws_eks_cluster_auth.cluster.token }
# Or using exec method (recommended for newer EKS) provider "kubernetes" { host = data.aws_eks_cluster.cluster.endpoint cluster_ca_certificate = base64decode(data.aws_eks_cluster.cluster.certificate_authority[0].data)
exec { api_version = "client.authentication.k8s.io/v1beta1" command = "aws" args = ["eks", "get-token", "--cluster-name", var.cluster_name] } } ```
For GKE clusters: ```hcl data "google_client_config" "default" {}
data "google_container_cluster" "cluster" { name = var.cluster_name location = var.cluster_location }
provider "kubernetes" { host = "https://${data.google_container_cluster.cluster.endpoint}" cluster_ca_certificate = base64decode(data.google_container_cluster.cluster.master_auth[0].cluster_ca_certificate) token = data.google_client_config.default.access_token } ```
For Azure AKS clusters: ```hcl data "azurerm_kubernetes_cluster" "cluster" { name = var.cluster_name resource_group_name = var.resource_group }
provider "kubernetes" { host = data.azurerm_kubernetes_cluster.cluster.kube_config[0].host client_certificate = base64decode(data.azurerm_kubernetes_cluster.cluster.kube_config[0].client_certificate) client_key = base64decode(data.azurerm_kubernetes_cluster.cluster.kube_config[0].client_key) cluster_ca_certificate = base64decode(data.azurerm_kubernetes_cluster.cluster.kube_config[0].cluster_ca_certificate) } ```
Using kubeconfig:
``hcl
provider "kubernetes" {
config_path = "~/.kube/config"
config_context = "my-cluster-context"
}
Issue 2: RBAC Permission Denied
Insufficient permissions to manage Kubernetes resources.
Error Example:
``
Error: Forbidden: User "terraform" cannot create resource "deployments"
in API group "apps" in namespace "production"
Solution:
Create proper RBAC configuration: ```hcl resource "kubernetes_service_account" "terraform" { metadata { name = "terraform-deployer" namespace = "kube-system" } }
resource "kubernetes_cluster_role" "terraform" { metadata { name = "terraform-deployer" }
rule { api_groups = ["", "apps", "batch", "extensions", "networking.k8s.io"] resources = ["*"] verbs = ["create", "delete", "get", "list", "update", "watch", "patch"] }
rule { api_groups = ["rbac.authorization.k8s.io"] resources = ["roles", "rolebindings", "clusterroles", "clusterrolebindings"] verbs = ["create", "delete", "get", "list", "update", "watch", "patch"] } }
resource "kubernetes_cluster_role_binding" "terraform" { metadata { name = "terraform-deployer-binding" }
role_ref { api_group = "rbac.authorization.k8s.io" kind = "ClusterRole" name = kubernetes_cluster_role.terraform.metadata[0].name }
subject { kind = "ServiceAccount" name = kubernetes_service_account.terraform.metadata[0].name namespace = "kube-system" } } ```
Namespace-specific permissions: ```hcl resource "kubernetes_role" "terraform_namespace" { metadata { name = "terraform-deployer" namespace = var.namespace }
rule { api_groups = ["", "apps"] resources = ["deployments", "services", "configmaps", "secrets"] verbs = ["*"] } }
resource "kubernetes_role_binding" "terraform_namespace" { metadata { name = "terraform-deployer" namespace = var.namespace }
role_ref { api_group = "rbac.authorization.k8s.io" kind = "Role" name = kubernetes_role.terraform_namespace.metadata[0].name }
subject { kind = "User" name = "terraform-user" api_group = "rbac.authorization.k8s.io" } } ```
Issue 3: Resource Version Mismatch
Resource has been modified outside Terraform.
Error Example:
``
Error: Resource version mismatch: object has been modified
Expected version: 12345, Current version: 12346
Solution:
Re-import the resource:
``bash
terraform import kubernetes_deployment.app production/my-app
Or refresh state:
``bash
terraform refresh -target=kubernetes_deployment.app
Prevent drift by ignoring certain fields: ```hcl resource "kubernetes_deployment" "app" { metadata { name = "my-app" namespace = "production" }
spec { # ... configuration ... }
lifecycle { # Ignore changes made by Kubernetes autoscaling ignore_changes = [ spec[0].replicas ]
# Prevent accidental deletion prevent_destroy = true } } ```
Issue 4: API Version Deprecation
Using deprecated API versions.
Error Example:
``
Error: API version "extensions/v1beta1" is deprecated
Use "apps/v1" instead
Solution:
Update to current API versions: ```hcl # Old (deprecated) # resource "kubernetes_deployment" "app" { # metadata { name = "my-app" } # spec { # replicas = 3 # } # }
# New (correct API version) resource "kubernetes_deployment" "app" { metadata { name = "my-app" namespace = "default"
annotations = { "kubectl.kubernetes.io/last-applied-configuration" = jsonencode({}) } }
spec { replicas = 3
selector { match_labels = { app = "my-app" } }
template { metadata { labels = { app = "my-app" } }
spec { container { name = "app" image = "nginx:latest"
port { container_port = 80 } } } } } } ```
Common API version updates:
- Deployments: extensions/v1beta1 -> apps/v1
- DaemonSets: extensions/v1beta1 -> apps/v1
- StatefulSets: apps/v1beta1 -> apps/v1
- Ingress: extensions/v1beta1 -> networking.k8s.io/v1
- NetworkPolicy: extensions/v1beta1 -> networking.k8s.io/v1
Issue 5: Namespace Does Not Exist
Target namespace not found.
Error Example:
``
Error: namespaces "production" not found
Solution:
Create namespace before other resources: ```hcl resource "kubernetes_namespace" "production" { metadata { name = "production"
labels = { environment = "production" managed-by = "terraform" } } }
resource "kubernetes_deployment" "app" { metadata { name = "my-app" namespace = kubernetes_namespace.production.metadata[0].name }
spec { replicas = 3 }
depends_on = [kubernetes_namespace.production] } ```
Issue 6: Invalid YAML or Configuration
Resource configuration has syntax errors.
Error Example:
``
Error: Invalid configuration: port number must be between 1 and 65535
Error: YAML parse error: line 25: unexpected character
Solution:
Validate configuration: ```hcl resource "kubernetes_service" "app" { metadata { name = "my-app-service" namespace = "default" }
spec { selector = { app = "my-app" }
port { name = "http" port = 80 # Valid: 1-65535 target_port = 8080 # Valid: 1-65535 or string protocol = "TCP" # TCP, UDP, or SCTP }
type = "LoadBalancer" # ClusterIP, NodePort, LoadBalancer, or ExternalName } } ```
Use kubectl_manifest for complex YAML:
```hcl
resource "kubectl_manifest" "custom_resource" {
yaml_body = <<-YAML
apiVersion: custom.example.com/v1
kind: CustomResource
metadata:
name: my-custom-resource
namespace: production
spec:
replicas: 3
config:
key: value
YAML
depends_on = [kubernetes_namespace.production] } ```
Issue 7: Secret Encoding Issues
Secret data not properly base64 encoded.
Error Example:
``
Error: Invalid secret data: value must be base64 encoded
Solution:
Encode secret values: ```hcl resource "kubernetes_secret" "app_secrets" { metadata { name = "app-secrets" namespace = "production" }
data = { username = base64encode("admin") password = base64encode(var.db_password) api_key = base64encode(var.api_key) }
type = "Opaque" }
# Or use sensitive values resource "kubernetes_secret" "sensitive" { metadata { name = "sensitive-secrets" namespace = "production" }
data = { # Terraform handles encoding secret_value = base64encode(sensitive_value) } } ```
Issue 8: Timeout Waiting for Resource
Resource creation takes too long.
Error Example:
``
Error: timed out waiting for resource "kubernetes_deployment.app" to be ready
Solution:
Configure timeouts and wait conditions: ```hcl resource "kubernetes_deployment" "app" { metadata { name = "my-app" namespace = "production" }
spec { replicas = 3
# ... rest of configuration ...
# Wait for deployment to be ready wait_for_rollout = true }
timeouts { create = "10m" update = "10m" delete = "5m" } } ```
Check deployment status:
``bash
kubectl rollout status deployment/my-app -n production
kubectl get pods -l app=my-app -n production
kubectl describe deployment my-app -n production
Issue 9: Provider Version Conflicts
Provider version incompatible with cluster version.
Error Example:
``
Error: Provider does not support Kubernetes version 1.24
Solution:
Update provider version: ```hcl terraform { required_providers { kubernetes = { source = "hashicorp/kubernetes" version = "~> 2.20" # Compatible with Kubernetes 1.24+ } } }
provider "kubernetes" { # Configuration ... } ```
Check compatibility matrix: - Kubernetes provider 2.0+ supports Kubernetes 1.19+ - Kubernetes provider 2.20+ supports Kubernetes 1.24+ - Use latest provider for newest Kubernetes versions
Verification Steps
Test cluster connectivity: ```bash kubectl cluster-info kubectl get nodes kubectl version
# Test with terraform terraform plan -target=kubernetes_namespace.test ```
Verify RBAC permissions:
``bash
kubectl auth can-i create deployments --as=terraform-user
kubectl auth can-i '*' '*' --all-namespaces
Prevention Best Practices
- 1.Configure authentication before deploying resources
- 2.Create namespaces before namespace-scoped resources
- 3.Use current API versions (apps/v1, networking.k8s.io/v1)
- 4.Encode secret values with base64encode()
- 5.Add depends_on for resource dependencies
- 6.Use ignore_changes for fields managed by Kubernetes
- 7.Configure appropriate timeouts for slow resources
- 8.Keep provider version updated for Kubernetes compatibility