Engineering · 3 min read
Headless Service:用電話簿取代總機
Headless Service 直接回傳 Pod IP,不經過 proxy 路由。這一個改變就能修復 CDP GUID race,讓兩步連線固定打到同一個 Pod。
Regular vs Headless
Regular Service = 總機。你打一個號碼,總機隨機轉接。兩通電話可以接到不同人。
Headless Service = 電話簿。你拿到所有分機號碼,自己選一個直撥。
為什麼這能修復 GUID Race
API Pod 查 DNS,拿到所有 Chrome Pod 的 IP(不是一個 proxy IP)。選一個,GET 和 WebSocket 都打給它。兩步到同一支 Chrome,GUID 一定對。
var chromePodRoundRobin atomic.Uint64
addrs, _ := net.LookupHost(hostname)
idx := chromePodRoundRobin.Add(1) % uint64(len(addrs))
podAddr := net.JoinHostPort(addrs[idx], port)
// GET 和 WebSocket 都用 podAddr
DNS 只回傳 Ready 的 Pod IP。正在啟動或 probe 失敗的 Pod 不會出現。retry 時重新查 DNS,可以切換到另一個 Pod。「逃離壞掉的 Pod」的能力保留了。
一個 Request 的完整流程
每個 request 跑在自己的 goroutine 裡。五個步驟都用同一個局部變數 podAddr。
Round-robin 計數器(atomic.Uint64)是所有 goroutine 之間唯一的共享狀態。其他東西都是局部的:podAddr、GUID、chromedp session。不用 mutex,沒有 data race。延伸閱讀:為什麼每次都要重新連線。
clusterIP 是 immutable 的。你不能把現有的 Service 從 Regular 改成 Headless。Kubernetes 會拒絕更新。必須刪掉重建。ArgoCD 需要
Replace=true加Force=truesync options。
參考來源:
Related: 看為什麼每次都要重新連線、這個方案修復的 GUID race、DNS 容量模型,或回到系列總覽。