Localhost 迷航記
當 localhost 不再是 localhost 時
文章目錄
故事背景稍微介紹一下,使用者反映 Fission基於 Kubernetes 之上的 FaaS (Function-as-a-Service) 框架
在週末突發性的無法正常運作。作為一個興趣使然的工程師,遇到使用者反應問題當然要 (義不容辭) 協助排解。
經過各種遠端通靈一種在不知曉確切運作環境或對於問題毫無頭緒下,仍然嘗試除錯的技術
,發現問題發生在當要初始化使用者的 function 時出現。
Fig. 1 Fission function pod specialization process
整個初始化流程如 Fig. 1,首先 executor 會送出 specialize
請求給 fetcher
,讓它取得 function code 後放至 share volume 內。
再由 fetcher 呼叫 env runtime
,讓其載入 function code 後服務 HTTP 請求。
"logger":"fetcher"
"msg":"error connecting to function environment pod for specialization request, retrying"
"error":"dial tcp 10.58.152.224:8888: i/o timeout"
從日誌上來看錯誤是 i/o timeout。奇妙的地方在於本來是呼叫 localhost
,卻顯示 10.58.152.224
超時 ?!
而用戶反應問題是在公司開始導入 proxy 後發生的,到這邊可能性有兩個:
- Proxy 設定出現異常,導致 Pod 內部的本地端 HTTP call 被攔截送往其他地方
- DNS 解析出現錯誤
原本想說會不會跟 docker 的 NO_PROXY 設定相關,但該設定主要跟 pull image 相關且測試後也驗證不是這個原因。
事已至此,剩下 DNS 解析出錯的可能性,也只能開始往最瞎的方向開始思考:
是不是在 namespace 底下有個名為
localhost
的服務存在?
Fig.2 為 Kubernetes 內 Pod 做 DNS 解析時的流程圖
Fig. 2 Kubernetes Pod DNS
當遇到域名時,整個解析過程的順序如下
- 向 kube-dns 詢問解析結果
- 若 cluster 內沒有對應記錄就繼續往上游 DNS 查詢
- 如果都沒有任何結果的話,查看本地端的
/etc/resolv.conf
好玩的是,其實 Kubernetes 允許建立名為 localhost
的服務,因此在 Pod 內查詢時就會被 kube-dns 當成
localhost.default.svc.cluster.local
所以正常狀況下會得到 127.0.0.1
的結果
root@helloworld-v1-7c45d5f8c4-8nzb7:/# nslookup localhost
Server: 10.96.0.10
Address: 10.96.0.10#53
Non-authoritative answer:
Name: localhost
Address: 127.0.0.1
在當 localhost 同名 kubernetes service 存在時,kube-dns 會回傳該 service 的 cluster ip。
$ kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
localhost NodePort 10.104.136.35 <none> 5678:32116/TCP 3m42s app=localhost
root@helloworld-v1-7c45d5f8c4-8nzb7:/opt/microservices# nslookup localhost
Server: 10.96.0.10
Address: 10.96.0.10#53
Name: localhost.default.svc.cluster.local
Address: 10.104.136.35
可以看到問題極有可能是因為 DNS 解析順序問題導致的,但套句歪國人常講的話
Who on earth would do something like that?
在 namespace 底下建立 localhost 服務,就像常見的工程師惡搞笑話一樣
還好結論不是因為有人創建 localhost 在惡搞 (雖然相差不遠),而是他們公司有人將自己電腦的 DNS 設定成 localhost.company.com
,
所以 upstream DNS 在解析後回傳該電腦的 IP。(果然神的都是別人隊友)
既然知道問題點後,解決方式也相當簡單,改用 127.0.0.1
取代 localhost
即可。
此議題進一步延伸,甚至能根據企業需求達成轉發流量至其他服務做流量處理, 或企業內部被惡意攻擊植入偽造 DNS record 時產生潛在問題。 因此加掛 custom DNS 時要特別注意其安全性及解析先後順序,避免意外發生。
最後使用者表示:
some idiot in our company has named his computer “localhost” ….
但我猜他心裡想講的話,翻譯成中文最接近的意思大概是
誰幹的,給我出來! 我保證不一槍打死你
這是近期遇到最奇耙的 issue,希望不要再有下個啊! XDD
最後附上血淋淋的 PR 給大家笑笑: https://github.com/fission/fission/pull/1227
相關文章
- Adopting Container and Kubernetes in Production
- Fission 1.4 更新重點聚光燈
- Fission - Serverless Framework For Kubernetes
- 邊車模式 (The Sidecar Pattern) - 介紹
- Designing Distributed Systems 導讀
文章內容的轉載、重製、發佈,請註明出處: https://tachingchen.com/tw/
Twitter
Google+
Facebook
Reddit
LinkedIn
StumbleUpon
Pinterest
Email