我是LEE骡男,老李像棘。
今天跟大家分享一個Docker底層軟件利器 - lxcfs嫉父。 我們先從一些場景和問題開始了解起這個軟件到底有什么用。
1. 大家在日常使用docker福青,尤其是在生產(chǎn)系統(tǒng)為了避免某些容器過分使用CPU或者內(nèi)存摄狱,與其他的容器發(fā)生資源爭搶,都會在docker啟動加上資源限制无午。但是實(shí)際工作中docker的通過cgroup做的資源隔離真的是那么滿意嗎媒役? 容器內(nèi)看到的還是宿主機(jī)的資源。
2. 我們的研發(fā)小伙在開發(fā)服務(wù)端( golang中 runtime.GOMAXPROCS(runtime.NumCPU()) ) 或者運(yùn)維小伙伴在設(shè)置服務(wù)啟動進(jìn)程數(shù)量的時候( 比如 nginx 配置中的 worker_processes auto )宪迟,都喜歡通過程序自動判斷所在運(yùn)行環(huán)境CPU的數(shù)量酣衷。
3. golang的小伙伴在編譯好的代碼,在一個docker中運(yùn)行的時候次泽,gc時候使用的內(nèi)存應(yīng)該是怎么計(jì)算呢穿仪? 是不是應(yīng)該按照我們在直接從系統(tǒng)中直接獲得內(nèi)存來設(shè)定呢?
當(dāng)然這樣的情況還有很多很多意荤,我就不一一列舉啊片。為啥突然要說這個,是因?yàn)榻裉熳罱约鹤鲅芯亢驮O(shè)計(jì)時候玖像,碰到這個問題紫谷。記得那是2017的時候曾經(jīng)也碰到這樣要求,可是社區(qū)沒有太多解決方案,后來美團(tuán)也提出了解決思路碴里,并提議修改沈矿。 但是看到回饋說是,老外覺得這個需求不重要咬腋,而且在一定程度違背了docker的設(shè)計(jì)理念羹膳。最后當(dāng)時的工作不得不停下來了,換用別的方案來解決根竿。
現(xiàn)在已經(jīng)到2019年了陵像,什么都是快速發(fā)展的( 好像最近下崗也是很快速的,唉寇壳! )醒颖,我想回去看看這個問題解了嗎? 今天偶然測試了一下壳炎。 好像這個問題已經(jīng)得到解決泞歉,雖然還有一些地方需要改進(jìn),但是通過今天的測試發(fā)現(xiàn)已經(jīng)到了可以使用的程度匿辩。所以決定將 lxcfs 的測試效果分享給大家腰耙。 以后再docker底層資源隔離這方面( 至少在CPU和內(nèi)存方面 ),可以做到跟虛擬機(jī)比較像铲球。 也方便以后小伙伴能夠?qū)⑻摂M機(jī)上跑的業(yè)務(wù)平滑的過度到docker里挺庞。
好了,言歸正傳稼病,我們了解下 lxcfs 的機(jī)制:
lxcfs 是一個開源的FUSE(用戶態(tài)文件系統(tǒng))實(shí)現(xiàn)來支持LXC容器选侨,它也可以支持Docker容器。讓容器內(nèi)的應(yīng)用在讀取內(nèi)存和CPU信息的時候通過lxcfs的映射然走,轉(zhuǎn)到自己的通過對cgroup中容器相關(guān)定義信息讀取的虛擬數(shù)據(jù)上援制。 有點(diǎn)繞,沒有關(guān)系我們往下繼續(xù)看芍瑞。
LXCFS通過用戶態(tài)文件系統(tǒng)隘谣,在容器中提供下列 procfs 的文件。
/proc/cpuinfo
/proc/diskstats
/proc/meminfo
/proc/stat
/proc/swaps
/proc/uptime
簡單的說一句話說:就是通過文件掛載的方式啄巧,把cgroup中關(guān)于系統(tǒng)的相關(guān)信息讀取出來寻歧,通過docker的volume掛載給容器內(nèi)部的proc系統(tǒng)。 然后讓docker內(nèi)的應(yīng)用讀取proc中信息的時候以為就是讀取的宿主機(jī)的真實(shí)的proc秩仆。
掛載命令也非常的簡單:? ?lxcfs /var/lib/lxcfs? ?就OK了码泛。 是不是突然覺得這個世界挺美好的。?
這里我們用內(nèi)存資源舉例:
當(dāng)我們把宿主機(jī)的 /var/lib/lxcfs/proc/memoinfo 文件掛載到Docker容器的/proc/meminfo位置后澄耍。容器中進(jìn)程讀取相應(yīng)文件內(nèi)容時噪珊,LXCFS的FUSE實(shí)現(xiàn)會從容器對應(yīng)的Cgroup中讀取正確的內(nèi)存限制晌缘。從而使得應(yīng)用獲得正確的資源約束設(shè)定。 CPU這塊原理一樣痢站,這里就不做列舉磷箕,自行腦補(bǔ)。
我們看看掛載前后的差別: (環(huán)境準(zhǔn)備了一臺虛擬機(jī) 2C1G 的環(huán)境)
掛載前:
執(zhí)行命令: docker run --cpus 1 --memory 50m -it ubuntu bash
容器內(nèi)存跟宿主機(jī)一樣是1G
容器CPU跟宿主機(jī)一樣2核
好像docker run起來沒有啥效果嘛阵难??
掛載后:
執(zhí)行命令:?docker run --cpus 1 --memory 50m -it -v /var/lib/lxcfs/proc/cpuinfo:/proc/cpuinfo:rw -v /var/lib/lxcfs/proc/diskstats:/proc/diskstats:rw -v /var/lib/lxcfs/proc/meminfo:/proc/meminfo:rw -v /var/lib/lxcfs/proc/stat:/proc/stat:rw -v /var/lib/lxcfs/proc/swaps:/proc/swaps:rw -v /var/lib/lxcfs/proc/uptime:/proc/uptime:rw ubuntu bash
容器內(nèi)存跟宿主機(jī)不一樣岳枷,是50M
容器CPU跟宿主機(jī)不一樣,是1核
嘿嘿呜叫,docker run 起來空繁,起到應(yīng)該有的效果了。 以后我們從虛擬機(jī)轉(zhuǎn)移代碼到容器的時候朱庆,再也不用擔(dān)心CPU和內(nèi)存資源獲得總數(shù)不正確了盛泡。
小Tips:
容器的CPU設(shè)置有兩種方式,一個是--cpus 2娱颊,限定容器最多只能使用兩個邏輯CPU傲诵,另一個是--cpuset-cpus "0,1",限定容器 可以使用的宿主機(jī)CPU箱硕。
top命令顯示的是容器?可以使用的?宿主機(jī)cpu拴竹,如果使用--cpus 2,看到的cpu個數(shù)是宿主機(jī)上的cpu個數(shù)颅痊。使用--cpuset-cpus "0,1"的時候,在容器看到cpu個數(shù)是--cpuset指定的cpu的個數(shù)局待。
當(dāng)然最后不能忘記分享我編譯好的 lxcfs 二進(jìn)制軟件包:
https://pan.baidu.com/s/14iz_2wrrjgwe2hbnBMzYUg
使用非常簡單:
# rpm -ivh?lxcfs-3.0.4-1.el7.x86_64.rpm
# systemctl enable lxcfs.service
#?systemctl start lxcfs.service