opentofu-kubernetes-explorer

Explore and manage Kubernetes clusters and resources using OpenTofu/Terraform

16 stars

Best use case

opentofu-kubernetes-explorer is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Explore and manage Kubernetes clusters and resources using OpenTofu/Terraform

Teams using opentofu-kubernetes-explorer should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/opentofu-kubernetes-explorer/SKILL.md --create-dirs "https://raw.githubusercontent.com/diegosouzapw/awesome-omni-skill/main/skills/devops/opentofu-kubernetes-explorer/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/opentofu-kubernetes-explorer/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How opentofu-kubernetes-explorer Compares

Feature / Agentopentofu-kubernetes-explorerStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Explore and manage Kubernetes clusters and resources using OpenTofu/Terraform

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# OpenTofu Kubernetes Explorer

## What I do

I guide you through managing Kubernetes clusters and resources using Kubernetes provider for OpenTofu/Terraform. I help you:

- **Cluster Management**: Deploy and manage Kubernetes clusters
- **Resource Deployment**: Create pods, deployments, services, and configmaps
- **Ingress and Networking**: Configure ingress controllers and network policies
- **Storage**: Create and manage persistent volumes and storage classes
- **Helm Charts**: Deploy Helm charts for complex applications
- **Best Practices**: Follow Kubernetes and provider documentation patterns

## When to use me

Use this skill when you need to:
- Automate Kubernetes resource management as code
- Deploy applications to Kubernetes clusters
- Manage Kubernetes configuration (ConfigMaps, Secrets)
- Configure ingress controllers and load balancers
- Setup persistent storage and storage classes
- Deploy Helm charts for application packages
- Manage multi-cluster Kubernetes deployments

**Note**: OpenTofu and Terraform are used interchangeably throughout this skill. OpenTofu is an open-source implementation of Terraform and maintains full compatibility with Terraform providers.

## Prerequisites

- **OpenTofu CLI installed**: Install from https://opentofu.org/docs/intro/install/
- **Kubernetes Cluster**: Running Kubernetes cluster (EKS, GKE, AKS, or self-managed)
- **kubectl**: Kubernetes command-line tool for local testing
- **kubeconfig**: Valid Kubernetes configuration file
- **Basic Kubernetes Knowledge**: Understanding of pods, services, deployments, and concepts

## Provider Documentation

- **Terraform Registry (Kubernetes Provider)**: https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs
- **Latest Provider Version**: hashicorp/kubernetes ~> 2.24.0
- **Provider Source**: https://github.com/hashicorp/terraform-provider-kubernetes
- **Kubernetes Documentation**: https://kubernetes.io/docs/
- **Helm Provider**: https://registry.terraform.io/providers/hashicorp/helm/latest/docs

## Steps

### Step 1: Install and Configure OpenTofu

```bash
# Verify OpenTofu installation
tofu version

# Initialize project
mkdir kubernetes-terraform
cd kubernetes-terraform
tofu init
```

### Step 2: Configure Kubernetes Provider

Create `versions.tf`:

```hcl
terraform {
  required_providers {
    kubernetes = {
      source  = "hashicorp/kubernetes"
      version = "~> 2.24.0"
    }
    helm = {
      source  = "hashicorp/helm"
      version = "~> 2.11.0"
    }
  }
  required_version = ">= 1.0"

  # Remote state backend
  backend "s3" {
    bucket         = "terraform-state"
    key            = "kubernetes/terraform.tfstate"
    region         = "ap-southeast-1"
    encrypt        = true
    dynamodb_table = "terraform-locks"
  }
}
```

### Step 3: Configure Provider Connection

Create `provider.tf`:

```hcl
provider "kubernetes" {
  # Method 1: Use default kubeconfig (recommended)
  # Uses ~/.kube/config by default
  # Best for local development and single cluster

  # Method 2: Specify kubeconfig path
  config_path = var.kubeconfig_path

  # Method 3: Use config context
  config_context = "my-cluster-context"

  # Method 4: Direct cluster configuration (for EKS)
  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

  # Namespace configuration
  config_context_auth_info = false
}

provider "helm" {
  kubernetes {
    config_path = var.kubeconfig_path
  }
}
```

### Step 4: Configure Environment Variables

