在多年的雲端架構設計經驗中,玄貓發現在 Google Cloud Platform(GCP)上佈署應用程式並設定 HTTPS 負載平衡器往往是個耗時的任務。為瞭解決這個問題,我開發了一套根據 Terraform 的自動化解決方案,讓整個佈署流程變得更加順暢與可重複使用。

架構概觀與技術堆積積疊選擇

在開始實作之前,先讓我分享這套架構的核心元件。這個方案主要整合了以下關鍵技術:

  • GKE(Google Kubernetes Engine)作為容器管理平台
  • Istio 服務網格處理流量管理
  • Terraform 實作基礎設施即程式碼(Infrastructure as Code)
  • Google Cloud Load Balancer 提供負載平衡能力

基礎環境需求

在實作這套自動化佈署方案之前,我們需要確保以下前置條件:

  1. 一個運作中的 GKE 叢集
  2. 已經在叢集中佈署與可存取的應用服務
  3. 已設定的網域名稱(選用)- 如果需要 HTTPS 存取,則必須將網域名稱指向我們稍後建立的負載平衡器 IP

環境建置:GKE 叢集與基礎應用

讓我先展示如何佈署一個簡單的 Nginx 應用作為示範。以下是基本的佈署設定:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80

接著是服務設定:

apiVersion: v1
kind: Service
metadata:
  name: ngnix-service
spec:
  selector:
    app: nginx
  type: NodePort
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80

Istio 服務網格的安裝與設定

在多年的微服務架構實踐中,玄貓發現 Istio 是管理服務間通訊的絕佳選擇。讓我們使用 Terraform 來自動化 Istio 的安裝過程。首先,我們需要建立專屬的名稱空間:

resource "kubernetes_namespace" "istio_system" {
  metadata {
    name = "istio-system"
  }
}

這個名稱空間的建立是後續所有 Istio 元件佈署的基礎。在實際專案中,玄貓建議根據環境需求調整名稱空間的標籤和註解,以便更好地進行資源管理和監控。

透過這種方式,我們為後續的 Istio 功能佈署奠定了基礎。接下來,我們將探討如何設定 Istio 的其他核心元件,以建立一個完整的服務網格環境。

使用 Terraform 佈署 Istio 服務網格

在這個深入的技術實作中,玄貓將展示如何使用 Terraform 佈署 Istio 服務網格的關鍵元件。這個佈署過程涉及多個重要元件的設定,包括 Istio 的基礎設施、控制平面以及閘道器的設定。

Istio 基礎元件佈署

首先,玄貓需要佈署 Istio 的兩個核心元件:istio-base 和 istiod。這裡使用 Helm 進行佈署,確保元件間的依賴關係正確設定:

resource "helm_release" "istio_base" {
  name       = "istio-base"
  repository = "https://istio-release.storage.googleapis.com/charts"
  chart      = "base"
  version    = "1.14.1"
  namespace  = kubernetes_namespace.istio_system.metadata.0.name
}

resource "helm_release" "istio_discovery" {
  name       = "istiod"
  repository = "https://istio-release.storage.googleapis.com/charts"
  chart      = "istiod"
  version    = "1.14.1"
  namespace  = kubernetes_namespace.istio_system.metadata.0.name
  depends_on = [helm_release.istio_base]
}

程式碼解密

  • istio_base 資源負責佈署 Istio 的基礎元件,包含自定義資源定義(CRD)
  • istio_discovery 資源佈署 Istio 的控制平面,使用 depends_on 確保在基礎元件佈署完成後才執行
  • 兩個元件都佈署在專門的 istio_system 名稱空間中

Istio 閘道器設定

接下來佈署 Istio 閘道器,這是處理入站流量的關鍵元件:

resource "helm_release" "istio_ingress" {
  name       = "istio-ingress"
  repository = "https://istio-release.storage.googleapis.com/charts"
  chart      = "gateway"
  version    = "1.14.1"
  namespace  = kubernetes_namespace.istio_ingress.metadata.0.name
  values     = [file("${path.module}/istio/ingress.yaml")]
  depends_on = [helm_release.istio_discovery]
}

閘道器的設定檔案(ingress.yaml)包含以下重要設定:

service:
  type: NodePort
  annotations:
    "cloud.google.com/backend-config": '{"default": "ingress-backendconfig"}'
    "cloud.google.com/neg": '{"ingress": true}'

