<p>I have been trying to create an EKS cluster with self managed nodes on AWS using Terraform but I can't get my Kubernetes Ingress to create a load balancer. There are no errors but no load balancer gets created, it just times out.</p>
<p>I did create a load balancer manually in my account first and verified that the load balancer role is present. The policy <code>AWSElasticLoadBalancingServiceRolePolicy</code> is accessed when my Terraform code runs.</p>
<p>I have relied heavily on <a href="https://github.com/markhorrocks/aws_eks_roles" rel="nofollow noreferrer">this tutorial</a></p>
<p>tfvars:</p>
<pre><code>aws_region     = &quot;ap-southeast-1&quot;
domain         = &quot;*.mydomain.com&quot;
cluster_name   = &quot;my-tf-eks-cluster&quot;
vpc_id         = &quot;vpc-0d7700e26db6b3e21&quot;
app_subnet_ids = &quot;subnet-03c1e8c57110c92e0, subnet-0413e8bf24cb32595, subnet-047dcce0b810f0fbd&quot;
// gateway subnet IDs
</code></pre>
<p>Terraform code:</p>
<pre><code>terraform {
}

provider &quot;aws&quot; {
 region  = var.aws_region
 version = &quot;~&gt; 2.8&quot;
}

data &quot;aws_acm_certificate&quot; &quot;default&quot; {
  domain   = var.domain
  statuses = [&quot;ISSUED&quot;]
}

resource &quot;kubernetes_service_account&quot; &quot;alb-ingress&quot; {
  metadata {
    name = &quot;alb-ingress-controller&quot;
    namespace = &quot;kube-system&quot;
    labels = {
      &quot;app.kubernetes.io/name&quot; = &quot;alb-ingress-controller&quot;
    }
  }

  automount_service_account_token = true
}

resource &quot;kubernetes_cluster_role&quot; &quot;alb-ingress&quot; {
  metadata {
    name = &quot;alb-ingress-controller&quot;
    labels = {
      &quot;app.kubernetes.io/name&quot; = &quot;alb-ingress-controller&quot;
    }
  }

  rule {
    api_groups = [&quot;&quot;, &quot;extensions&quot;]
    resources  = [&quot;configmaps&quot;, &quot;endpoints&quot;, &quot;events&quot;, &quot;ingresses&quot;, &quot;ingresses/status&quot;, &quot;services&quot;]
    verbs      = [&quot;create&quot;, &quot;get&quot;, &quot;list&quot;, &quot;update&quot;, &quot;watch&quot;, &quot;patch&quot;]
  }

  rule {
    api_groups = [&quot;&quot;, &quot;extensions&quot;]
    resources  = [&quot;nodes&quot;, &quot;pods&quot;, &quot;secrets&quot;, &quot;services&quot;, &quot;namespaces&quot;]
    verbs      = [&quot;get&quot;, &quot;list&quot;, &quot;watch&quot;]
  }
}

resource &quot;kubernetes_cluster_role_binding&quot; &quot;alb-ingress&quot; {
  metadata {
    name = &quot;alb-ingress-controller&quot;
    labels = {
      &quot;app.kubernetes.io/name&quot; = &quot;alb-ingress-controller&quot;
    }
  }

  role_ref {
    api_group = &quot;rbac.authorization.k8s.io&quot;
    kind      = &quot;ClusterRole&quot;
    name      = &quot;alb-ingress-controller&quot;
  }

  subject {
    kind      = &quot;ServiceAccount&quot;
    name      = &quot;alb-ingress-controller&quot;
    namespace = &quot;kube-system&quot;
  }
}