```bash
# Method 1: Use default kubeconfig
# Provider automatically uses ~/.kube/config

# Method 2: Specify kubeconfig path
export KUBECONFIG="/path/to/kubeconfig"

# Method 3: Use config context
export KUBECONFIG="/path/to/kubeconfig"
kubectl config use-context my-cluster-context

# Method 4: For EKS with AWS credentials
# Set AWS environment variables
export AWS_ACCESS_KEY_ID="..."
export AWS_SECRET_ACCESS_KEY="..."
export AWS_DEFAULT_REGION="ap-southeast-1"
```

### Step 5: Create Namespace

Create `namespace.tf`:

```hcl
# Application namespace
resource "kubernetes_namespace" "app" {
  metadata {
    name = var.app_namespace
    labels = {
      app       = var.application_name
      managedBy = "terraform"
      environment = var.environment
    }
  }
}

# Monitoring namespace
resource "kubernetes_namespace" "monitoring" {
  metadata {
    name = "monitoring"
    labels = {
      name   = "monitoring"
      managedBy = "terraform"
    }
  }
}

# Ingress namespace
resource "kubernetes_namespace" "ingress" {
  metadata {
    name = "ingress-nginx"
    labels = {
      app   = "ingress-nginx"
      managedBy = "terraform"
    }
  }
}
```

### Step 6: Create ConfigMap and Secret

Create `config.tf`:

```hcl
# Application ConfigMap
resource "kubernetes_config_map" "app_config" {
  metadata {
    name      = "app-config"
    namespace = kubernetes_namespace.app.metadata[0].name
  }

  data = {
    "application.properties" = <<-EOT
      server.port=8080
      database.url=${var.database_url}
      logging.level=INFO
      environment=${var.environment}
    EOT

    "logback.xml" = file("${path.module}/config/logback.xml")
  }
}

# Application Secret
resource "kubernetes_secret" "app_secret" {
  metadata {
    name      = "app-secret"
    namespace = kubernetes_namespace.app.metadata[0].name
  }

  data = {
    "database-password" = var.database_password
    "api-key"          = var.api_key
  }

  type = "Opaque"
}
```

### Step 7: Create Deployment

Create `deployment.tf`:

```hcl
# Application Deployment
resource "kubernetes_deployment" "app" {
  metadata {
    name      = var.application_name
    namespace = kubernetes_namespace.app.metadata[0].name
    labels = {
      app = var.application_name
    }
  }

  spec {
    replicas = var.replicas

    selector {
      match_labels = {
        app = var.application_name
      }
    }

    template {
      metadata {
        labels = {
          app = var.application_name
        }
      }

      spec {
        container {
          name  = "app"
          image = var.container_image

          port {
            container_port = 8080
          }

          # Environment variables
          env {
            name  = "SERVER_PORT"
            value = "8080"
          }

          env {
            name = "DATABASE_URL"
            value_from {
              secret_key_ref {
                name = kubernetes_secret.app_secret.metadata[0].name
                key  = "database-password"
              }
            }
          }

          # Resource limits
          resources {
            limits = {
              cpu    = "500m"
              memory = "512Mi"
            }
            requests = {
              cpu    = "250m"
              memory = "256Mi"
            }
          }

          # Liveness probe
          liveness_probe {
            http_get {
              path = "/health"
              port = 8080
            }
            initial_delay_seconds = 10
            period_seconds        = 10
            timeout_seconds      = 5
            failure_threshold    = 3
          }

          # Readiness probe
          readiness_probe {
            http_get {
              path = "/ready"
              port = 8080
            }
            initial_delay_seconds = 5
            period_seconds        = 5
            timeout_seconds      = 3
            failure_threshold    = 2
          }
        }
      }
    }
  }

  # Prevent pod disruption during update
  strategy {
    type = "RollingUpdate"

    rolling_update {
      max_surge       = 1
      max_unavailable = 0
    }
  }
}
```

### Step 8: Create Service

Create `service.tf`:

```hcl
# Application Service (ClusterIP)
resource "kubernetes_service" "app" {
  metadata {
    name      = var.application_name
    namespace = kubernetes_namespace.app.metadata[0].name
    labels = {
      app = var.application_name
    }
  }

  spec {
    type = "ClusterIP"

    selector {
      app = var.application_name
    }

    port {
      name        = "http"
      protocol    = "TCP"
      port        = 80
      target_port = 8080
    }
  }
}

# Application Service (LoadBalancer)
resource "kubernetes_service" "app_lb" {
  metadata {
    name      = "${var.application_name}-lb"
    namespace = kubernetes_namespace.app.metadata[0].name
    labels = {
      app = var.application_name
    }
    annotations = {
      "service.beta.kubernetes.io/aws-load-balancer-type" = "nlb"
    }
  }

  spec {
    type = "LoadBalancer"

    selector {
      app = var.application_name
    }

    port {
      name        = "http"
      protocol    = "TCP"
      port        = 80
      target_port = 8080
    }

    port {
      name        = "https"
      protocol    = "TCP"
      port        = 443
      target_port = 8080
    }
  }
}

# Headless Service for StatefulSets
resource "kubernetes_service" "app_headless" {
  metadata {
    name      = "${var.application_name}-headless"
    namespace = kubernetes_namespace.app.metadata[0].name
    labels = {
      app = var.application_name
    }
  }

  spec {
    type = "ClusterIP"
    cluster_ip = "None"

    selector {
      app = var.application_name
    }

    port {
      name        = "http"
      protocol    = "TCP"
      port        = 8080
      target_port = 8080
    }
  }
}
```

### Step 9: Create Ingress

Create `ingress.tf`:

```hcl
# Ingress Controller Deployment (nginx)
resource "helm_release" "ingress_nginx" {
  name       = "ingress-nginx"
  repository = "https://kubernetes.github.io/ingress-nginx"
  chart      = "ingress-nginx"
  namespace  = kubernetes_namespace.ingress.metadata[0].name

  set {
    name  = "controller.service.type"
    value = "LoadBalancer"
  }

  set {
    name  = "controller.publishService.enabled"
    value = "true"
  }
}

# Application Ingress
resource "kubernetes_ingress" "app" {
  metadata {
    name      = var.application_name
    namespace = kubernetes_namespace.app.metadata[0].name
    labels = {
      app = var.application_name
    }
    annotations = {
      "kubernetes.io/ingress.class"           = "nginx"
      "cert-manager.io/cluster-issuer"         = "letsencrypt-prod"
      "nginx.ingress.kubernetes.io/ssl-redirect" = "true"
    }
  }

  spec {
    rule {
      host = var.ingress_host

      http {
        path {
          backend {
            service_name = kubernetes_service.app.metadata[0].name
            service_port = 80
          }

          path = "/"
        }
      }
    }

    tls {
      hosts       = [var.ingress_host]
      secret_name = kubernetes_secret.tls_cert.metadata[0].name
    }
  }
}
```

### Step 10: Create Persistent Volume

Create `storage.tf`:

```hcl
# Storage Class
resource "kubernetes_storage_class" "gp2" {
  metadata {
    name = "gp2"
  }

  storage_provisioner = "kubernetes.io/aws-ebs"
  parameters = {
    type = "gp2"
  }

  allow_volume_expansion = true

  reclaim_policy = "Retain"
  volume_binding_mode = "WaitForFirstConsumer"
}

# Persistent Volume Claim
resource "kubernetes_persistent_volume_claim" "data" {
  metadata {
    name      = "app-data"
    namespace = kubernetes_namespace.app.metadata[0].name
  }

  spec {
    access_modes       = ["ReadWriteOnce"]
    storage_class_name = kubernetes_storage_class.gp2.metadata[0].name

    resources {
      requests = {
        storage = "10Gi"
      }
    }
  }
}
```

### Step 11: Deploy Helm Chart

Create `helm.tf`:

```hcl
# Redis Deployment
resource "helm_release" "redis" {
  name       = "redis"
  repository = "https://charts.bitnami.com/bitnami"
  chart      = "redis"
  namespace  = kubernetes_namespace.app.metadata[0].name
  version    = "17.11.0"

  set {
    name  = "auth.enabled"
    value = "true"
  }

  set {
    name  = "auth.password"
    value = var.redis_password
  }

  set {
    name  = "persistence.enabled"
    value = "true"
  }

  set {
    name  = "persistence.size"
    value = "8Gi"
  }
}

# PostgreSQL Deployment
resource "helm_release" "postgresql" {
  name       = "postgresql"
  repository = "https://charts.bitnami.com/bitnami"
  chart      = "postgresql"
  namespace  = kubernetes_namespace.app.metadata[0].name
  version    = "12.5.0"

  set {
    name  = "auth.enablePostgresUser"
    value = "true"
  }

  set {
    name  = "auth.password"
    value = var.postgresql_password
  }

  set {
    name  = "auth.database"
    value = "appdb"
  }

  set {
    name  = "primary.persistence.enabled"
    value = "true"
  }

  set {
    name  = "primary.persistence.size"
    value = "20Gi"
  }
}
```