程式碼解密

  • istio_ingress 資源佈署閘道器元件,負責管理進入叢集的流量
  • 閘道器設定使用 NodePort 服務類別
  • 透過註解整合 Google Cloud 的後端設定和容器原生負載平衡功能
  • cloud.google.com/backend-config 註解連結到負載平衡器的健康檢查設定
  • cloud.google.com/neg 註解啟用容器原生負載平衡,實作 Pod 層級的流量分配

Istio 閘道器資源定義

為了完整設定閘道器功能,玄貓還需要佈署 Istio 閘道器資源:

resource "kubernetes_manifest" "istio_gateway" {
  count = var.use_crds ? 1 : 0
  manifest = {
    apiVersion = "networking.istio.io/v1alpha3"
    kind       = "Gateway"
    metadata = {
      name      = "istio-gateway"
      namespace = kubernetes_namespace.istio_ingress.metadata.0.name
    }
    spec = {
      selector = {
        istio = "ingress"
      }
      servers = [{
        hosts = ["*"]
        port = {
          name     = "http"
          number   = 80
          protocol = "HTTP"
        }
      }]
    }
  }
  depends_on = [helm_release.istio_base]
}

程式碼解密

  • 使用 kubernetes_manifest 資源定義 Istio 閘道器
  • 設定選擇器以識別入口閘道器
  • 設定 HTTP 流量處理,監聽 80 連線埠
  • 允許來自所有主機的流量(使用 “*” 萬用字元)

經過這些設定,玄貓已經建立了一個完整的 Istio 服務網格環境。這個設定不僅提供了強大的流量管理能力,還整合了 Google Cloud 的進階負載平衡功能。在實際應用中,這種設定能夠提供更好的流量控制、監控和安全性。

後續還可以透過虛擬服務(Virtual Services)和目標規則(Destination Rules)來進一步細化流量路由策略,實作更複雜的服務治理需求。這個基礎架構為微服務應用提供了可靠的服務網格基礎。

在現代雲端架構中,有效管理進入 Kubernetes 叢集的流量是一項關鍵任務。玄貓今天要分享如何使用 Terraform 在 Google Kubernetes Engine(GKE)上設定 Istio Ingress 與負載平衡器,這套設定不僅確保了流量的高效管理,還提供了完整的 SSL 支援。

後端設定與健康檢查

首先,讓我們來設定後端設定。在實際佈署過程中,我發現適當的健康檢查機制對於確保服務可靠性至關重要。以下是核心設定:

metadata = {
  name      = "ingress-backendconfig"
  namespace = kubernetes_namespace.istio_ingress.metadata.0.name
}

spec = {
  healthCheck = {
    requestPath = "/healthz/ready"
    port        = 15021
    type        = "HTTP"
  }
}

這段設定建立了一個後端健康檢查機制,玄貓特別選擇了 HTTP 類別的檢查,因為它能提供更細緻的健康狀態評估。在實務經驗中,這個設定幫助我們及早發現並解決了許多潛在的服務問題。

設定全域 IP 位址

在建立 Ingress 之前,我們需要設定一個固定的外部 IP 位址作為流量入口點:

resource "google_compute_global_address" "istio_ingress_lb_ip" {
  name = var.address_name != "" ? 
    "istio-ingress-lb-ip-${var.address_name}" : 
    "istio-ingress-lb-ip"
}

這個設定確保我們的服務擁有一個穩定的公開存取點。在生產環境中,固定 IP 對於 DNS 設定和服務可靠性來說都是非常重要的。

建立專用名稱空間

為了更好地組織和管理資源,我們建立一個專門的名稱空間:

resource "kubernetes_namespace" "istio_ingress" {
  metadata {
    name = "istio-ingress"
    labels = {
      istio-injection = "enabled"
    }
  }
}

這個名稱空間設定啟用了 Istio 的自動注入功能,這讓服務網格的管理變得更加順暢。在實務上,這種隔離方式讓我們能更有效地管理 Istio 相關的資源。

管理 SSL 憑證

在建置生產環境時,安全性是首要考量。Google Cloud 的託管憑證提供了一個簡單與可靠的方式來處理 SSL:

