如何用Terraform为Ingress自动配置多后端服务
我正在通过Terraform的Helm Provider部署GKE集群与2个测试应用,这两个应用会输出自定义消息,期望Nginx Ingress能根据路径前缀转发至对应服务。目前手动将各Release的服务名添加到Ingress规则/后端可正常运行,但希望在执行terraform apply时自动完成该配置:部署Release与Ingress后,自动获取可用的服务名并传入Ingress,这样后续新增10个不同路径的Release时,只需在变量映射中添加配置即可。请问是否可行?能否像Terraform中那样将输出传递给变量?以下是我的Helm资源配置、releases_map变量配置及Ingress模板,希望通过Terraform覆盖values.yaml中的值来实现需求。
现有Helm资源配置
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 } . . }
releases_map变量配置
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-1" 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-2" message = "test-2" } }
Ingress模板(helm-app/templates/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}}
完全可行,核心思路是在Terraform中动态生成Ingress规则配置,并将其传递给Ingress的Helm Chart(或单独的Ingress Helm资源)。具体操作如下:
1. 过滤并生成Ingress规则列表
定义Terraform本地变量,从var.releases_map中筛选需要配置Ingress的应用(ingress_configured = true),整理成Ingress模板所需的结构:
locals { ingress_rules = [ for release_name, release_config in var.releases_map : { service_name = release_name # 若服务名与Release名称不一致,可从helm_release的输出属性中获取 service_port = tonumber(release_config.service_port) path_prefix = release_config.path_prefix } if release_config.ingress_configured ] }
2. 将动态规则注入Ingress Helm资源
根据你的部署方式选择以下两种方案:
方案A:单独部署Ingress Helm Chart
如果使用独立的Ingress-Nginx Chart,在对应的helm_release资源中传递生成的规则:
resource "helm_release" "nginx_ingress" { name = "nginx-ingress" chart = "ingress-nginx/ingress-nginx" namespace = "kube-system" repository = "https://kubernetes.github.io/ingress-nginx" set { name = "controller.service.type" value = "LoadBalancer" } # 将动态规则注入Chart的values values = [ yamlencode({ ingress = { rules = local.ingress_rules } }) ] }
方案B:复用应用Chart的Ingress模板
若Ingress模板属于应用自身的Chart,调整模板为条件生成,并在应用的helm_release资源中传递规则:
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"), yamlencode({ ingress = { enabled = each.value.ingress_configured rules = [ { service_name = each.key service_port = tonumber(each.value.service_port) path_prefix = each.value.path_prefix } ] } }) ] set { name = "deployment.replicaCount" value = each.value.replica_count } # 其他set配置... }
3. 修正Ingress模板语法错误
原始模板存在变量引用和参数错误,修正后如下:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: nginx-ingress spec: rules: - http: paths: {{- range .Values.ingress.rules}} - pathType: Prefix backend: service: name: {{ .service_name }} port: number: {{ .service_port }} path: {{ .path_prefix }} {{- end}}
4. 新增应用的操作方式
后续新增应用时,只需在var.releases_map中添加条目,设置ingress_configured = true并指定path_prefix,执行terraform apply后,Terraform会自动将新应用的服务信息注入到Ingress规则中,无需手动修改Ingress配置。
内容的提问来源于stack exchange,提问作者Kikeman26

