Search code examples
kubernetesterraformgoogle-kubernetes-engineterraform-provider-gcp

Add multiple backends to Ingress using Terraform


I'm deploying a GKE cluster and 2 releases with Helm provider in Terraform.

Basically I'm deploying 2 test app that writes a custom message and the Nginx ingress should redirect to one or another depending on the pathPrefix, If I manually add the Service name of each release to the Ingress rules/backend it works, but I want it to be automatically done when applying the terraform, deploy the releases, deploy the ingress and once the Services names are available, pass the name to the Ingress, so that way in case we have 10 releases with different paths we just have to apply the terraform adding more to the variable map.

So, it's possible? Having the output and pass it to a variable? just like in Terraform.

So my Helm resource looks like this:

resource "helm_release" "helm_releases" {
  for_each         = var.releases_map
  name             = each.key
  chart            = each.value.chart_source
  namespace        = each.value.namespace
  create_namespace = each.value.create_namespace

  values = [
    "${file("./helm-app/values.yaml")}"
  ]

  set {
    name  = "deployment.replicaCount"
    value = each.value.replica_count
  }
  .
  .
}

And my variable "releases_map" {} looks like this:

releases_map = {
  "gke-test-1" = {
    chart_source     = "./helm-app"
    namespace        = "gke-ns"
    create_namespace = true
    service_type     = "ClusterIP"
    replica_count    = "3"
    service_port     = "80"
    container_image  = "publicrepo/helm-app"
    image_version    = "1.10"
    ingress_configured = true
    path_prefix        = "custom-message"
    message          = "test-1"
  }
  "gke-test-2" = {
    chart_source     = "./helm-app"
    namespace        = "gke-ns"
    create_namespace = false
    service_type     = "ClusterIP"
    replica_count    = "3"
    service_port     = "80"
    container_image  = "publicrepo/helm-app"
    image_version    = "1.10"    
    ingress_configured = true
    path_prefix        = "custom-message"    
    message          = "test-2"
  }

}

I'm thinking of a range but I'm kinda lost, in my Ingress.yaml:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-ingress
spec:
  rules:
  - http:
      paths:
      {{- range .Values.ingress}}
      - pathType: {{ .pathPrefix }}
        backend:
          service:
             name: {{ include "helm-app.name" . }}
             port: 
              number: {{ .Values.ingress.port }}
        path: {{ .Values.ingress.path }}
      {{- end}}

I have some values in the values.yaml, but the idea is to override those and pass the values with Terraform as seen above.


Solution

  • I ended up by using an Ingress resource from Kubernetes Terraform provider:

    So this way the Dynamic Block will iterate to the new releases in the variable and add them to the paths.

    resource "kubernetes_ingress_v1" "ingress-nginx" {
      wait_for_load_balancer = true
      metadata {
        name = var.ingress_name
        namespace = var.ingress_namespace
        annotations = {
          "kubernetes.io/ingress.class" = "nginx"
          "nginx.ingress.kubernetes.io/rewrite-target" = "/$2"
        }
      }
      spec{
        rule {
          http {
            dynamic "path" {
              for_each = var.releases_map
              content {
                backend {
                  service {
                    name = "helm-app-${path.key}"
                    port {
                      number = path.value.service_port
                    }                
                  }
                }
                path = "/${path.value.path_prefix}(/|$)(.*)"
              }
            }
          }
        }
      }
    }