resource "kubernetes_manifest" "istio_managed_certificate" {
  for_each = toset([
    for host in var.istio_ingress_configuration.hosts : host.host
  ])

  manifest = {
    apiVersion = "networking.gke.io/v1"
    kind       = "ManagedCertificate"
    metadata = {
      name      = random_id.istio_ingress_lb_certificate[each.value].hex
      namespace = kubernetes_namespace.istio_ingress.metadata.0.name
    }
    spec = {
      domains = [each.value]
    }
  }
}

在我多年的雲端架構經驗中,使用託管憑證不僅簡化了 SSL 管理流程,還能自動處理憑證的更新,大幅降低了維護成本。

Ingress 設定詳解

最後,讓我們來看 Ingress 的完整設定:

resource "kubernetes_ingress_v1" "istio" {
  metadata {
    name      = "istio-ingress"
    namespace = kubernetes_namespace.istio_ingress.metadata.0.name
    annotations = {
      "networking.gke.io/managed-certificates"      = join(",", [
        for managed_cert in kubernetes_manifest.istio_managed_certificate : 
        managed_cert.manifest.metadata.name
      ])
      "kubernetes.io/ingress.global-static-ip-name" = google_compute_global_address.istio_ingress_lb_ip.name
      "kubernetes.io/ingress.allow-http"            = var.istio_ingress_configuration.allow_http
    }
  }

  spec {
    dynamic "rule" {
      for_each = [
        for host in var.istio_ingress_configuration.hosts : {
          host            = host.host
          backend_service = host.backend_service
        }
      ]
      content {
        host = rule.value.host
        http {
          path {
            backend {
              service {
                name = coalesce(
                  rule.value.backend_service, 
                  helm_release.istio_ingress.name
                )
                port {
                  number = 80
                }
              }
            }
          }
        }
      }
    }
  }

  depends_on = [helm_release.istio_ingress]
}

這個設定整合了多個重要元素:託管憑證、靜態 IP、HTTP 存取控制,以及動態路由規則。在實際佈署中,這種結構化的設定讓我們能夠靈活地管理多個網域名稱和後端服務。

透過以上的設定,我們建立了一個完整的 Istio Ingress 環境,不僅確保了流量的安全管理,還提供了靈活的路由控制。這套設定在我負責的多個大型專案中都證明瞭其可靠性和擴充套件性。在實施過程中,務必根據實際需求調整引數,特別是在安全性設定和效能最佳化方面。

經過這套設定的實施,我們的服務具備了企業級的負載平衡能力,同時保持了優異的安全性和可維護性。這正是現代雲端架構所追求的目標。

在建置現代化的雲端服務時,服務網格(Service Mesh)、SSL憑證管理和負載平衡是不可或缺的關鍵元素。作為一位經常處理大規模微服務佈署的技術工作者,玄貓發現許多團隊在這方面常遇到挑戰。今天,讓我分享如何在 Google Kubernetes Engine(GKE)上優雅地整合這些元件。

憑證與負載平衡的自動化設定

在實際專案中,玄貓發現手動管理SSL憑證既耗時又容易出錯。透過 Google 的受管憑證(Managed Certificates)服務,我們可以大幅簡化這個過程。以下是核心設定重點:

resource "kubernetes_manifest" "managed_certificates" {
  for_each = toset(var.istio_ingress_configuration.hosts)
  
  manifest = {
    apiVersion = "networking.gke.io/v1"
    kind       = "ManagedCertificate"
    metadata = {
      name      = "cert-${replace(each.value.host, ".", "-")}"
      namespace = kubernetes_namespace.istio_ingress.metadata[0].name
    }
    spec = {
      domains = [each.value.host]
    }
  }
}

設定解析說明

這段設定實作了幾個關鍵功能:

  • 自動為每個主機名稱生成對應的受管憑證
  • 在指定的名稱空間中建立憑證資源
  • 確保憑證與負載平衡器的自動繫結

Istio 虛擬服務的智慧路由

在建置微服務架構時,準確的流量路由至關重要。玄貓在多個專案中發現,透過 Istio 虛擬服務可以實作精確的流量控制:

resource "kubernetes_manifest" "istio_virtual_services" {
  for_each = var.use_crds ? var.virtual_services : {}
  
  manifest = {
    apiVersion = "networking.istio.io/v1alpha3"
    kind       = "VirtualService"
    metadata = {
      name      = each.key
      namespace = each.value.target_namespace
    }
    spec = {
      gateways = ["${kubernetes_namespace.istio_ingress.metadata.0.name}/${kubernetes_manifest.istio_gateway[0].manifest.metadata.name}"]
      hosts    = each.value.hosts
      http     = [{
        match = [{
          uri = {
            prefix = "/"
          }
        }]
        route = [{
          destination = {
            host = "${each.value.target_service}.${each.value.target_namespace}.svc.cluster.local"
            port = {
              number = each.value.port_number
            }
          }
        }]
      }]
    }
  }
}