### Step 12: Create Horizontal Pod Autoscaler

Create `autoscaler.tf`:

```hcl
resource "kubernetes_horizontal_pod_autoscaler" "app" {
  metadata {
    name      = "${var.application_name}-hpa"
    namespace = kubernetes_namespace.app.metadata[0].name
  }

  spec {
    scale_target_ref {
      api_version = "apps/v1"
      kind       = "Deployment"
      name       = kubernetes_deployment.app.metadata[0].name
    }

    min_replicas = var.min_replicas
    max_replicas = var.max_replicas

    target_cpu_utilization_percentage    = 60
    target_memory_utilization_percentage = 70
  }
}
```

### Step 13: Define Variables

Create `variables.tf`:

```hcl
variable "kubeconfig_path" {
  description = "Path to kubeconfig file"
  type        = string
  default     = "~/.kube/config"
}

variable "app_namespace" {
  description = "Application namespace"
  type        = string
  default     = "app"
}

variable "application_name" {
  description = "Application name"
  type        = string
}

variable "container_image" {
  description = "Container image to deploy"
  type        = string
}

variable "replicas" {
  description = "Number of replicas"
  type        = number
  default     = 3
}

variable "min_replicas" {
  description = "Minimum replicas for autoscaling"
  type        = number
  default     = 2
}

variable "max_replicas" {
  description = "Maximum replicas for autoscaling"
  type        = number
  default     = 10
}

variable "database_url" {
  description = "Database connection URL"
  type        = string
  sensitive   = true
}

variable "database_password" {
  description = "Database password"
  type        = string
  sensitive   = true
}

variable "api_key" {
  description = "API key"
  type        = string
  sensitive   = true
}

variable "ingress_host" {
  description = "Ingress host"
  type        = string
}

variable "redis_password" {
  description = "Redis password"
  type        = string
  sensitive   = true
}

variable "postgresql_password" {
  description = "PostgreSQL password"
  type        = string
  sensitive   = true
}

variable "environment" {
  description = "Environment name"
  type        = string
  validation {
    condition     = contains(["dev", "staging", "prod"], var.environment)
    error_message = "Environment must be dev, staging, or prod."
  }
}
```

### Step 14: Create Outputs

Create `outputs.tf`:

```hcl
output "namespace" {
  description = "Application namespace"
  value       = kubernetes_namespace.app.metadata[0].name
}

output "deployment_name" {
  description = "Application deployment name"
  value       = kubernetes_deployment.app.metadata[0].name
}

output "service_name" {
  description = "Application service name"
  value       = kubernetes_service.app.metadata[0].name
}

output "load_balancer_url" {
  description = "Load balancer URL"
  value       = kubernetes_service.app_lb.status[0].load_balancer[0].ingress[0].hostname
}

output "ingress_url" {
  description = "Ingress URL"
  value       = "https://${var.ingress_host}"
}
```

### Step 15: Initialize and Apply

```bash
# Set kubeconfig
export KUBECONFIG="/path/to/kubeconfig"

# Initialize providers
tofu init

# Plan changes
tofu plan -out=tfplan

# Apply changes
tofu apply tfplan

# Show outputs
tofu output

# Verify deployment
kubectl get all -n $APP_NAMESPACE
kubectl logs -f deployment/app -n $APP_NAMESPACE
```

## Best Practices

### Resource Management

1. **Use Namespaces**: Separate resources by namespace for isolation
2. **Label Everything**: Apply consistent labels to all resources
3. **Resource Limits**: Set appropriate resource requests and limits
4. **Probes**: Configure liveness and readiness probes
5. **Strategy**: Use RollingUpdate for zero-downtime deployments

### Security

1. **Least Privilege**: Use RBAC to restrict permissions
2. **Secrets Management**: Never store secrets in ConfigMaps; use Kubernetes Secrets
3. **Network Policies**: Implement network policies for pod-to-pod communication
4. **Image Security**: Use signed and verified container images
5. **Pod Security Context**: Define security context for pods and containers

### High Availability

