skip to Main Content

I am trying to specify different hosts (subdomains) to different Kubernetes Services within my Kubernetes NGINX Ingress. For reference I am using Azure AKS.

I have the following ingress declared in Terraform.

resource "helm_release" "nginx_ingress" {
  name             = "nginx-ingress"
  repository       = "https://kubernetes.github.io/ingress-nginx"
  chart            = "ingress-nginx"
  namespace        = "ingress-nginx"
  create_namespace = true
  set {
    name  = "controller.service.type"
    value = "LoadBalancer"
  }
}

resource "kubernetes_ingress_v1" "nginx_ingress" {
  metadata {
    name = "nginx-ingress"
  }

  spec {
    ingress_class_name = "nginx"

    rule {
      host = "front-end.mydomain.com" # disable to access both hosts
      http {
        path {
          path      = "/"
          path_type = "Prefix"
          backend {
            service {
              name = kubernetes_service_v1.front_end.metadata[0].name
              port {
                number = 80
              }
            }
          }
        }
      }
    }

    rule {
      host = "docs.mydomain.com"
      http {
        path {
          path      = "/"
          path_type = "Prefix"
          backend {
            service {
              name = kubernetes_service_v1.front_end.metadata[0].name
              port {
                number = 80
              }
            }
          }
        }
      }
    }
  }
}

This is what happens with different configurations.

If I have one host set, both sites are accessible over HTTP on their domains.

If I have no hosts set, no sites are accessible over HTTP on their domains.

If I have both hosts set, no sites are accessible over HTTP on their domains.

I do not currently understand why this is occurring. I have confirmed the DNS A records point towards the correct IP address of the load balancer/ingress for each subdomain.

Edit: Fixed missing curly brace

2

Answers


  1. Chosen as BEST ANSWER

    After significant tinkering, I have resolved the issue.

    The solution was to set the below on the NGINX ingress controller declared using the helm release provider.

    # Required for SSL/TLS self-check to succeed (cert-manager)
    set {
      name  = "controller.service.beta.kubernetes.io/azure-load-balancer-health-probe-request-path"
      value = "/healthz"
    }
    
    # Required for host path routing to succeed
    set {
      name  = "controller.service.externalTrafficPolicy"
      value = "Local"
    }
    

    Updated complete example below.

    resource "helm_release" "nginx_ingress" {
      name             = "nginx-ingress"
      repository       = "https://kubernetes.github.io/ingress-nginx"
      chart            = "ingress-nginx"
      namespace        = "ingress-nginx"
      create_namespace = true
      set {
        name  = "controller.service.type"
        value = "LoadBalancer"
      }
      set {
        name  = "controller.service.beta.kubernetes.io/azure-load-balancer-health-probe-request-path"
        value = "/healthz"
      }
      set {
        name  = "controller.service.externalTrafficPolicy"
        value = "Local"
      }
    }
    
    resource "kubernetes_ingress_v1" "nginx_ingress" {
      metadata {
        name = "nginx-ingress"
      }
    
      spec {
        ingress_class_name = "nginx"
    
        rule {
          host = "front-end.mydomain.com"
          http {
            path {
              path      = "/"
              path_type = "Prefix"
              backend {
                service {
                  name = kubernetes_service_v1.front_end.metadata[0].name
                  port {
                    number = 80
                  }
                }
              }
            }
          }
        }
    
        rule {
          host = "docs.mydomain.com"
          http {
            path {
              path      = "/"
              path_type = "Prefix"
              backend {
                service {
                  name = kubernetes_service_v1.front_end.metadata[0].name
                  port {
                    number = 80
                  }
                }
              }
            }
          }
        }
    
        tls {
          hosts = [
            "front-end.mydomain.com",
            "docs.mydomain.com"
          ]
          secret_name = "letsencrypt-tls"
        }
      }
    }
    

  2. This is a normal behavior, because you have an issue in your parentheses.

    rule { # STARTS HERE
      host = "front-end.mydomain.com" # this will be the only domain
      http {
        path {
          path      = "/"
          path_type = "Prefix"
          backend {
            service {
              name = kubernetes_service_v1.front_end.metadata[0].name
              port {
                number = 80
              }
            }
          }
        }
      }
    
    rule {
      host = "docs.mydomain.com"
      http {
        path {
          path      = "/"
          path_type = "Prefix"
          backend {
            service {
              name = kubernetes_service_v1.front_end.metadata[0].name
              port {
                number = 80
              }
            }
          }
        }
      }
    } # ENDS HERE
    }
    

    but according to this, you can only define one host in each rule.
    The following may work:

    rule {
      host = "front-end.mydomain.com"
      http {
        path {
          path      = "/"
          path_type = "Prefix"
          backend {
            service {
              name = kubernetes_service_v1.front_end.metadata[0].name
              port {
                number = 80
              }
            }
          }
        }
      }}
    
    rule {
      host = "docs.mydomain.com"
      http {
        path {
          path      = "/"
          path_type = "Prefix"
          backend {
            service {
              name = kubernetes_service_v1.front_end.metadata[0].name
              port {
                number = 80
              }
            }
          }
        }
      }
    }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search