<p>I want to expose a few webapps in EKS to the internet in a centrally managed secure way.</p>
<p>In AWS, using an ALB is nice, as it for example allows you to terminate TLS and add authentication using Cognito. (<a href="https://aws.amazon.com/blogs/containers/how-to-use-application-load-balancer-and-amazon-cognito-to-authenticate-users-for-your-kubernetes-web-apps/" rel="nofollow noreferrer">see here</a>)</p>
<p>To provision an ALB and connect it to the application there is the <a href="https://github.com/kubernetes-sigs/aws-load-balancer-controller" rel="nofollow noreferrer">aws-load-balancer-controller</a>.
It works fine, but it requires for each and every app/ingress to configure a new ALB:</p>
<pre><code>  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/tags: Environment=test,Project=cognito
    external-dns.alpha.kubernetes.io/hostname: sample.${COK_MY_DOMAIN} 
    alb.ingress.kubernetes.io/listen-ports: '[{&quot;HTTP&quot;: 80}, {&quot;HTTPS&quot;:443}]'
    alb.ingress.kubernetes.io/actions.ssl-redirect: '{&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;}}'
    alb.ingress.kubernetes.io/auth-type: cognito
    alb.ingress.kubernetes.io/auth-scope: openid
    alb.ingress.kubernetes.io/auth-session-timeout: '3600'
    alb.ingress.kubernetes.io/auth-session-cookie: AWSELBAuthSessionCookie
    alb.ingress.kubernetes.io/auth-on-unauthenticated-request: authenticate
    alb.ingress.kubernetes.io/auth-idp-cognito: '{&quot;UserPoolArn&quot;: &quot;$(aws cognito-idp describe-user-pool --user-pool-id $COK_COGNITO_USER_POOL_ID --region $COK_AWS_REGION --query 'UserPool.Arn' --output text)&quot;,&quot;UserPoolClientId&quot;:&quot;${COK_COGNITO_USER_POOL_CLIENT_ID}&quot;,&quot;UserPoolDomain&quot;:&quot;${COK_COGNITO_DOMAIN}.auth.${COK_AWS_REGION}.amazoncognito.com&quot;}'
    alb.ingress.kubernetes.io/certificate-arn: $COK_ACM_CERT_ARN 
    alb.ingress.kubernetes.io/target-type: 'ip'
</code></pre>
<p>I would love to have one central well defined ALB and all the application do not need to care about this anymore.</p>
<p>My idea was having a regular <a href="https://github.com/kubernetes/ingress-nginx" rel="nofollow noreferrer">nginx-ingress-controller</a> and expose it via a central ALB.</p>
<p>Now the question is: <strong>How do I connect the ALB to the nginx-controller?</strong></p>
<p>One way would be manually configuring the ALB and build the target group by hand, which does not feel like a stable solution.</p>
<p>Another way would be using aws-load-balancer-controller to connect the nginx. In that case however nginx seems not to be able to publish the correct loadbalancer address and external-dns will enter the wrong DNS records. (Unfortunately there seems to be no <a href="https://github.com/kubernetes/ingress-nginx/issues/5231" rel="nofollow noreferrer">--publish-ingress</a> option in usual ingress controllers like nginx or traefik.)</p>
<p><strong>Question:</strong></p>
<ul>
<li>Is there a way to make the nginx-ingress-controller provide the correct address?</li>
<li>Is there maybe an easier way that combining two ingress controllers?</li>
</ul>

<p>I think I found a good solution.</p>
<p>I set up my environment using terraform.
After I set up the alb ingress controller, I can create a suitable ingress object, wait until the ALB is up, use terraform to extract the address of the ALB and use <code>publish-status-address</code> to tell nginx to publish exactly that address to all its ingresses:</p>
<pre><code>resource &quot;kubernetes_ingress_v1&quot; &quot;alb&quot; {
  wait_for_load_balancer = true
  metadata {
    name = &quot;alb&quot;
    namespace = &quot;kube-system&quot;
    annotations = {
      &quot;alb.ingress.kubernetes.io/scheme&quot; = &quot;internet-facing&quot;
      &quot;alb.ingress.kubernetes.io/listen-ports&quot; = &quot;[{\&quot;HTTP\&quot;: 80}, {\&quot;HTTPS\&quot;:443}]&quot;
      &quot;alb.ingress.kubernetes.io/ssl-redirect&quot; = &quot;443&quot;
      &quot;alb.ingress.kubernetes.io/certificate-arn&quot; = local.cert
      &quot;alb.ingress.kubernetes.io/target-type&quot; = &quot;ip&quot;
    }
  }
  spec {
    ingress_class_name = &quot;alb&quot;
    default_backend {
      service {
        name = &quot;ing-nginx-ingress-nginx-controller&quot;
        port {
          name = &quot;http&quot;
        }
      }
    }
  }
}

resource &quot;helm_release&quot; &quot;ing-nginx&quot; {
  name       = &quot;ing-nginx&quot;

  repository = &quot;https://kubernetes.github.io/ingress-nginx&quot;
  chart      = &quot;ingress-nginx&quot;
  namespace  = &quot;kube-system&quot;

  set {
    name  = &quot;controller.service.type&quot;
    value = &quot;ClusterIP&quot;
  }
  set {
    name  = &quot;controller.publishService.enabled&quot;
    value = &quot;false&quot;
  }
  set {
    name  = &quot;controller.extraArgs.publish-status-address&quot;
    value = kubernetes_ingress_v1.alb.status.0.load_balancer.0.ingress.0.hostname
  }
  set {
    name  = &quot;controller.config.use-forwarded-headers&quot;
    value = &quot;true&quot;
  }
  set {
    name  = &quot;controller.ingressClassResource.default&quot;
    value = &quot;true&quot;
  }
}
</code></pre>
<p>It is a bit weird, as it introduces something like a circular dependency, but the ingress simply waits until nginx is finally up and all is well.</p>
<p>This solution in not exactly the same as the <a href="https://github.com/kubernetes/ingress-nginx/issues/5231" rel="nofollow noreferrer">--publish-ingress</a> option as it will not be able to adapt to any changes of the ALB address. - Luckily I don't expect that address to change, so I'm fine with that solution.</p>