1. **Replicas**: Deploy multiple replicas for critical applications
2. **Anti-Affinity**: Distribute pods across nodes
3. **Pod Disruption Budgets**: Configure PDBs to prevent voluntary disruptions
4. **Health Checks**: Use liveness and readiness probes
5. **Autoscaling**: Configure HPA for automatic scaling

### Storage

1. **Storage Classes**: Use appropriate storage classes for your use case
2. **Persistent Volumes**: Use PVCs for stateful applications
3. **Volume Expansion**: Enable storage expansion when possible
4. **Backup**: Implement backup strategies for persistent data
5. **StatefulSets**: Use StatefulSets for databases and stateful apps

### Ingress and Networking

1. **Ingress Controller**: Deploy an ingress controller for external access
2. **TLS Termination**: Use TLS termination at ingress
3. **Cert-Manager**: Automate TLS certificate management
4. **Load Balancer Type**: Choose appropriate LB type (ALB, NLB, etc.)
5. **DNS**: Configure DNS records for ingress hosts

### Helm Charts

1. **Version Pinning**: Pin chart versions for reproducibility
2. **Values Override**: Use `set` blocks to override default values
3. **Namespace Isolation**: Deploy charts in dedicated namespaces
4. **Release Management**: Use meaningful release names
5. **Upgrade Strategy**: Understand chart upgrade strategies

## Common Issues

### Issue: Provider Connection Failed

**Symptom**: Error `Error: Failed to configure provider`

**Solution**:
```bash
# Verify kubeconfig
kubectl cluster-info
kubectl config current-context

# Check kubeconfig path
ls -la ~/.kube/config

# Test connection
kubectl get nodes

# Verify KUBECONFIG environment variable
echo $KUBECONFIG

# For EKS with AWS credentials
aws eks describe-cluster --name my-cluster --region ap-southeast-1
```

### Issue: Image Pull Error

**Symptom**: Error `Failed to pull image`

**Solution**:
```bash
# Verify image exists
docker pull <image-name>

# Check image registry access
docker login <registry-url>

# Use image pull secrets
kubectl create secret docker-registry regcred \
  --docker-server=<registry-url> \
  --docker-username=<username> \
  --docker-password=<password>

# Reference: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
```

### Issue: Pod Pending State

**Symptom**: Pods stuck in Pending state

**Solution**:
```bash
# Describe pod for details
kubectl describe pod <pod-name>

# Check events
kubectl get events --sort-by='.lastTimestamp'

# Common issues:
# - Insufficient resources (check requests/limits)
# - Node affinity (check node selectors)
# - Taints and tolerations
# - Image pull errors
```

### Issue: Service Not Accessible

**Symptom**: Service is created but not accessible

**Solution**:
```bash
# Check service endpoints
kubectl get endpoints <service-name>

# Verify pod labels match service selector
kubectl get pods --show-labels

# Check service type
# ClusterIP: Only accessible within cluster
# LoadBalancer: External access via LB DNS/URL
# NodePort: External access via NodeIP:Port

# For LoadBalancer, check firewall/security groups
# Allow traffic to LB ports
```

### Issue: Ingress Not Working

**Symptom**: Ingress created but traffic not reaching pods

**Solution**:
```bash
# Verify ingress controller is running
kubectl get pods -n ingress-nginx

# Check ingress class annotation
kubectl describe ingress <ingress-name>

# Verify TLS secret exists
kubectl get secret <tls-secret-name>

# Check ingress backend service
kubectl get svc <backend-service-name>

# Check DNS resolution
nslookup <ingress-host>
dig <ingress-host>

# Reference: https://kubernetes.io/docs/concepts/services-networking/ingress/
```

### Issue: Persistent Volume Not Mounting

**Symptom**: Pod fails with volume mount errors

**Solution**:
```bash
# Check PVC status
kubectl get pvc

# Check storage class
kubectl get sc

# Verify volume exists
kubectl get pv

# Check pod events
kubectl describe pod <pod-name> | grep -A 10 Events

# Ensure storage class supports dynamic provisioning
# Check reclaim_policy and volume_binding_mode
```

### Issue: Helm Chart Upgrade Failed

**Symptom**: Error `Error: failed to upgrade release`

