為什么我不再使用Alpine Linux?
原文連接:https://www.sohu.com/a/662909120_121124377
現(xiàn)在,Alpine Linux 已經(jīng)成為最受歡迎的容器基礎(chǔ)鏡像之一。許多人(你可能也是其中之一)用它干很多事情。有些人選擇 Alpine 是因為它體積小,有些人是因為習(xí)慣,還有些人可能只是從某個教程中復(fù)制粘貼了 Dockerfile。但是,也有很多人告訴你,在某些情況下不應(yīng)該使用 Alpine 作為容器鏡像,因為這可能會給你帶來麻煩。
#01
麻煩的根源
要了解 Alpine 在某些情況下為什么不是一個好選擇,我們首先需要談?wù)撘幌?musl。musl 是 C 標準庫的一種實現(xiàn)。相對于其他 Linux 發(fā)行版(如 Ubuntu)所使用的 glibc,musl 更輕量、更快、更簡單。大部分情況下,這兩種實現(xiàn)可以互換,這就是為什么你可以從 Ubuntu 切換到 Alpine 而幾乎察覺不到任何差異。
然而,正是這些微小的差異可能帶來一系列麻煩。其中一些問題源于 musl(因此也包括 Alpine)如何處理 DNS(怎么總是 DNS?)。更具體地說,musl(出于設(shè)計考慮)不支持 DNS-over-TCP。
通常情況下,你可能不會注意到這種差異,因為大多數(shù)情況下,一個單獨的 UDP 數(shù)據(jù)包(512 字節(jié))足以解析主機名…… 直到有一天,當某些外部網(wǎng)絡(luò)變化導(dǎo)致解析某個特定域名需要超過單個 UDP 數(shù)據(jù)包可容納的 512 字節(jié)時,你的應(yīng)用程序(在 Kubernetes 上運行)突然對一個非常關(guān)鍵的主機名拋出 “Unknown Host” 異常。最糟糕的是,這個問題可能隨機出現(xiàn),只要某些外部網(wǎng)絡(luò)變化導(dǎo)致解析某個特定域名需要更多字節(jié),就可能會發(fā)生這種情況。
通過使用 Alpine,你實際上為你的集群獲得了一種 “免費” 的混沌工程。
如果你運行幾十甚至數(shù)百個基于 Alpine 的微服務(wù)/應(yīng)用程序,它們突然停止工作,唯一的解決方法是切換到另一個 Linux 發(fā)行版,這將需要重新構(gòu)建所有應(yīng)用程序并重新部署,那么你可能面臨著一個極具破壞性的、持續(xù)好幾天的停機時間。
這個 DNS 問題不會在 Docker 容器中暴露出來。它只會在 Kubernetes 中發(fā)生,所以如果你在本地進行測試,一切工作都正常,只有在將應(yīng)用程序部署到集群中時才會發(fā)現(xiàn)無法解決的問題。此外,Kubernetes 文檔聲稱 DNS 問題只與 “Alpine 3.3 或更早版本”,但我在 Alpine 3.16 上也遇到了上述問題,所以你可以自行判斷。
作為額外福利,許多流行的工具也使用 Alpine 作為基礎(chǔ)鏡像,例如 nicolaka/netshoot 或 giantswarm/tiny-tools,前者專門用于網(wǎng)絡(luò)故障排除。當你的網(wǎng)絡(luò)故障排除工具本身也出現(xiàn)問題時,那只能祝你好運了。
#02
其他問題
雖然 DNS 問題是 musl 的最常見問題,但還有更多原因要重新考慮使用它。任何依賴于 C 標準庫的編程語言或其庫都會受到 musl 和 glibc 之間差異的影響。
例如,對于 Python 來說,許多流行的庫如 NumPy 或 Cryptography 依賴于 C 代碼進行優(yōu)化。幸運的是,至少對于像 NumPy 這樣的一些庫,你很有可能找到基于 Alpine 編譯的軟件包和相關(guān)依賴項。
然而,對于不太流行的庫,你可能需要自己進行編譯,但是這樣做值得嗎?在我看來…… 不值得。此外,即使你成功構(gòu)建了一個包含 NumPy 等庫的鏡像,其大小也將達到約 400MB,這時候使用 Alpine 來節(jié)省空間并沒有太多幫助。
FROM python:3.11-alpine
RUN apk --update add gcc build-base
RUN pip install --no-cache-dir numpy
另一個例子是 Golang,其標準庫(特別是 net/http 或 os/user 模塊)依賴于 C 庫,因此也依賴于 glibc。即使你不使用這些特定模塊,如果你的應(yīng)用程序需要設(shè)置 CGO_ENABLED=1,那么在 Alpine 上也可能會遇到問題。
#03
代替方案
如果上述問題促使你重新考慮使用 Alpine,你可能會想知道有什么可以使用的代替方案。其實選擇有很多,而且它們各有優(yōu)缺點,使用的時候需要你來權(quán)衡。
Alpine 最大的吸引力在于其小巧的體積,所以如果你非常關(guān)注這一點,那么 Wolfi(例如,cgr.dev/chainguard/wolfi-base 只有 12MB)或 Distroless 是不錯的選擇。
如果你需要一個大小合適且不基于 musl 的通用基礎(chǔ)鏡像,那么可以考慮使用 Red Hat 提供的 UBI(Universal Base Image),其 “micro” 版本只有 26.7MB(registry.access.redhat.com/ubi8-micro),這與 Alpine 相差無幾。
選擇 Alpine 的另一個原因是其安全性。這也與其小巧的體積有關(guān),因為小巧的體積通常意味著較少的軟件包,從而減少了潛在的漏洞。前面提到的 Wolfi 鏡像在這方面特別出色。
但是實事求是地說,除非你需要頻繁拉取鏡像(你可能本應(yīng)該避免這樣做),否則通過 Alpine 的小巧體積節(jié)省幾兆字節(jié)的空間可能并不重要,因此基于 Ubuntu 或 Debian 的基礎(chǔ)鏡像也是不錯的選擇。
#04
結(jié)論
總之,雖然使用 Alpine 沒有問題,并且作為基礎(chǔ)容器鏡像操作系統(tǒng)是很好的選擇,但就我個人而言,因為前面描述的 DNS 問題,我可能再也不會完全信任它,也不會信任使用 musl 的其他系統(tǒng)。
本文的目的不是詆毀 Alpine,而是提醒人們。盡管 Alpine 可能看起來是一個不錯的選擇(考慮到上述問題),但至少是有一定風(fēng)險的,在某些特定情況下決定使用 Alpine 可能是很魯莽的。當然,Alpine 也有許多優(yōu)點,所以如果你不擔(dān)心或不受本文描述的問題影響,那么繼續(xù)使用它也是可以的。
因此,我們應(yīng)該得出結(jié)論:在決定使用任何東西(無論是容器操作系統(tǒng)、框架還是庫)之前,要進行合理的研究。一個系統(tǒng)受歡迎并且聲譽良好并不意味著它會自動成為一個好的選擇。
- END -
推薦閱讀
30天拿下高含金量K8s CKA+CKS雙認證! ![]()
阿里 Nacos 高可用集群部署
一位老架構(gòu)師的忠告:別想著靠技術(shù)生存一輩子 神器 Nginx 的學(xué)習(xí)手冊 ( 建議收藏 ) K8S 常用資源 YAML 詳解 DevOps與CI/CD常見面試問題匯總
我會在Docker容器中抓包了! 19 個 K8S集群常見問題總結(jié),建議收藏 運維高可用架構(gòu)的 6 大常規(guī)方案
運維監(jiān)控指標全方面總結(jié) 9 個實用 Shell 腳本,建議收藏!
詳解 K8S Helm CI/CD發(fā)布流程
ES+Redis+MySQL,這套高可用架構(gòu)設(shè)計太頂了! 一臺服務(wù)器最大能支持多少條TCP連接? K8S運維必知必會的 Kubectl 命令總結(jié)
16 張圖硬核講解 Kubernetes 網(wǎng)絡(luò)
史上最全 Jenkins Pipeline流水線詳解 主流監(jiān)控系統(tǒng) Prometheus 學(xué)習(xí)指南 搭建一套完整的企業(yè)級 K8s 集群(二進制方式)
40個 Nginx 常問面試題 Linux運維工程師 50個常見面試題
點亮,服務(wù)器三年不宕機 ![]()

