GKE の Ingress で Load Balancer を作成すると、同一 namespace 内の Service にしか振り分けられないとか、単一の Cluster でしか使えないとか不都合な場合があります。その場合 Load Balancer 関連のリソースは Terraform で作成したくなりますが、NEG まで作らなければ BackendService を作成できません。 しかし、NEG は GKE のコントローラが作成するため、鶏卵問題で悲しい思いをしたことはないでしょうか。 この NEG は GKE が作るのを待たずに Terraform で作成することも可能だったのでそのメモです。
答えを先に書いておくと、次のようになります。
data "google_compute_zones" "available" {}
resource "google_compute_network_endpoint_group" "igw" {
for_each = toset([for zone in data.google_compute_zones.available.names : zone if substr(zone, 0, length(var.region)) == var.region])
name = "${var.env}-igw"
description = "{\"cluster-uid\":\"${data.kubernetes_namespace_v1.kube_system.metadata[0].uid}\",\"namespace\":\"istio-ingress\",\"service-name\":\"istio-ingressgateway\",\"port\":\"80\"}"
network = google_compute_network.vpc.id
subnetwork = google_compute_subnetwork.tokyo.id
zone = each.key
depends_on = [
google_container_cluster.cluster,
]
}
ポイントは description に謎の JSON をセットしている部分です。 GKE のコントローラが作成する場合にこれがセットされるようになっており、それを真似て作ってやると endpoint として GKE の Pod が登録されるようになります。
{
"cluster-uid": "5052b0f9-569a-44cc-a407-72554fb21913",
"namespace": "istio-ingress",
"service-name": "istio-ingressgateway",
"port": "80"
}
問題はこの cluster-uid というものの値はどこから取得できるのかということですが、kube-system namespace の metadata にある uid が使われるようです。(Google に確認しました)
NEG は Zonal リソースなので zone ごとに作成しています。 google_compute_zones という data source から対象のリージョンのものだけ取り出すようにしました。