有一些公司認(rèn)為虛擬機(jī)已經(jīng)是昨兒黃花必須打倒,大家趕緊一切皆容器。軟件開(kāi)發(fā)和運(yùn)維活動(dòng)中,可維護(hù)性、正確性、性能的優(yōu)先級(jí)是依次降低的,那么對(duì)于虛擬機(jī) vs 容器,自然我們也需要從這三方面考察。
有一些公司認(rèn)為虛擬機(jī)已經(jīng)是昨兒黃花必須打倒,大家趕緊一切皆容器。軟件開(kāi)發(fā)和運(yùn)維活動(dòng)中,可維護(hù)性、正確性、性能的優(yōu)先級(jí)是依次降低的,那么對(duì)于虛擬機(jī) vs 容器,自然我們也需要從這三方面考察。
虛擬機(jī)—維護(hù)性
從 hypervisor 講,Xen/KVM/vSphere/HyperV 都很成熟了,久經(jīng)考驗(yàn),BSD 也在湊熱鬧搞 bhyve(FreeBSD) 和 vmm(OpenBSD),最近 unikernel 也在試圖跑在 hypervisor 上,而 AWS/GCE/Azure 等等
云計(jì)算巨頭以及 Intel/AMD 等在CPU、磁盤和網(wǎng)絡(luò)IO虛擬化技術(shù)上的投資顯然不會(huì)立馬推翻,Linux 上虛擬機(jī)的開(kāi)源管理方案也已成熟定型:libvirt, OpenStack,沒(méi)人吃飽了撐的去弄個(gè) “新的開(kāi)源” 項(xiàng)目替換它們,雖然我很不喜歡 OpenStack 的亂糟和復(fù)雜。VM 的動(dòng)態(tài)遷移也是成熟技術(shù),出來(lái)好多年了,實(shí)現(xiàn)原理非常簡(jiǎn)單,反正整個(gè) OS 內(nèi)存一鍋端弄過(guò)去,不操心少個(gè)依賴進(jìn)程的內(nèi)存沒(méi)過(guò)去。想用不同版本內(nèi)核? 想要自定義內(nèi)核模塊?想調(diào)整內(nèi)核參數(shù)?期望更安全的隔離?期望如同物理機(jī)版幾乎一致的使用體驗(yàn)?VM 就是虛擬機(jī)的縮寫嘛,這些都是拿手戲。
容器— 維護(hù)性
Linux 容器,Linux 一貫的作風(fēng),慢慢演化,不求仔細(xì)設(shè)計(jì),然后就是 cgroup, pid/uts/ipc/net/uid namespace 一個(gè)個(gè)實(shí)現(xiàn)出來(lái),湊出一個(gè)容器技術(shù),貌似 uid namespace 還是最近剛剛出來(lái)的特性。用戶
空間則更是群雄并起,LXC,Docker,rkt,LXD,各有擁蹇,鹿死誰(shuí)手,還真不好說(shuō),在這個(gè)局還沒(méi)明朗的時(shí)候,Mesos、Swarm、Kubernetes、Nomad 又出來(lái)一堆攪局的,眼下看來(lái)最吸引眼球的 Kubernetes 儼然有 OpenStack 繼任者的感覺(jué),但依然很嫩,沒(méi)幾個(gè)人敢在生產(chǎn)環(huán)境大規(guī)模使用。
Linux容器里進(jìn)程的跨機(jī)器動(dòng)態(tài)遷移我還沒(méi)聽(tīng)說(shuō),不要說(shuō)是個(gè)服務(wù)就得有集群有 HA 嘛,可還真有不少用戶一個(gè)服務(wù)就單機(jī)頂著呢,就算有熱備或者冷備,在線那臺(tái)機(jī)器內(nèi)存里的東西可寶貴了,輕易不能丟。用Linux容器就不能挑內(nèi)核,不能加載內(nèi)核模塊,不能掛載文件系統(tǒng),不能調(diào)整內(nèi)核參數(shù),不能改網(wǎng)絡(luò)配置,等等,不要告訴我你能——你是不是開(kāi)了 docker run –privileged 了? 你是不是沒(méi) drop capability?你是不是沒(méi)有 remap uid?話說(shuō)某大公司的容器還真就用 –privileged 選項(xiàng)跑的呢。 而 Linux 的隔離不徹底恐怕大部分人都沒(méi)意識(shí)到,/sys, /dev, /selinux 還有 /proc 下的某些關(guān)鍵文件比如 /proc/kcore 沒(méi)隔離呢。
Redhat 做的 project Atomic 意識(shí)到這些問(wèn)題,正在積極的給 Docker 加 SELinux 支持,指定 SELinux policy,但 Docker 官方愛(ài)搭不理,而且 SELinux 這種高端技術(shù)是凡人玩的么? 結(jié)局大概依然是 “FAQ 1: 關(guān)掉 SELinux”。Linux 容器本來(lái)并不局限在一個(gè)容器里跑幾個(gè)進(jìn)程,但 Docker 官方為了加強(qiáng)“輕量級(jí)”這詞的洗腦效果,搞出個(gè)無(wú)比腦殘的 single process 理念,被無(wú)數(shù)人捧臭腳,所幸有些人慢慢意識(shí)到問(wèn)題,Yelp 搞了個(gè) dumb-init 擦了一半屁股,還有無(wú)數(shù) docker image 用 runit、supervisor 之類的做 /sbin/init 替換,但問(wèn)題在于這要自定義啟動(dòng)腳本,需要加 ssh/cron/syslog/logrotate 等等邊角料——這已然是解決了無(wú)數(shù)遍的問(wèn)題,還要解決一遍,不覺(jué)得麻煩嗎?難道沒(méi)有人認(rèn)為這些包的作者或者打包者更善于處理服務(wù)啟動(dòng)腳本么?像 systemd 那種搞法還算正道,特意考慮容器環(huán)境,跳過(guò)一些步驟,但貌似還沒(méi)做完善,需要手動(dòng)刪除一些 .service 文件。
虛擬機(jī) vs 容器
也許有人會(huì)說(shuō) docker pull/push 多方便啊,docker build 多方便啊,可不要忘了,vm image storage 早在 openstack 里就解決了,自己處理也不是個(gè)大事,vm image build 也有 Hashicorp 的 Packer 工具代勞,不是個(gè)事。Docker 自豪的官方 docker registry 其實(shí)大家最多用用 base os image,那些 app 級(jí)別的出于信任以及定制考慮都會(huì)自己 build。而 Docker 自豪的 layered storage 也是無(wú)數(shù)血淚,aufs overlayfs 坑了多少人?容器社區(qū)最近還特崇拜 immutable deployment,以把容器根文件系統(tǒng)弄做只讀的為榮,全然不管有緊急安全更新或者功能修正怎么處理——什么,你要說(shuō) docker rm docker run 再起一批不就完事么?真有這么簡(jiǎn)單就好了。
像 Linux kernel 和 git 那種才是正經(jīng) unix 設(shè)計(jì)的思想,分層堆疊,底層提供mechanism,高層提供 policy,各取所需,可惜人總是易于被洗腦,在接受各種高大上policy的時(shí)候全然忘了mechanism還在不在自己手里。
回合二:正確性之爭(zhēng)
強(qiáng)隔離、full OS 體驗(yàn)、保留 mechanism,這才是正道。另外容器還隱藏了一個(gè)坑,/proc/cpuinfo和free命令輸出是host os的,這坑了無(wú)數(shù)探測(cè)系統(tǒng)資源自動(dòng)決定默認(rèn)線程池和內(nèi)存池大小的程序,尤以Java最為普遍。
回合三:性能之爭(zhēng)
容器粉絲津津樂(lè)道——啟動(dòng)容器快,容器的開(kāi)銷少。 這兩點(diǎn)確實(shí)如此但好處真的有那么巨大么?誰(shuí)有事沒(méi)事不停創(chuàng)建虛擬機(jī)?誰(shuí)的虛擬機(jī)生命周期平均在分鐘級(jí)別?誰(shuí)的“用完全啟動(dòng)時(shí)間”平均在秒級(jí)? 至于說(shuō)到虛擬機(jī)浪費(fèi)的資源太多,其實(shí)也就是個(gè)障眼法。理論上服務(wù)器的資源利用率平均不應(yīng)該超過(guò) 80%而實(shí)際上絕大部分公司的服務(wù)器資源利用率應(yīng)該都不到 50%,大量的CPU、內(nèi)存、本地磁盤都是常年浪費(fèi)的,所以 VM 的額外開(kāi)銷不過(guò)是浪費(fèi)了原本就在浪費(fèi)的資源罷了。就單機(jī)的巔峰 I/O 能力來(lái)言,VM 確實(shí)不敵容器。但平時(shí)根本就用不到巔峰狀態(tài), 原本一個(gè) VM 里多進(jìn)程干的事,非得搞多個(gè)容器跑,這容器開(kāi)銷,這人力開(kāi)銷怎么算?
關(guān)于容器還有一個(gè)幻想,那就是可以在物理機(jī)上直接跑容器,開(kāi)銷巨低、管理巨方便,用專用物理機(jī)方式提供多租戶強(qiáng)隔離。前面兩點(diǎn)上面已經(jīng)駁過(guò)了,話說(shuō)還有人用 openstack 管理 docker 容器呢。 我只是說(shuō)一下第三點(diǎn),在一臺(tái)物理機(jī)上直接跑容器的一個(gè)最容易被忽視的問(wèn)題:現(xiàn)在用來(lái)提供
云服務(wù)的物理機(jī)一般都是硬件超級(jí)牛逼,跑上百個(gè)容器都沒(méi)問(wèn)題,但問(wèn)題在于用戶很可能只需要幾個(gè)容器,所以要么跟人共用物理機(jī),要么浪費(fèi)資源白交錢。哪怕用戶需要上百個(gè)容器,出于容災(zāi)考慮,也不可以把上百容器部署到一臺(tái)物理機(jī)上,所以還是要么跟人共用物理機(jī),要么浪費(fèi)資源。
方案
以上是我的觀點(diǎn),我并不是“容器黑”,而是“實(shí)用白”。AWS、Azure、GCE 都主推在虛擬機(jī)上跑容器,按虛擬機(jī)收費(fèi),這非常明智的解決了問(wèn)題:老的純 VM 基礎(chǔ)設(shè)施不用動(dòng),計(jì)費(fèi)照舊,單物理機(jī)可以被安全的多租戶共用,資源隔離有保證(起碼比共享內(nèi)核強(qiáng)多了),把容器管理軟件如“kubernetes”給用戶,既滿足用戶的容器需求,又不擔(dān)心容器的多租戶問(wèn)題。
所以我認(rèn)為:以 VM 為基礎(chǔ),以容器為輔助點(diǎn),要買就買 VM,自己管理容器,別買 CAAS 直接提供的容器,別看不到底下物理機(jī)或者虛擬機(jī)。用 VM 還是用容器,冷靜考察自己的應(yīng)用上容器是否有好處。最后,殘念,VM 開(kāi)源管理軟件能搞個(gè)比 OpenStack 簡(jiǎn)單的東西嗎?