雲計算的前世此生(下)

做者簡介:劉超,網易雲解決方案首席架構師。10年雲計算領域研發及架構經驗,Open DC/OS貢獻者。長期專一於kubernetes, OpenStack、Hadoop、Docker、Lucene、Mesos等開源軟件的企業級應用及產品化。曾出版《Lucene應用開發揭祕》。mysql

如下爲正文:spring

容器的誕生

雲計算的前世此生(上)中提到:雲計算解決了基礎資源層的彈性伸縮,卻沒有解決PaaS層應用隨基礎資源層彈性伸縮而帶來的批量、快速部署問題。因而容器應運而生。sql

容器是Container,Container另外一個意思是集裝箱,其實容器的思想就是要變成軟件交付的集裝箱。集裝箱的特色,一是打包,二是標準。docker

圖片描述

在沒有集裝箱的時代,假設將貨物從A運到B,中間要通過三個碼頭、換三次船。每次都要將貨物卸下船來,擺的七零八落,而後搬上船從新整齊擺好。所以在沒有集裝箱的時候,每次換船,船員們都要在岸上待幾天才能走。數據庫

圖片描述

有了集裝箱之後,全部的貨物都打包在一塊兒了,而且集裝箱的尺寸所有一致,因此每次換船的時候,一個箱子總體搬過去就好了,小時級別就能完成,船員不再能上岸長時間耽擱了。
這是集裝箱「打包」、「標準」兩大特色在生活中的應用。下面用一個簡單的案例來看看容器在開發部署中的實際應用。ubuntu

假設有一個簡單的Java網站須要上線,代碼的運行環境以下:segmentfault

圖片描述

看,一個簡單的Java網站,就有這麼多零零散散的東西!這就像不少零碎地貨物,若是不打包,就須要在開發、測試、生產的每一個環境上從新查看以保證環境的一致,有時甚至要將這些環境從新搭建一遍,就像每次將貨物卸載、重裝同樣麻煩。中間稍有差池,好比開發環境用了JDK 1.8,而線上是JDK 1.7;好比開發環境用了root用戶,線上須要使用hadoop用戶,均可能致使程序的運行失敗。tomcat

圖片描述

那麼容器如何對應用打包呢?仍是要學習集裝箱,首先要有個封閉的環境,將貨物封裝起來,讓貨物之間互不干擾,互相隔離,這樣裝貨卸貨才方便。好在ubuntu中的lxc技術早就能作到這一點。服務器

圖片描述

封閉的環境主要使用了兩種技術,一種是看起來是隔離的技術,稱爲namespace,也即每一個namespace中的應用看到的是不一樣的IP地址、用戶空間、程號等。另外一種是用起來是隔離的技術,稱爲cgroup,也即明明整臺機器有不少的CPU、內存,而一個應用只能用其中的一部分。
有了這兩項技術,集裝箱的鐵盒子咱們是焊好了,接下來是決定往裏面放什麼。微信

圖片描述

最簡單粗暴的方法,就是將上面列表中全部的都放到集裝箱裏面。可是這樣太大了!由於即便你安裝一個乾乾靜靜的ubuntu操做系統,什麼都不裝,就很大了。把操做系統裝進容器至關於把船也放到了集裝箱裏面!傳統的虛擬機鏡像就是這樣的,動輒幾十G。答案固然是NO!因此第一項操做系統不能裝進容器。

撇下第一項操做系統,剩下的全部的加起來,也就幾百M,就輕便多了。所以一臺服務器上的容器是共享操做系統內核的,容器在不一樣機器之間的遷移不帶內核,這也是不少人聲稱容器是輕量級的虛擬機的緣由。輕不白輕,天然隔離性就差了,一個容器讓操做系統崩潰了,其餘容器也就跟着崩潰了,這至關於一個集裝箱把船壓漏水了,全部的集裝箱一塊兒沉。

另外一個須要撇下的就是隨着應用的運行而產生並保存在本地的數據。這些數據多以文件的形式存在,例如數據庫文件、文本文件。這些文件會隨着應用的運行,愈來愈大,若是這些數據也放在容器裏面,會讓容器變得很大,影響容器在不一樣環境的遷移。並且這些數據在開發、測試、線上環境之間的遷移是沒有意義的,生產環境不可能用測試環境的文件,因此每每這些數據也是保存在容器外面的存儲設備上。也是爲何人們稱容器是無狀態的。

至此集裝箱焊好了,貨物也裝進去了,接下來就是如何將這個集裝箱標準化,從而在哪艘船上都能運輸。這裏的標準一個是鏡像,一個是容器的運行環境。