resource &quot;kubernetes_deployment&quot; &quot;alb-ingress&quot; {
  metadata {
    name = &quot;alb-ingress-controller&quot;
    labels = {
      &quot;app.kubernetes.io/name&quot; = &quot;alb-ingress-controller&quot;
    }
    namespace = &quot;kube-system&quot;
  }

  spec {
    selector {
      match_labels = {
        &quot;app.kubernetes.io/name&quot; = &quot;alb-ingress-controller&quot;
      }
    }

    template {
      metadata {
        labels = {
          &quot;app.kubernetes.io/name&quot; = &quot;alb-ingress-controller&quot;
        }
      }
      spec {
        volume {
          name = kubernetes_service_account.alb-ingress.default_secret_name
          secret {
            secret_name = kubernetes_service_account.alb-ingress.default_secret_name
          }
        }
        container {
          # This is where you change the version when Amazon comes out with a new version of the ingress controller
          image = &quot;docker.io/amazon/aws-alb-ingress-controller:v1.1.8&quot;
          name  = &quot;alb-ingress-controller&quot;
          args = [
            &quot;--ingress-class=alb&quot;,
            &quot;--cluster-name=${var.cluster_name}&quot;,
            &quot;--aws-vpc-id=${var.vpc_id}&quot;,
            &quot;--aws-region=${var.aws_region}&quot;
          ]
          volume_mount {
            name       = kubernetes_service_account.alb-ingress.default_secret_name
            mount_path = &quot;/var/run/secrets/kubernetes.io/serviceaccount&quot;
            read_only  = true
          }
        }

        service_account_name = &quot;alb-ingress-controller&quot;

      }
    }
  }
}


resource &quot;kubernetes_ingress&quot; &quot;main&quot; {
  metadata {
    name = &quot;main-ingress&quot;
    annotations = {
      &quot;alb.ingress.kubernetes.io/scheme&quot; = &quot;internet-facing&quot;
      &quot;kubernetes.io/ingress.class&quot; = &quot;alb&quot;
      &quot;alb.ingress.kubernetes.io/subnets&quot; = &quot;${var.app_subnet_ids}&quot;
      &quot;alb.ingress.kubernetes.io/certificate-arn&quot; = &quot;${data.aws_acm_certificate.default.arn}&quot;
      &quot;alb.ingress.kubernetes.io/listen-ports&quot; = &lt;&lt;JSON
[
  {&quot;HTTP&quot;: 80},
  {&quot;HTTPS&quot;: 443}
]
JSON
      &quot;alb.ingress.kubernetes.io/actions.ssl-redirect&quot; = &lt;&lt;JSON
{
  &quot;Type&quot;: &quot;redirect&quot;,
  &quot;RedirectConfig&quot;: {
    &quot;Protocol&quot;: &quot;HTTPS&quot;,
    &quot;Port&quot;: &quot;443&quot;,
    &quot;StatusCode&quot;: &quot;HTTP_301&quot;
  }
}
JSON
    }
  }

  spec {
    rule {
      host = &quot;app.xactpos.com&quot;
      http {
        path {
          backend {
            service_name = &quot;ssl-redirect&quot;
            service_port = &quot;use-annotation&quot;
          }
          path = &quot;/*&quot;
        }
        path {
          backend {
            service_name = &quot;app-service1&quot;
            service_port = 80
          }
          path = &quot;/service1&quot;
        }
        path {
          backend {
            service_name = &quot;app-service2&quot;
            service_port = 80
          }
          path = &quot;/service2&quot;
        }
      }
    }

    rule {
      host = &quot;api.xactpos.com&quot;
      http {
        path {
          backend {
            service_name = &quot;ssl-redirect&quot;
            service_port = &quot;use-annotation&quot;
          }
          path = &quot;/*&quot;
        }
        path {
          backend {
            service_name = &quot;api-service1&quot;
            service_port = 80
          }
          path = &quot;/service3&quot;
        }
        path {
          backend {
            service_name = &quot;api-service2&quot;
            service_port = 80
          }
          path = &quot;/service4&quot;
        }
      }
    }
  }

  wait_for_load_balancer = true
}
</code></pre>

markhorrocks
<p>I am by no means a K8s expert, but I went through the Terraform code, and the only thing that I see as an option that could possibly help you debug this seems to be the <code>wait_for_load_balancer</code> option in the <code>kubernetes_ingress</code> resource. From the <a href="https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/ingress_v1#wait_for_load_balancer" rel="nofollow noreferrer">documentation</a>:</p>
<pre><code>Terraform will wait for the load balancer to have at least 1 endpoint before considering the resource created.
</code></pre>
<p>Maybe the output will be more clear in that case (if the creation fails for some reason), or you might find out why it's not creating an LB.</p>
