為什麼Docker容器不適合資料庫服務(一)

標題出自一篇博文

Why databases are not for containersmyopsblog.wordpress.com圖標

該文章在 Y-Combinator 上引起了熱烈的討論,討論的帖子內容似乎比原博文更有價值....

討論帖翻譯如下(原貼時間2017年2月開始,非常長,分為幾部分翻譯,略過了一些很簡短無意義的回復)

XorNot

這篇文章太差勁了。泛泛而談缺少技術細節--並沒有任何證據佐證他所列出來的觀點。我在 Docker 容器中做了大量 Hadoop/Hbase的基準測試,並沒有性能上的差異。穩定性也沒什麼不同(哦,節點可能 crash?300個節點的集群中這樣的事情幾乎每天都會發生)。

任何資料庫集群都應該能從節點失效中恢復。通常的關係型資料庫通過備份和郵件報警也差不多可以做到自動恢復。容器化並不會讓這一過程變得更困難或更輕鬆,但是容器化對測試和部署非常有幫助。

wkd

我同意你的說法,但是我還是想提醒一些用戶不要太著急把生產環境上的什麼東西都容器化。 如果你的環境不具備可複製性而且也配置管理也不可控,那麼你會遇到麻煩。使用 Docker 只會給原本一團糟的架構多加一層抽象,如果出了問題 DBA 將束手無策。我可以想像得到,對 docker 卷的不正確理解可能會坑到一些人,而且網路的配置還有一些值得商榷的默認值(userland proxy,rewriting iptables)。

儘管這麼說,我們還是有Docker 化的資料庫用於生產,主要是面向一些基本空閑的服務(mongodb for graylog,zookeeper for kafka)。在適當的負載情況下(每秒數千次寫入redis/kafka,對 redis 和 kafka 來說就是毛毛雨)並沒有遇到什麼問題。

大部分情況下我們還是使用非容器化的資料庫服務,它們獨佔 bare metal 虛擬機。因為我不覺得有任何風險-收益值得去這麼做(將它們Docker化)。但是我很樂意聽一聽其他人大規模地在Docker 中跑資料庫的故事。

對於開發而言,在 Docker 中運行資料庫是再合適不過了,甩手動安裝、虛擬機、共享開發機好幾條街。我覺得教育你團隊里的每個人去使用這種技術是值得的。使用 Docker 即使是搭建一個非常複雜的開發環境也會變得非常簡單。

alexnewman

是的,docker 的卷脫離於 unionfs 。這篇文章充滿了妄惻(FUD),暴露了作者他們對自己所說的東西毫無經驗。我想知道 Google 是否有在容器中跑資料庫節點?

jdc0589

我也對此好奇了很久。我敢肯定某些大玩家(公司)這麼幹了,我很想看到他們的案例研究報告。

derekperkins

Youtube在 Borg 中跑 MySQL,他們開源了管理方案 Vitess - Database Clustering System for Horizontal Scaling of MySQL

mondoshawan

Google他們內部也有在 Borg 中跑 MySQL。

bhntr3

Hadoop 和 HBase 與 mysql 的差異太大了,他們本來是跑在 yarn 之上,本來就是為容器而設計的。關於「通常的關係型資料庫也差不多可以做到自動恢復」:

以我的經驗,大部分人不會開啟自動恢復。對於 mysql 容器而言,我認同文中的那些考慮是合理且重要的。

更新:我確實覺得這篇文章把容器和 kubernetes/mesos奇怪地攪合在了一起。關於在容器中運行關係型資料庫的論據還是合理的。

guardiangod

你是在告訴我你會那麼信任 MySQL 的自動複製恢復功能,每天激活它好幾次?在一個繁忙的集群上,比如說300GB?

subway > guardiangod

這是個誤區(Seems like a straw-man). 為什麼在容器中的進程就一定比運行在 bare metal上的進程會更頻繁的 failover 呢?(觸發 failover)更像是資源或者進程調度導致的問題,和容器並沒有太大關係。

guardiangod > subway

且不說容器化增加了一層抽象引入的 bug,暗示容器技術沒有bare metal 可靠也不是個誤區。或者,你認為 Docker 和 bare metal 一樣可靠嗎?

