GKE 如何綁對外的固定 IP ? 利用 VPC 網路、Cloud Router、搭配 Cloud NAT 設定 External IP Address
前言
近期,客戶需要主動提供商品資料給我們,而且是要是用提供 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。
即便使用 Cloud NAT 綁固定 IP 後,執行 kubectl get nodes -o wide
顯示的 EXTERNAL-IP 也會是 None,因為我們不是針對 Node 綁 IP。雖然每個 Node 也可以單獨綁對外的 External IP,是透過在 VPC 的 RESERVE EXTERNAL IP ADDRESS 的設定中,可以綁單獨一個 Node ,但是我們沒這麼做,因為我們程式是跑排程, Node 執行完可能會因閒置而被被刪除。
Node 執行完會被刪除的原因: 是因為的 Node Pool 的機器有設定 Autoscaling, 加上我們是跑排程,所以執行完後閒置的 Node 會被自動刪除。
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 仍會優先使用內部網路,因為更安全、更有效率。
找出 Node 隸屬於哪個 Node Pool,查看其對應的網路 IP
Pod IP address ranges 是 Pod 彼此溝通的內網 IP
Step 2 - 建立 Cloud Router
- 用意: 讓 VPC 內網流量,都由這個路由與 外網或 其他 VPC 對接。
- Advertised route configuration: 主要是讓外網知道怎麼連進你的 VPC 內網,並路由流量到你的 VPC 內部資源,所以如果不要讓外網連,要設定 No。
VPC 是封閉的網路環境,內部資源通常無法直接被外部網路訪問,除非配置了適當的路由和安全設置。
Step 3 - 建立 External IP Address
手動保留 IP: Reserve External IP
in used by 一開始會是 none,要透過 Cloud NAT 綁定 IP,才會顯示成 Router
如果直接刪掉 Cloud NAT,這個 IP Address 會直接消失。
若要保留 IP,先把 Cloud NAT 設定成 Automatic Method,這會讓 in used by 會變成 None
Step 4 - 建立 Cloud NAT
Cloud NAT 的 VPC, Cloud Router, Region 都選剛剛建立的
Cloud NAT IP Address 設定成 Manual Method,選擇剛預留的 IP Address
測試
建立測試的 Pod
Yaml 如下設定,雖然
Pod
本身並不是一個 “workload kind”,但仍然可以直接創建一個 Pod 來測試某些功能test-pod.yaml 1
2
3
4
5
6
7
8
9
10
11apiVersion: 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