滬江黃凱:Kuberneters 的 Fannel 有一種模式是 Vxlan,它的封裝折包是做內(nèi)核里做的,效率會高一點。容器多就會效率會低是因為,在 Kubernetes 1.2 的時候,走這樣的一種模式,數(shù)據(jù)先到內(nèi)核態(tài)中,然后把數(shù)據(jù)拉回到用戶態(tài),用 Proxy的方式分發(fā)給各個容器當中的。其實在Kubernetes 1.3以后,它直接在iptables里設(shè)規(guī)則,相當于用戶數(shù)據(jù)不用跑到用戶態(tài),在內(nèi)核直接分發(fā)出去了,這種效率會非常高。所以可以研究一下Kubernetes新版本。
扇貝丁彥:我們碰到過網(wǎng)絡(luò)方面的問題。默認的Docker engine的啟動參數(shù)里面有個iptables,不知道大家有沒有定制化過,如果不定制化這個參數(shù),它默認會幫你建iptables的轉(zhuǎn)發(fā)規(guī)則,并會開啟內(nèi)核的網(wǎng)絡(luò)追蹤的模塊。一開始我們沒有注意這件事情,當我們的Nginx遷到Docker的時候,Nginx服務(wù)瞬間會掛。后來查原因,是因為這些參數(shù)會開啟網(wǎng)絡(luò)追蹤模塊。因為我們的Nginx流量非常大,當時只有3臺Linux云主機,分發(fā)Http請求的,然后會導(dǎo)致3臺Linux宿主機,內(nèi)存會被刷破,網(wǎng)絡(luò)會出現(xiàn)堵塞。所以我們關(guān)掉了 iptables 參數(shù),并采用Host的網(wǎng)絡(luò)模型。所以它的容器拿到的IP就是Host的IP。我們一開始也想上一些Kubernetes這些東西,然后發(fā)現(xiàn)簡單跑個模型根本跑不起來,所以一開始就放棄了這一套東西,直接搞了個裸的Docker。
主持人:關(guān)于跨數(shù)據(jù)中心容器集群的使用,大家有經(jīng)驗么?
滬江黃凱:我們跨數(shù)據(jù)中心主要是IP分配上的問題,我們現(xiàn)在也在嘗試使用Calico,如果Host網(wǎng)絡(luò)是通的話,那么它的內(nèi)部網(wǎng)絡(luò)也就通了,可以自由劃Vlan,這樣你就可以解決跨Data center的問題。還有一個問題就在跨Data center時,服務(wù)注冊與發(fā)現(xiàn)的問題。這個問題也困擾我們很久了,我們現(xiàn)在使用Consul做服務(wù)注冊與發(fā)現(xiàn)。雖然Consul它是官方支持跨Data center,但是我們在使用當中的話會發(fā)現(xiàn)注冊的IP,在另外一個注冊中心,它會發(fā)現(xiàn)的比較慢,甚至有時候出現(xiàn)IP沖突的時候。
我們的做法是把 Host 的 IP 地址直接用 Environment 的形式注到 Docker 鏡像內(nèi)部,接下 來 Docker 鏡像要注冊,它就會讀取 app 的 IP,然后發(fā)送給 Consul,只要保證 Host 的 IP 和 Docker內(nèi)部容器的 IP 能夠互通的就行了。如果不能通的話,比如說完全和 Host IP 隔離,那么起碼有幾臺機器要暴露出去,又比如說,Consul 它本身自己要暴露出去才能訪問到。Host 的 IP 是容器啟動之后注進去的,啟動命令中把 Host 的 IP 地址加在 -e 的后面,容器在啟動之后,它的環(huán)境就會有這么一個 IP。我們用 Mesos 就沒這個問題,但是用 Kubernetes 就有這個問題。Mesos 會自動幫你把這些東西注入容器中去。
滴滴田智偉:其實 Kubernetes 本身也是可以解決這個問題,我們現(xiàn)在在做線下持續(xù)交付的時候。定義完 Service 之后,容器會同一個 Namespace 默認加一個系統(tǒng)環(huán)境變量。
滬江黃凱:我們試過,在 Pod 啟動之后,Pod 里容器想訪問 host 的 IP 地址,是沒有辦法做到的。
蘑菇街張振華:因為我們之前也遇到這個問題,然后我們業(yè)務(wù)方,他們可能有一些程序會獲取本機 IP 地址,如果是內(nèi)部的 IP 地址,他們程序可能會出現(xiàn)問題,于是我們當時沒有用 Docker 默認的網(wǎng)絡(luò),而是采用 Vlan。
主持人:我們提到好多 Mesos、Kubernetes、網(wǎng)絡(luò),發(fā)現(xiàn)沒有提自動伸縮,有沒有項目涉及到容器的自動伸縮?
滬江黃凱:我們滬江是基于 Mesos+Marathon 做了自己的一個服務(wù),它這個服務(wù)是干嘛的呢,就是監(jiān)測,不停的監(jiān)測每一個 Docker 的 CPU 和內(nèi)存的利用率,一旦超過百分之多少以后,就向Marathon發(fā)一個命令,說我要擴容,它還可以支持時間點,比如 15 分鐘監(jiān)測一次,如果在 15 分鐘發(fā)現(xiàn)它超過閾值了,就馬上擴容出來,但是縮的話,不是適用于頻繁監(jiān)控,如果小于 20% 的話就會縮,一旦縮的話會影響線上用戶的請求。怎么辦呢?我們在縮的時候可以規(guī)定它的時間點,比如半夜里2-3點,訪問量少于多少點時候把它縮掉。我們監(jiān)測的是 Docker 內(nèi)部的 CPU 的使用率。就是監(jiān)測一個服務(wù),它可以監(jiān)控所有同一服務(wù)的 Container,比如一個服務(wù)有100個容器,那么這一百多個 CPU 利用率加起來除于一百,相當于平均的利用率。如果平均利用率超過 80%了,那說明這個集群到了擴展程度了,它會以一種比例來擴展。針對單個容器,可以設(shè)置內(nèi)存的限制。我們給每一個容器呢,比如它只能用 4 個 CPU,只能用 8G 的內(nèi)存,或者更小一點的內(nèi)存,這些都設(shè)好,設(shè)好之后它自動擴展相同規(guī)格的容器。這么做是因為 Cgroup 有個問題,當利用率到達了啟動的限制,Cgroup 會把這個容器 kill 掉。這個是不可理喻的問題,所以我們想到用 Load scale 來擴容,不讓他直接死掉。