**Solution**:
```bash
# Check Helm release history
helm list -n <namespace>

# Get current values
helm get values <release-name> -n <namespace>

# Dry-run upgrade
helm upgrade --dry-run <release-name> <chart> -n <namespace>

# Rollback if needed
helm rollback <release-name> <revision> -n <namespace>

# Check chart compatibility
# Ensure chart version supports Kubernetes version
kubectl version
helm search repo <chart-name> --versions
```

### Issue: Autoscaling Not Working

**Symptom**: HPA not scaling pods

**Solution**:
```bash
# Check HPA status
kubectl get hpa

# Describe HPA for details
kubectl describe hpa <hpa-name>

# Check resource requests (required for HPA)
kubectl describe pod <pod-name> | grep -A 5 Requests

# Verify metrics server is running
kubectl get pods -n kube-system | grep metrics

# Check metrics availability
kubectl top nodes
kubectl top pods
```

## Reference Documentation

- **Terraform Registry (Kubernetes Provider)**: https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs
- **Kubernetes Documentation**: https://kubernetes.io/docs/
- **Helm Documentation**: https://helm.sh/docs/
- **Kubernetes API Reference**: https://kubernetes.io/docs/reference/
- **OpenTofu Documentation**: https://opentofu.org/docs/
- **kubectl Documentation**: https://kubernetes.io/docs/reference/kubectl/

## Examples

### Complete Application Deployment

```hcl
# namespace.tf
resource "kubernetes_namespace" "app" {
  metadata {
    name = "production"
  }
}

# config.tf
resource "kubernetes_config_map" "app_config" {
  metadata {
    name      = "app-config"
    namespace = kubernetes_namespace.app.metadata[0].name
  }

  data = {
    "config.json" = jsonencode({
      port = 8080
      env  = "production"
    })
  }
}

# deployment.tf
resource "kubernetes_deployment" "app" {
  metadata {
    name      = "webapp"
    namespace = kubernetes_namespace.app.metadata[0].name
  }

  spec {
    replicas = 3

    template {
      spec {
        container {
          name  = "webapp"
          image = "nginx:1.21"

          port {
            container_port = 80
          }

          resources {
            limits = {
              cpu    = "500m"
              memory = "512Mi"
            }
            requests = {
              cpu    = "250m"
              memory = "256Mi"
            }
          }
        }
      }
    }
  }
}
```

### Ingress with TLS

```hcl
# ingress.tf
resource "kubernetes_ingress" "app" {
  metadata {
    name      = "webapp-ingress"
    namespace = kubernetes_namespace.app.metadata[0].name
    annotations = {
      "kubernetes.io/ingress.class" = "nginx"
      "cert-manager.io/cluster-issuer" = "letsencrypt-prod"
    }
  }

  spec {
    rule {
      host = "app.example.com"

      http {
        path {
          backend {
            service_name = kubernetes_service.webapp.metadata[0].name
            service_port = 80
          }
        }
      }
    }

    tls {
      hosts       = ["app.example.com"]
      secret_name = kubernetes_secret.tls_cert.metadata[0].name
    }
  }
}
```

### Helm Chart Deployment

```hcl
# helm.tf
resource "helm_release" "redis" {
  name       = "redis"
  repository = "https://charts.bitnami.com/bitnami"
  chart      = "redis"
  namespace  = kubernetes_namespace.app.metadata[0].name

  set {
    name  = "auth.enabled"
    value = "true"
  }

  set {
    name  = "auth.password"
    value = var.redis_password
  }

  set {
    name  = "master.persistence.size"
    value = "8Gi"
  }
}
```

### EKS Cluster with Kubernetes Provider

```hcl
# eks.tf
resource "aws_eks_cluster" "main" {
  name     = "my-eks-cluster"
  role_arn = aws_iam_role.eks_cluster.arn
  version  = "1.27"

  vpc_config {
    subnet_ids = aws_subnet.public[*].id
  }
}

data "aws_eks_cluster" "cluster" {
  name = aws_eks_cluster.main.name
}

data "aws_eks_cluster_auth" "cluster" {
  name = aws_eks_cluster.main.name
}

# kubernetes.tf
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
}

resource "kubernetes_deployment" "app" {
  metadata {
    name      = "app"
    namespace = kubernetes_namespace.app.metadata[0].name
  }

  spec {
    template {
      spec {
        container {
          name  = "app"
          image = "my-app:latest"
        }
      }
    }
  }
}
```

## Tips and Tricks