路由設定解析

這個虛擬服務設定實作了:

  • 彈性的主機名稱路由
  • 精確的服務目標定位
  • 自動的連線埠對映處理

模組化佈署策略

在實務經驗中,玄貓發現模組化設定可以大幅提升佈署效率。這裡是一個實用的模組設定範例:

module "istio_gke" {
  source = "./istio"
  
  cluster_node_network_tags = []
  private_cluster          = false
  address_name             = "private"
  
  istio_ingress_configuration = {
    allow_http = false
    hosts = [
      {host = "demo.astrafy.online"},
      {host = "article.astrafy.online"}
    ]
  }
  
  virtual_services = {
    vs-vault = {
      target_namespace = "app"
      hosts           = ["demo.astrafy.online", "article.astrafy.online"]
      target_service  = "ngnix-service"
      port_number     = 80
    }
  }
  
  use_crds = false
}

這個模組化設定特別適合需要管理多個服務的場景。在實際佈署中,玄貓建議採用兩階段佈署策略:首先設定 use_crds = false 進行初始佈署,然後切換為 true 完成完整設定。這種方式可以有效避免因 CRD 未就緒導致的佈署問題。

在多年的雲端架構經驗中,玄貓觀察到此架構方案不僅簡化了管理流程,更為後續的擴充套件提供了靈活性。透過這種設定,一個負載平衡器就能優雅地處理多個服務,大幅降低了維運成本。最重要的是,憑證的自動管理讓團隊能夠專注於業務邏輯開發,而不必擔心基礎設施的細節問題。

在實際佈署後,通常需要等待約30分鐘讓 Google 完成憑證設定。這個等待時間是值得的,因為它為我們帶來了完全自動化的憑證管理體系。透過 Google Cloud Console 的負載平衡器頁面,我們可以輕鬆監控憑證的設定狀態,確保所有服務都受到適當的安全保護。 完成 DNS 指向由 Terraform 建立的 IP 位址後,我們就能透過 HTTPS 從瀏覽器存取網站。這套模組確實為我們在不同的 Google Kubernetes Engine(GKE)叢集上佈署公開應用程式節省了大量時間。當需要在新的叢集重複這個過程時,只需將其加入對應的 Terraform 模組,填入變數,就能輕鬆完成佈署。

不過在最佳實務方面,玄貓必須指出,使用 use_cdrs 變數來分兩階段安裝 Istio 的自定義資源定義(Custom Resource Definitions,CRDs)並不是最理想的做法,雖然這是最快速的方式。在從開發環境遷移到測試或正式環境時,我們不應該需要修改程式碼或切換任何標記的布林值。

理想情況下,在正式環境中應該能夠在單一計劃中完成所有操作。但由於目前尚未支援這種方式,我們需要採用其他策略,例如:

  • 在獨立的 Terraform 設定中安裝 CRDs
  • 使用 ArgoCD 等 DevOps 工具來管理佈署

這個模組還具備在私有叢集中使用的功能。在私有叢集的情境下,需要額外提供叢集所在的虛擬私有雲(VPC)和專案作為模組變數。雖然這個模組可能不適用於所有環境,可能需要根據特定使用情境進行一些調整,但玄貓的目標是讓開發者能夠全面理解這個佈署流程,並節省寶貴的開發時間。

透過這個實作經驗,玄貓認為在處理 GKE 叢集的公開服務佈署時,需要特別注意以下幾點:

  1. 安全性考量:確保所有對外服務都經過適當的安全控制
  2. 佈署流程的一致性:盡可能讓開發到正式環境的佈署流程保持一致
  3. 基礎設施即程式碼(Infrastructure as Code)的最佳實踐:維持程式碼的可重用性和可維護性
  4. 監控與維運:建立完整的監控機制,確保服務的穩定性

在實際佈署過程中,我們需要根據具體情況選擇最適合的實作方式。重點不在於遵循單一標準作法,而是在理解各種方案的優劣後,選擇最適合當前情境的解決方案。透過這種方式,我們能夠建立更穩健、更易於維護的基礎設施。