你可以看看 Docker 的介紹,注意他們聲稱 Docker 是:

1. 更輕量

2. 易運行

3. 安全

完全沒有說「更可靠」。我在設計系統時有用 Docker;我可以意識到容器技術的限制。我的職責就是排除這些坑。

tazjin > guardiangod

這個討論需要區分開Docker 和容器技術,前者只是一個產品。合理地使用 kubernetes 就可以避免很多使用 Docker 遇到的問題(比如卷管理),不需要關心 Docker 在做些什麼。

「你認為 Docker 和 bare metal 一樣可靠嗎」 這個問題毫無意義。Docker 作為一個產品當然有很多問題,但是容器技術並沒有。你怎麼區別二者?chroot 和 bare metal 一樣可靠?什麼時候容器不是運行在 bare metal 之上呢?

guardiangod > tazjin

Linux 內核的Namespace當然是非常成熟的。但是如果人們只是使用 Namespace 那就沒有必要使用 Docker 和其他的特性了--人們會停留在 LXC(無意冒犯 LXC)。人們需要整體的評估一個軟體,而非單獨看它核心的技術。我個人認為 Docker 的成熟性還未得到驗證。無狀態的應用?很好。有狀態?那還是算了吧...

正如你說的,如果人們用 kubernetes 而不是 Docker,很多問題將不復存在。同樣的,如果人們使用 PostgreSQL 而不是 MySQL很多副本相關的問題也會消失。我想表達的是,如果一個新手把不成熟的技術攪合在一起,他會遇到不必要的麻煩。

subway > guardiangod

從來沒有人說容器技術比其他運行進程的方法更可靠,只是說運行在容器中的進程不會比非容器化的進程更不可靠。

除非你搞錯了,Docker(和其他 Linux 容器系統一樣)只是名空間隔離了你的進程,並沒有額外的抽象層,它只是一個更受限的執行環境。

throwawayish > subway

我遇到的Docker 的那些穩定性和性能上的問題(不只是在容器內,還影響到了 main cgroup 和宿主機),卻從沒有在 LXC 上遇到過,按你的說法 LXC 和 docker 都「只是名空間隔離了你的進程」,這解釋不通。

Docker 很好,當它正常工作時。但是不正常時就會遇到很多 bug 和經常性的 regress。我不理解為什麼要把生產基礎設施運行在 Docker 之上,而不是其他替代方案。

user5994461 > subway

FYI: 網路和磁碟是完全抽象出來的,有多層相當複雜的抽象。

brobinson > user5994461

並不一定,你可以用 `--net=host and -v /db_data:/db_data`. 用這種方式,進程在 Docker 內的磁碟和網路性能和直接運行在 host 上沒有任何區別。

如其他人提到的,這篇文章真的很糟糕。

gnufied > user5994461

掛載在容器中的卷跳過了 unionfs。使用容器內的分區或者 host 上的分區沒有本質上的不同。

user5994461 > subway

"為什麼在容器中的進程就一定比運行在 bare metal上的進程會更頻繁的 failover 呢?" -- 因為對容器中的任何東西做變更的方法是 kill 然後 restart。這從根本上與管理非容器內的資料庫不同。

subway > user5994461

只要你寫的軟體不是很爛,你都可以發送 SIGTERM 殺死它,然後等待它退出。不管是在容器內還是容器外這都是正確的。

事實上 `docker kill` 默認使用 SIGKILL 而不是 SIGTERM 是個悲劇,使用 Docker 部署進程之前需要注意這一點。但是,這也並不會讓容器內的進程更不可靠。

更新:貌似 `docker stop`做了正確的事情--發送 SIGTERM 然後如果超時才會回退到SIGKILL. (值得一提,docker stop的超時是可配置)

ec109685 > user5994461

你不用這麼運維容器。如果你需要推送配置到容器內,你可以把它改為可寫的。

To be continued.


推薦閱讀:

什麼鬼!基於備份恢復的數據還能變多?
Python採集微博熱評進行情感分析祝你狗年脫單
循序漸進學習如何在 MariaDB 中配置主從複製
七周成為數據分析師:SQL,從熟練到掌握

TAG:Docker | 容器虛擬化 | 資料庫 |