前言

近期,客戶需要主動提供商品資料給我們,而且是要是用提供 api 的方式,但是需要綁固定 IP。也就是說,只有客戶允許的 IP 列表 ( 白名單 ) 才能讀到 api 的資料。但我們的服務是使用 GKE 的 Cronjob,所以問題就變成: 要怎麼在 GKE 上綁固定 IP 呢?

概念

透過建立 VPC ( Virtual Private Cloud ) 來控制 GKE 內部網路的串連、分配子網路。並經由 Cloud Router 來處理與 外網其他 VPC 連接的路由,最後經由 Cloud NAT 來管理出站流量。此時,出站流量就可以綁定固定的 External IP,這樣所有從 VPC 出去的請求都會有固定的 IP。

檢查 Node 節點 IP

在 GKE 中,Pod 通常會使用節點 (Node) 的外部 IP 來進行對外的 API 請求。可以使用指令 kubectl get nodes -o wide 來查看節點的外部 IP。

取得節點 IP

即便使用 Cloud NAT 綁固定 IP 後,執行 kubectl get nodes -o wide 顯示的 EXTERNAL-IP 也會是 None,因為我們不是針對 Node 綁 IP。雖然每個 Node 也可以單獨綁對外的 External IP,是透過在 VPC 的 RESERVE EXTERNAL IP ADDRESS 的設定中,可以綁單獨一個 Node ,但是我們沒這麼做,因為我們程式是跑排程, Node 執行完可能會因閒置而被被刪除。

單獨節點綁固定 IP

Node 執行完會被刪除的原因: 是因為的 Node Pool 的機器有設定 Autoscaling, 加上我們是跑排程,所以執行完後閒置的 Node 會被自動刪除。

閒置節點會因 autoscaling 設定而被刪除

Step 1 - 建立 VPC 網路

  • 用意: 建立一個虛擬的雲端私有網路,與 外部網路其他 VPC 網路 隔離

  • 新增 Subnet 子網路,Primary IPv4 range 需跟 Node Pool 的 Node Networks 對到,Region ( 地區 ) 是 asia-east1 ,有包含 Zone ( 可用地區 ) asia-east1-a

    • 子網路 ( Subnet ): 在 VPC 中可建立多個子網路,來劃分不同的 IP 範圍和網路區域

      • Primary: 給 VM 或 Node 使用的
      • Secondary: 給 Pod 使用的
    • Private Google Access: 即使 VM 或其他 GCP 資源沒有公共 IP 地址,仍可以通過 VPC 的內部網路訪問 Google 的公共 API 服務,例如 Google Cloud Storage, BigQuery, Pub/Sub 等。即使有公共 IP,VM 仍會優先使用內部網路,因為更安全、更有效率。

      新增 Subnet 子網路

  • 找出 Node 隸屬於哪個 Node Pool,查看其對應的網路 IP

    • Pod IP address ranges 是 Pod 彼此溝通的內網 IP

      查看 node pool 的 node networks

Step 2 - 建立 Cloud Router

  • 用意: 讓 VPC 內網流量,都由這個路由與 外網其他 VPC 對接。
  • Advertised route configuration: 主要是讓外網知道怎麼連進你的 VPC 內網,並路由流量到你的 VPC 內部資源,所以如果不要讓外網連,要設定 No。
    • VPC 是封閉的網路環境,內部資源通常無法直接被外部網路訪問,除非配置了適當的路由和安全設置。

      建立 cloud router

Step 3 - 建立 External IP Address

  • 手動保留 IP: Reserve External IP

  • in used by 一開始會是 none,要透過 Cloud NAT 綁定 IP,才會顯示成 Router

    保留 External IP

  • 如果直接刪掉 Cloud NAT,這個 IP Address 會直接消失。

    • 若要保留 IP,先把 Cloud NAT 設定成 Automatic Method,這會讓 in used by 會變成 None

      刪除 Cloud Nat 後,仍要保留 External IP

Step 4 - 建立 Cloud NAT

  • Cloud NAT 的 VPC, Cloud Router, Region 都選剛剛建立的

    建立 Cloud Nat

  • Cloud NAT IP Address 設定成 Manual Method,選擇剛預留的 IP Address

    選擇 manual method 設定 IP

測試

  • 建立測試的 Pod

  • Yaml 如下設定,雖然 Pod 本身並不是一個 “workload kind”,但仍然可以直接創建一個 Pod 來測試某些功能

    test-pod.yaml
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    apiVersion: v1
    kind: Pod
    metadata:
    name: curl-pod
    labels:
    app: curl-pod
    spec:
    containers:
    - name: curl-container
    image: curlimages/curl:latest
    command: ["sleep", "3600"]
  • 將 Pod 部屬到 GKE 上:kubectl apply -f test-pod.yaml

  • 進入這個 Pod 的 shell:kubectl exec -it curl-pod -- /bin/sh

  • 在 Pod 中,使用 curl 或其他命令來檢查出站 IP 地址:curl http://ifconfig.me

    測試結果

  • 測試完後刪除 Pod:kubectl delete pod curl-pod

    • 在 GKE 上觀察測試的 pod

    觀察 GKE 上的測試 Pod