所謂的鏡像,就是將你焊好集裝箱的那個時刻,將集裝箱的狀態保存下來,就像孫悟空說定,集裝箱裏面就定在了那一刻,而後將這一刻的狀態保存成一系列文件。這些文件的格式是標準的,誰看到這些文件,都能還原當時定住的那個時刻。將鏡像還原成運行時的過程(就是讀取鏡像文件,還原那個時刻的過程)就是容器的運行的過程。除了大名鼎鼎的Docker,還有其餘的容器,例如AppC、Mesos Container,都能運行容器鏡像。因此說容器不等於Docker。

總而言之,容器是輕量級的、隔離差的、適用於無狀態的,能夠基於鏡像標準實現跨主機、跨環境的隨意遷移。

圖片描述

有了容器,使得PaaS層對於用戶自身應用的自動部署變得快速而優雅。容器快,快在了兩方面,第一是虛擬機啓動的時候要先啓動操做系統,容器不用啓動操做系統,由於是共享內核的。第二是虛擬機啓動後使用腳本安裝應用,容器不用安裝應用,由於已經打包在鏡像裏面了。因此最終虛擬機的啓動是分鐘級別,而容器的啓動是秒級。容器咋這麼神奇。其實一點都不神奇,第一是偷懶少幹活了,第二是提早把活幹好了。

由於容器的啓動快,人們每每不會建立一個個小的虛擬機來部署應用,由於這樣太費時間了,而是建立一個大的虛擬機,而後在大的虛擬機裏面再劃分容器,而不一樣的用戶不共享大的虛擬機,能夠實現操做系統內核的隔離。這又是一次合久必分的過程。由IaaS層的虛擬機池,劃分爲更細粒度的容器池。

容器管理平臺

有了容器的管理平臺,又是一次分久必合的過程。

容器的粒度更加細,管理起來更難管,甚至是手動操做難以應對的。假設你有100臺物理機,其實規模不是太大,用Excel人工管理是沒問題的,可是一臺上面開10臺虛擬機,虛擬機的個數就是1000臺,人工管理已經很困難了,可是一臺虛擬機裏面開10個容器,就是10000個容器,你是否是已經完全放棄人工運維的想法了。

因此容器層面的管理平臺是一個新的挑戰,關鍵字就是自動化:

圖片描述

  1. 自發現:容器與容器之間的相互配置還能像虛擬機同樣,記住IP地址,而後互相配置嗎?這麼多容器,你怎麼記得住一旦一臺虛擬機掛了重啓,IP改變,應該改哪些配置,列表長度至少萬行級別的啊。因此容器之間的配置經過名稱來的,不管容器跑到哪臺機器上,名稱不變,就能訪問到。
  2. 自修復:容器掛了,或是進程宕機了,能像虛擬機那樣,登錄上去查看一下進程狀態,若是不正常重啓一下麼?你要登錄萬臺docker了。因此容器的進程掛了,容器就自動掛掉了,而後自動重啓。
  3. 彈性自伸縮 Auto Scaling:當容器的性能不足的時候,須要手動伸縮,手動部署麼?固然也要自動來。

當前火熱的容器管理平臺有三大流派:

圖片描述

    • 一個是Kubernetes,咱們稱爲段譽型。段譽(Kubernetes)的父親(Borg)武功高強,出身皇族(Google),管理過偌大的一個大理國(Borg是Google數據中心的容器管理平臺)。做爲大理段式後裔,段譽的武功基因良好(Kubernetes的理念設計比較完善),周圍的高手雲集,習武環境也好(Kubernetes生態活躍,熱度高),雖然剛剛出道的段譽武功不及其父親,可是隻要跟着周圍的高手不斷切磋,武功既能夠飛速提高。
    • 一個是Mesos,咱們稱爲喬峯型。喬峯(Mesos)的主要功夫降龍十八掌(Mesos的調度功能)獨步武林,爲其餘幫派所無。並且喬峯也管理過人數衆多的丐幫(Mesos管理過Tweeter的容器集羣)。後來喬峯從丐幫出來,在江湖中特例獨行(Mesos的創始人成立了公司Mesosphere)。喬峯的優點在於,喬峯的降龍十八掌(Mesos)就是在丐幫中使用的降龍十八掌,相比與段譽初學其父的武功來講,要成熟不少。可是缺點是,降龍十八掌只掌握在少數的幾個丐幫幫主手中(Mesos社區仍是以Mesosphere爲主導),其餘丐幫兄弟只能遠遠崇拜喬峯,而沒法相互切磋(社區熱度不足)。
    • 一個是Swarm,咱們稱爲慕容型。慕容家族(Swarm是Docker家族的集羣管理軟件)的我的功夫是很是棒的(Docker能夠說稱爲容器的事實標準),可是看到段譽和喬峯可以管理的組織規模愈來愈大,有一統江湖的趨勢,着實眼紅了,因而開始想建立本身的慕容鮮卑帝國(推出Swarm容器集羣管理軟件)。可是我的功夫好,並不表明着組織能力強(Swarm的集羣管理能力),好在慕容家族能夠借鑑段譽和喬峯的組織管理經驗,學習各家公司,以彼之道,還施彼身,使得慕容公子的組織能力(Swarm借鑑了不少前面的集羣管理思想)也在逐漸的成熟中。

    三大容器門派,到底鹿死誰手,誰能一統江湖,還沒有可知。

    網易雲之因此選型Kubernetes做爲本身的容器管理平臺,是由於基於 Borg 成熟的經驗打造的 Kubernetes,爲容器編排管理提供了完整的開源方案,而且社區活躍,生態完善,積累了大量分佈式、服務化系統架構的最佳實踐。

    容器初體驗

    想不想嘗試一下最早進的容器管理平臺呢?咱們先了解一下Docker的生命週期。如圖所示。

    圖片描述

    圖中最中間就是最核心的兩個部分,一個是鏡像Images,一個是容器Containers。鏡像運行起來就是容器。容器運行的過程當中,基於原始鏡像作了改變,好比安裝了程序,添加了文件,也能夠提交回去(commit)成爲鏡像。若是你們安裝過系統,鏡像有點像GHOST鏡像,從GHOST鏡像安裝一個系統,運行起來,就至關於容器;容器裏面自帶應用,就像GHOST鏡像安裝的系統裏面不是裸的操做系統,裏面可能安裝了微信,QQ,視頻播放軟件等。安裝好的系統使用的過程當中又安裝了其餘的軟件,或者下載了文件,還能夠將這個系統從新GHOST成一個鏡像,當其餘人經過這個鏡像再安裝系統的時候,則其餘的軟件也就自帶了。

    普通的GHOST鏡像就是一個文件,可是管理不方便,好比若是有十個GHOST鏡像的話,你可能已經記不清楚哪一個鏡像裏面安裝了哪一個版本的軟件了。因此容器鏡像有tag的概念,就是一個標籤,好比dev-1.0,dev-1.1,production-1.1等,凡是可以幫助你區分不一樣鏡像的,均可以。
    爲了鏡像的統一管理,有一個鏡像庫的東西,能夠經過push將本地的鏡像放到統一的鏡像庫中保存,能夠經過pull將鏡像庫中的鏡像拉到本地來。

    從鏡像運行一個容器可以使用下面的命令,若是初步使用Docker,記下下面這一個命令就能夠了。
    圖片描述

    這行命令會啓動一個裏面安裝了mysql的容器。其中docker run就是運行一個容器;--name就是給這個容器起個名字;-v 就是掛數據盤,將外面的一個目錄/my/own/datadir掛載到容器裏面的一個目錄/var/lib/mysql做爲數據盤,外面的目錄是在容器所運行的主機上的,也能夠是遠程的一個雲盤;-e 是設置容器運行環境的環境變量,環境變量是最常使用的設置參數的方式,例如這裏設置mysql的密碼。mysql:tag就是鏡像的名字和標籤。

    docker stop能夠中止這個容器,start能夠再啓動這個容器,restart能夠重啓這個容器。在容器內部作了改變,例如安裝了新的軟件,產生了新的文件,則調用docker commit變成新的鏡像。

    鏡像生產過程,除了能夠經過啓動一個docker,手動修改,而後調用docker commit造成新鏡像以外,還能夠經過書寫Dockerfile,經過docker build來編譯這個Dockerfile來造成新鏡像。爲何要這樣作呢?前面的方式太不自動化了,須要手工干預,並且還常常會忘了手工都作了什麼。用Dockerfile能夠很好的解決這個問題。

    Dockerfile的一個簡單的例子以下:
    圖片描述

    這實際上是一個鏡像的生產說明書,Docker build的過程就是根據這個生產說明書來生產鏡像:

    1. FROM基礎鏡像,先下載這個基礎鏡像,而後從這個鏡像啓動一個容器,而且登錄到容器裏面;
    2. RUN運行一個命令,在容器裏面運行這個命令;
    3. COPY/ADD將一些文件添加到容器裏面;
    4. 最終給容器設置啓動命令 ENTRYPOINT,這個命令不在鏡像生成過程當中執行,而是在容器運行的時候做爲主程序執行;
    5. 將全部的修改commit成鏡像。

    這裏須要說明一下的就是主程序,是Docker裏面一個重要的概念,雖然鏡像裏面能夠安裝不少的程序,可是必須有一個主程序,主程序和容器的生命週期徹底一致,主程序在則容器在,主程序亡則容器亡。

    圖片描述

    就像圖中展現的同樣,容器是一個資源限制的框,可是這個框沒有底,全靠主進程撐着,主進程掛了,衣服架子倒了,衣服也就垮了。

    瞭解瞭如何運行一個獨立的容器,接下來介紹如何使用容器管理平臺。

    容器管理平臺初體驗

    圖片描述
    容器管理平臺會對容器作更高的抽象,容器再也不是單打獨鬥,並且組成集團軍共同戰鬥。
    多個容器組成一個Pod,這幾個容器親如兄弟,乾的也是相關性很強的活,可以經過localhost訪問彼此,真是兄弟齊心,力可斷金。有的任務一幫兄弟還剛不住,就須要多個Pod協力完成,這個由ReplicationController進行控制,能夠將一個Pod複製N個副本,同時承載任務,衆人拾柴火焰高。

    N個Pod若是對外散兵做戰,一是沒法協力,二是給人很亂的感受,於是須要有一個老大,做爲代言人,將你們團結起來,一致對外,這就是Service。老大對外提供統一的虛擬IP和端口,並將這個IP和服務名關聯起來,訪問服務名,則自動映射爲虛擬IP。老大的意思就是,若是外面要訪問我這個團隊,喊一聲名字就能夠,例如」雷鋒班,幫敬老院打掃衛生!」,你不用管雷鋒班的那我的去打掃衛生,每一個人打掃哪一部分,班長會統一分配。

    最上層經過namespace分隔徹底隔離的環境,例如生產環境,測試環境,開發環境等。就像軍隊分華北野戰軍,東北野戰軍同樣。野戰軍立正,出發,部署一個Tomcat的Java應用。

    實戰案例

    有個blog的war,能夠從這裏下載
    http://demo.nos-eastchina1.12...

    還須要一個jar,從這裏下載
    http://demo.nos-eastchina1.12...

    將編譯結果上傳到對象存儲

    登錄網易雲,點擊對象存儲,建立桶。上傳springblog.war到這個桶裏面。
    對於spring,還須要spring-instrument-tomcat-4.2.2.RELEASE.jar放到這個桶裏面。

    圖片描述

    寫一個Dockerfile

    圖片描述

    因爲這是基於Tomcat的,因此咱們使用hub.c.163.com/library/tomcat:8.0-jre7做爲基礎鏡像。這個鏡像能夠在鏡像倉庫裏面搜到。

    圖片描述

    經過ADD命令,將對象存儲中的war,jar放入容器鏡像中,而且修改權限。注意URL地址不是本例子中的地址,而是您本身的地址,能夠在對象存儲界面上經過複製地址獲得這個地址。
    將catalina.sh run做爲ENTRYPOINT。

    構建一個鏡像

    在鏡像倉庫裏面,建立鏡像倉庫,起個名字

    圖片描述

    點擊鏡像倉庫,點擊構建鏡像

    圖片描述

    圖片描述

    在本地選擇寫好的Dockerfile開始構建。
    構建成功則顯示以下:

    圖片描述

    圖片描述

    建立tomcat服務

    圖片描述

    在服務管理中,點擊建立服務。

    圖片描述

    填寫名稱testtomcat,選擇無狀態
    圖片描述

    鏡像選擇前面構建的鏡像。

    圖片描述

    選擇默認的規格,端口映射爲8080映射爲8080。
    點擊當即建立。等待建立成功。

    建立負載均衡器

    圖片描述

    在負載均衡頁面,點擊建立負載均衡,取名testtomcat。

    圖片描述

    點擊建立監聽。

    取名testtomcat,監聽端口8080,映射爲testtomcat服務的8080.
    點擊當即建立。

    1. 訪問頁面

    圖片描述

    使用負載均衡的IP地址加上8080端口訪問tomcat。

    圖片描述

    使用user/user登錄,建立一個博客

    圖片描述

    相關文章
    相關標籤/搜索