- **Use kubectl**: Verify Terraform-created resources with kubectl
- **Dry Run**: Use `helm upgrade --dry-run` to test changes
- **Port Forward**: Use `kubectl port-forward` for local debugging
- **Logs**: Use `kubectl logs -f` for real-time debugging
- **Describe Everything**: Use `kubectl describe` for detailed resource information
- **Events**: Check events for troubleshooting issues
- **Resource Labels**: Use labels for organization and discovery
- **Namespace Isolation**: Use namespaces for environment separation
- **Helm Values**: Use `helm show values` to understand default configuration
- **Version Control**: Store Helm values files in version control
- **Import Resources**: Import existing Kubernetes resources into Terraform state

## Next Steps

After mastering Kubernetes provider, explore:
- **Kubernetes Advanced**: Learn about StatefulSets, DaemonSets, and Jobs
- **Kubernetes Operators**: Deploy operators for complex applications
- **Service Mesh**: Implement Istio or Linkerd for service-to-service communication
- **GitOps**: Use ArgoCD or Flux for GitOps workflows
- **Monitoring**: Deploy Prometheus and Grafana for observability
- **Kubernetes Security**: Learn about RBAC, network policies, and security contexts
- **Kubernetes Best Practices**: Follow K8s best practices for production workloads

Related Skills

learn-kubernetes-space-station-intermediate

16
from diegosouzapw/awesome-omni-skill

Interactive narrative learning session that teaches Kubernetes through a Space Station adventure at intermediate level. Use this session when you want to learn Kubernetes through immersive story-driven chapters, hands-on exercises, and tasks grounded in real, up-to-date documentation.

kubernetes-troubleshooting

16
from diegosouzapw/awesome-omni-skill

Debug Kubernetes pods, services, networking, and scaling issues. Use this skill when troubleshooting K8s deployments, investigating pod failures, or diagnosing cluster problems.

kubernetes-orchestration

16
from diegosouzapw/awesome-omni-skill

Kubernetes container orchestration. Use when deploying to Kubernetes, writing manifests, configuring Helm charts, or troubleshooting cluster issues.

kubernetes-ops

16
from diegosouzapw/awesome-omni-skill

Kubernetes cluster operations: kubectl commands, manifest generation, Helm charts, RBAC, debugging, and deployment strategies.

kubernetes-operators

16
from diegosouzapw/awesome-omni-skill

Kubernetes infrastructure patterns including operators, Helm, GitOps, and component provisioning.

kubernetes-deployment

16
from diegosouzapw/awesome-omni-skill

Deploy, manage, and scale applications on Kubernetes clusters using manifests, Helm charts, and autoscaling configurations.

kubernetes-deployer

16
from diegosouzapw/awesome-omni-skill

Package and deploy applications to Kubernetes with Dockerfiles, Helm charts, and local Minikube deployment. Use when containerizing applications, creating Kubernetes manifests, setting up Helm charts, deploying to Minikube, or preparing cloud-ready configurations. Focuses on local-first deployment with stateless services.

kubernetes-architect

16
from diegosouzapw/awesome-omni-skill

Expert Kubernetes architect specializing in cloud-native infrastructure, advanced GitOps workflows (ArgoCD/Flux), and enterprise container orchestration.

Kind Local Kubernetes

16
from diegosouzapw/awesome-omni-skill

This skill should be used when the user asks to "setup Kind", "local Kubernetes", "Kind cluster", "multi-node cluster", "Kubernetes development", "k8s local environment", or works with local Kubernetes clusters using Kind.

featbit-deployment-kubernetes

16
from diegosouzapw/awesome-omni-skill

Deploys FeatBit to Kubernetes using Helm Charts. Use when user mentions "Kubernetes", "Helm", "K8s", "kubectl", works with values.yaml files, asks about "cloud deployment", "AKS", "EKS", "GKE", "ingress", or needs production-grade container orchestration setup.

FastAPI Kubernetes Deployment

16
from diegosouzapw/awesome-omni-skill

This skill should be used when the user asks to "deploy FastAPI to Kubernetes", "create Dockerfile", "build Docker image", "write Helm chart", "configure K8s deployment", "add health checks", "scale FastAPI", or mentions Docker, Kubernetes, K8s, containers, Helm, or deployment. Provides containerization and orchestration patterns.

Docker & Kubernetes

16
from diegosouzapw/awesome-omni-skill

Containerization, orchestration, and deployment with Docker and K8s