一、容器技術
?1.1、為什么需要容器
????????在使用虛擬化一段時間后,發現它存在一些問題:不同的用戶,有時候只是希望運行各自的一些簡單程序,跑一個小進程。為了不相互影響,就要建立虛擬機。如果建虛擬機,顯然浪費就會有點大,而且操作也比較復雜,花費時間也會比較長。而且,有的時候,想要遷移自己的服務程序,就要遷移整個虛擬機。顯然,遷移過程也會很復雜。有沒有辦法更靈活快速一些呢?有,這就引入了“容器(Container)” 。
?1.2、容器和虛擬機的區別
????????容器也是虛擬化,但是屬于“輕量級”的虛擬化。它的目的和虛擬機一樣,都是為了創造“隔離環境”。但是,它又和虛擬機有很大的不同——虛擬機是操作系統級別的資源隔離,而容器本質上是進程級的資源隔離。
????????虛擬機通常包括整個操作系統和應用程序。它們還需要一個與它們一起運行的管理程序來控制虛擬機。由于它們包括操作系統,因此它們的大小為幾千兆字節。使用虛擬機的一個缺點是,它們需要花費幾分鐘來啟動操作系統,并初始化它們所承載的應用程序。同時,這些容器是輕量級的,并且大部分在兆字節大小范圍內。與虛擬機相比,容器的性能要好得多,幾乎可以立即啟動。
?1.3、容器的優缺點
| 容器技術主要解決環境配置問題,它是一種虛擬化技術,對進程進行隔離,被隔離的進程獨立于宿主操作系統和其它隔離的進程。使用容器可以不修改應用程序代碼,不需要開發人員學習特定環境下的技術,就能夠將現有的應用程序部署在其它機器上。 | ||
| 序號 | 容器的優點 | 容器的缺點 |
| 1 | 敏捷環境 (容器創建實例比虛擬機要快非常多,容器輕量級的腳本可以從性能和大小兩個方面減小開銷) | 復雜性增加 (隨著容器和應用數量的增加,同時也伴隨著復雜性的增加;在生產環境中管理如此多的容器是一個極具挑戰性的任務,雖然說可以使用K8s等編排工具去管理這些容器,但是隨著服務和應用的增加,管理的難度也會隨之增加) |
| 2 | 提高生產力 (容器可以移除跨服務依賴和沖突提高開發者的生產能力;每個容器都可以看作是一個不同微服務,因此可以獨立升級,而不用擔心同步) | 原生Linux支持 (大多數的容器技術(如Docker)最初都是基于Linux容器來進行開發和實現的,相比于在原生Linux中運行的容器,在Windows環境中使用容器就會顯得很笨拙,并且日常的使用也會帶來一些復雜性。也就是說容器在Linux下支持很好,但是在Windows環境下支持會很差) |
| 3 | 版本控制 (每個容器的鏡像都有版本控制,這樣就可以追蹤不同版本的容器,監控版本之間的差異等) | 不太成熟 (這也是相對的,隨著技術的發展會逐漸成熟;容器技術在目前的市場上是相對較新的技術,是需要時間來適應市場;開發者可用的資源也是有限的(如:若開發者遇到問題需要花費更多的時間去解決)) |
| 4 | 運行環境可移植 (容器封裝了所有應用程序所必須得相關細節(如:應用程序所依賴的一些軟件包以及操作系統)這就使得鏡像從一個環境移植到另外一個環境變得非常靈活以及高效(如:同一個鏡像既可以在Windows或Linux進行開發測試,然后也可以在其他環境下之間去運行)) | |
| 5 | 標準化 (大多數的容器是基于開放的標準,可以運行在所有主流的Linux發行版本、Windows平臺等) | |
| 6 | 安全 (容器之間的進程是互相隔離的,其中的基礎設施也是如此,這樣其中一個容器的升級、變化時不會影響到其他容器】) | |
?1.4、容器的分類
| 常見的容器有【操作系統容器】和【應用系統容器】 | ||
| 序號 | 操作系統容器 | 應用程序容器 |
| 1 | 操作系統容器是一種操作系統級別的虛擬化,操作系統內核是允許存在多個獨立的用戶空間實例的;從程序運行的角度來看這些實例一般都會被稱為容器虛擬化引擎【操作系統容器中,可以運行多個服務和進程】 | 應用程序虛擬化是一種軟件技術,它從執行它的底層操作系統中封裝計算機程序;一個完全虛擬化的應用程序并不是傳統意義上的安裝,盡管它仍然像以前一樣去正常運行。 那么應用程序在運行時的行為就像它直接與原始操作系統以及由它管理的所有資源一樣,但可以不同程度的隔離或沙盒化,因此我們說應用容器的設計就是將【服務打包并作為單個進程運行】 (如:Docker、Rocket容器就是應用程序容器,當我們啟動Docker容器時會運行一個進程,但為應用程序創建容器時這個過程通常是會運行應用程序的一個進程,這與傳統的操作系統容器是不同的【因為在傳統操作系統容器中,一個操作系統容器會運行多個服務】)。 |
| 2 | 操作系統容器是共享主機操作系統內核,但提供用戶空間的隔離,可以安裝配置不同的應用程序。就和在主機上運行程序一樣;同樣分配給容器的資源,僅僅對該容器可見。任何來賓用戶的系統鏡像都無法訪問其他來賓系統的資源。 ? ? ? 由于操作系統容器提供的虛擬環境與相互隔離的用戶空間共享內核的方法去實現;因此操作系統容器是非常適合運行同一應用不同版本的需求,對于相同版本更是容易。但大多數情況下容器是以模板或鏡像的方式創建的,那么這些模板或鏡像決定了容器的結構和內容,并且去創建普通環境的容器也是十分方便的。 | 當需要將應用程序打包并作為組件分發時,應用程序容器是個很好的選擇。 |
| 3 | 如果只想要一個可以安裝不同庫、語言、數據庫的操作系統,那么操作系統容器更適合。 | |
?1.5、容器的主要應用場景
????????容器技術的誕生其實主要解決了PAAS的層的技術實現。像OpenStack、 Cloudstack這樣的技術是解決IAAS層的問題。 IAAS層和PAAS層前面已經做過介紹,關于它們的區別和特性我這里不在描述。那么容器技術主要應用在哪些場景呢?目前主流的有以下幾種:
| 序號 | 容器主要應用場景 | 說明 |
| 1 | 容器化傳統應用 | 容器不僅可以提高現有應用的安全性和可一致性還能節省成本;每個企業的環境中都有一套較舊的應用來服務于客戶或自動執行業務流程; ????????即使是大規模的單體應用,通過容器隔離的增強安全性以及可移植性的特點,也能從Docker中獲得收益,從而降低成本。一旦容器化之后,這些應用可以擴展額外的服務,或者轉變為微服務架構 |
| 2 | 持續集成和持續部署 (CI/CD) | 通過Docker可以加速應用管道自動化和應用部署,交付的速度至少要提高十幾倍; ????????現在開發流程非常快,需要持續且具備自動執行的能力,最終是要開發出更可靠的軟件,那么通過持續集成和持續部署,每次開發人員遷入代碼并順利測試之后,IT團隊都能夠去集成新的代碼;作為運維開發方向的基礎CI/CD創造了一種實時反饋的回路機制,持續的傳輸小型迭代更改,從而加速更改,提高質量。 CI環境通常是完全自動化的,通過Git推送命令觸發測試,測試成功后,會自動構建新鏡像,然后推送到Docker鏡像倉庫,通過后續的自動化和腳本,可以將新鏡像的容器部署到預演環境,從而進一步進行測試。 |
| 3 | 微服務 | ?通過微服務可以加速應用架構現代化的進度,應用架構正在從采用瀑布模式開發的方法,然后轉變為獨立開發和部署的松耦合的服務模式,那么成千上萬的服務相互連接起來就形成了一個應用。? ????????Docker是允許開發人員,選擇最適合于哪種服務的技術棧,隔離服務可以消除潛在的沖突,從而避免地獄式的矩陣依賴,那么這些容器可以獨立于應用的其他服務組件,輕松的共享、部署、更新和瞬間擴展。 ????????Docker的端到端的安全功能,可以讓團隊能夠構建和運行最低權限的微服務模型,服務所需的一些資源( 如:應用、生命信息、計算資源等)會實時的被創建并被訪問。 |
| 4 | ?IT 基礎設施優化 | Docker和容器是有助于優化IT基礎設施,它的成本利用率;優化不僅僅是削減成本,還能確保在適當的時候有效地使用適當的資源。 ? ? ? ? 容器是一種輕量級的打包和隔離應用工具,所以Docker允許在同一物理或虛擬服務器上,毫不沖突的運行多個項目的工作;企業可以整合數據中心,將并購而來的IT資源進行整合,從而獲得像云端的可遷移性;同時減少操作系統和服務器的一些維護工作。 |
二、容器引擎
?2.1、Docker引擎
????????多數技術人員在談到Docker時,主要是指Docker引擎。Docker引擎是用于運行和編排容器的基礎設施工具。開源后的Docker在2013年突然一炮而紅,Docker幾乎已經成為了容器技術的代名詞;但容器技術其實早就已經存在了,之所以傳統的容器技術沒有成為主流的原因,是因為它沒有能夠提供標準化的應用運行環境。而基于容器技術的Docker是一開始就以提供標準化運行時環境為目標的,它真正做到了構建一次,到處運行的理念,所以Docker就火起來了。相比傳統的虛擬機Docker的優勢十分明顯:《1》啟動時間很快是秒級甚至毫秒級;《2》對資源的利用率很高(一臺主機上可以同時運行幾十上百上千個容器都是可以的);《3》占用空間很小(一般占用幾十兆幾百兆)。
????????Docker引擎是運行容器的核心容器運行時。其他 Docker公司或第三方的產品都是圍繞Docker引擎進行開發和集成的。
?2.2、Docker核心技術
????????Docker的核心技術包括【docker鏡像】【docker容器】和【docker倉庫】。
? 2.2.1、Docker鏡像
????????Docker鏡像是一個特殊的文件系統,它提供了容器運行時所需的程序、庫、資源、配置等文件外,還包含了一些為運行時準備的一些配置參數(如匿名卷、環境變量、用戶等) 。鏡像不包含任何動態數據,其內容在構建之后也不會被改變(只讀屬性)。鏡像結構如下圖所示:

| 序號 | 鏡像內容 | 說明 |
| 1 | 可寫容器(container) | 【可寫】 |
| 2 | 鏡像(tomcat) | 【不可寫】 |
| 3 | 鏡像(jdk) | 【不可寫】 |
| 4 | rootfs基礎鏡像(Centos/Ubuntu) | 是典型的Linux文件系統,主要包含目錄系統(如:dev、etc、bin、proc等)這些內容都是Linux系統標準的目錄和文件【是操作系統的基礎鏡像】【不可寫】 |
| 5 | bootfs | 是典型的Linux文件系統,主要包含啟動引導、內核程序;這個啟動引導主要是加載內核,當內核加載到內存之后,這個bootfs就會被卸載掉【是操作系統的基礎鏡像】【不可寫】 |
? 2.2.2、Docker容器
| 序號 | 說明 |
| 1 | 鏡像(Image)和容器(Container)有緊密的關系,鏡像是靜態的定義,容器是鏡像運行時的實體。容器可以被創建、啟動、停止、刪除、暫停等。 |
| 2 | 容器的實質是進程,但與直接在宿主執行的進程不同,容器進程運行于屬于自己的獨立的命名空間。因此容器可以擁有自己的root文件系統、自己的網絡配置、自己的進程空間,甚至自己的用戶 ID 空間。 |
| 3 | 容器內的進程是運行在一個隔離的環境里,使用起來,就好像是在一個獨立于宿主的系統下操作一樣。這種特性使得容器封裝的應用比直接在宿主運行更加安全。也因為這種隔離的特性,很多人初學 Docker 時常常會混淆容器和虛擬機 |
| 4 | 容器也是與鏡像一樣分層存儲,每次容器運行時,是以鏡像為基礎層在其之上創建當前容器的存儲層(稱之為容器運行時); 為讀寫而準備的存儲層稱之為容器存儲層(容器存儲層的生命周期和容器是一樣的,容器消亡時容器存儲層也隨之消亡,任何存保存存儲層的數據信息都會隨著容器的刪除而刪除【所以容器中的存儲層是不應該寫入任何數據進行存儲的,容器存儲層應該保持一個無狀態變化,所有的文件寫入操作都應該使用【數據卷】或者【綁定宿主機目錄】(也就是把數據寫入到宿主機目錄中)】數據卷的生命周期是獨立于容器的(即與容器無關))。 |
? 2.2.3、Docker倉庫
????????鏡像構建完成后,可以很容易的在當前宿主機上運行,但是,如果需要在其它服務器上使用這個鏡像,我們就需要一個集中的存儲、分發鏡像的服務, Docker Registry 就是這樣的服務。
????????一個 Docker Registry 中可以包含多個倉庫(Repository),每個倉庫可以包含多個標簽(Tag);每個標簽對應一個鏡像。通常,一個倉庫會包含同一個軟件不同版本的鏡像,而標簽就常用于對應該軟件的各個版本:
????????《1》我們可以通過【倉庫名:標簽】的格式來指定具體這個軟件是哪個版本的鏡像;
????????《2》若不給標簽則以【latest】為默認的標簽。
倉庫可以分為【公共倉庫】【私有倉庫】:
????????《1》公共倉庫:主要提供公開的服務,允許用戶免費的去下載鏡像、上傳鏡像(最大的倉庫就是Docker的Docker Hub、國內可以使用阿里云鏡像倉庫);
????????《2》私有倉庫:適用于內部數據和機密數據的鏡像場景(可用于構建本地私有倉庫的知名軟件有:VMware Harbor?、Nexus Repository)。
三、容器編排工具
?3.1、容器編排工具Kubernetes
????????容器編排工具Kubernetes,中文意思是舵手或導航員。 Kubernetes這個單詞很長不好記,所以大家把K到S中間8個字母縮寫成8,就成了K8S。
? ? ? ? Kubernetes是谷歌開源的容器管理系統,在Docker基礎之上為容器化的應用提供了【部署運行】【資源調度】【服務發現】【動態伸縮】等一系列的完整編排功能,提高了大規模容器集群管理的便捷性。K8S的主要設計思想是從更宏觀的角度,以統一的方式來定義任務之間的各種關系,并且為將來支持更多種類的任務留下足夠的余地。
????????K8S擅長的就是按照用戶的意愿和整體的系統規則完全自動化的去處理好容器之間的各種關系,這種功能就是我們經常說到的編排。K8S的本質就是【為用戶提供一個具有普遍意義的容器編排工具】。【K8S是對Docker容器的編排】【OpenStack是對KVM虛擬化的編排】。
????????K8S是一個容器集群管理系統,主要職責是容器編排(Container Orchestration) ——啟動容器,自動化部署、擴展和管理容器應用,還有回收容器。簡單來說, K8S有點像容器的保姆。它負責管理容器在哪個機器上運行,監控容器是否存在問題,控制容器和外界的通信等等。
?3.2、Kubernetes的重要概念
| 序號 | Kubernetes重要概念 | 說明 |
| 1 | Cluster | 是計算存儲和網絡資源的集合;K8S就是利用這些資源進行各種基于容器的應用 |
| 2 | Master | 是Cluster的大腦,主要職責是調度,是用來決定將應用放到哪里去運行【是K8S中的管理者角色,可以有多個】。 ????????Master是運行在Linux操作系統中,這個系統可以是物理機或者虛擬機,為了實現高可用性,我們在實際的生產環境當中,會把Master做成多個,實現高可靠性【K8S是支持多Master架構】 |
| 3 | Node | Node的職責是運行容器應用【負責監控、匯報容器狀態】,是由Master管理(Node同時可以根據Master的要求去管理應用的生命周期)。 ? ? ? ? Node也是運行在Linux操作系統中,這個系統可以是物理機或者虛擬機。 |
| 4 | Pod | Pod是K8S中最小的工作單元,每個Pod可以包含一個或者多個容器; Pod中的容器會被看作是一個整體被Master調度到一個Node中去運行,Pod有兩種使用方式: ????????《1》一個Pod運行單一的容器(運行單一容器是K8S最常見的模型,即便只有一個容器,K8S管理的也是一個Pod,不會直接管理容器); ????????《2》一個Pod運行多個容器(Pod中運行多個容器的話,哪些容器應該放到一個Pod中呢?【答案是這些容器聯系必須非常緊密,而且需要共享資源的時候,才需要把多個容器放到一個Pod里面】); |
| 5 | Controller | K8S不會直接創建Pod,而是通過Controller來管理Pod; Controller定義了Pod的部署特性(如:Pod有幾個副本、在什么樣的Node去運行)為了滿足不同的業務場景,K8S提供了多種Controller(如: ????????《1》Replicat? Controller【簡稱RC】(是K8S集群中最早保證Pod高可用的API對象,通過監控運行中的Pod來保證集群中運行指定數目的Pod副本,指定的數目可以是一個也可以是多個,少于指定數目時RC就會啟動運行新的Pod副本;多于指定數目時,RC就會殺死多余的Pod副本;即使在指定Pod數目為一的情況,通過RC運行Pod也比直接運行Pod明智,因為RC可以發揮它高可用的能力,永遠保證有指定數目的Pod副本在運行)【只適用于長期伺服型的業務類型(如:提供高可用的Web服務等),目前已經很少使用了】。 ????????《2》Replica?Set【簡稱RS】、 ????????《3》Deployment【部署】、 ????????《4》Daemonset【后臺支撐型服務】、 ????????《5》Job等)。 |
| 6 | Replica Set (RS) | Replica Set【簡稱RS】是新一代的RC(或者是RC的升級版)同樣提供了高可用的能力,區別在于:RS后來居上,能夠支持更多種類的匹配模式。 ????????RS對象一般不單獨使用,而是作為Deployment這樣的資源一塊配合使用;使用Deployment的時候,Deployment會自動創建RS,也就是說Deployment是通過RS來管理Pod的多個副本的;我們通常是不用直接去使用RS。 |
| 7 | deployment(部署) | deployment表示用戶對K8S集群的一次更新操作,它是一個比RS業務模式更廣的API對象;它可以創建一個新的服務、更新一個新的服務、也可以滾動升級一個服務。 ????????以K8S的發展方向來說,未來對所有長期伺服型的業務管理,都會去通過deployment來進行管理實現 |
| 8 | ?daemonset (后臺支撐型服務) | 長期伺服型和批處理型服務的核心,在業務應用:可能有些節點在運行多個同類業務的Pod,有些節點又沒有這類業務在運行;而后臺支撐型服務的核心的關注點是在K8S中每個節點,它要保證每個節點上都有一個此Pod在運行,節點可能是所有集群節點選定的一些特定節點。 ????????典型的后臺支撐性服務節點包括:【存儲】【日志】【監控】等在每個節點上支持K8S集群運行的服務 |
| 9 | Service | Service的用途首先要從deployment來說,deployment可以部署多個Pod副本,每個Pod都有自己的IP地址,那么這個時候外界是如何去訪問這些副本呢?【答案就是Service】。 ????????K8S的Service定義了外界訪問一組特定的Pod的方法方式,Service也有自己的IP和端口,并且Service為Pod服務提供了一個負載均衡;K8S運行容器Pod與訪問容器這兩項任務分別是由Controller和Service來執行的。 |
| 10 | namespace | 可以將一個物理的Cluster集群邏輯上劃分為多個虛擬的集群,那么每個集群就是一個namespace;不同的namespace的資源是完全隔離的,K8S默認創建了兩個namespace: 《1》其中一個是default(這個是創建資源池如果不指定就會把資源放到這個namespace里面來)、 《2》另外一個是系統自動創建的kube-system(K8S自己創建的系統資源都會放到這個namespace當中)。 |
?3.3、Kubernetes運行架構
????????Kubernetes屬于主從分布式架構,主要由Master Node和Worker Node(一般叫做Node節點)成,以及包括客戶端命令行工具kubectl和其它附加項來組成。基本架構如下圖所示:

![]() | ||
| 序號 | Master節點運行的服務 | 說明 |
| 1 | kube-apiserver | 是K8S的前端接口;各種客戶端工具,以及K8S的其他組件都可以通過kube-apiserver來管理集群中的各種資源【是K8S管理集群的入口】 |
| 2 | kube-scheduler | 是負責決定將Pod放到哪個Node上去運行;另外kube-scheduler在調度時它也會充分考慮集群的架構、當前各個節點的負載、以及應用對高可用系統的性能、數據親和性等的需求 |
| 3 | kube-controller-manager | 主要是用來維護集群的狀態(如:故障檢測、自動擴展、滾動更新等);不同的Controller管理的資源是不同的。 |
| 4 | Etcd | Etcd是負責保存K8S集群的配置信息和各種集群的狀態信息; K8S中所有服務節點的信息和服務數據(包括:配置數據)都是存儲在Etcd中;當數據發生變化的時候,Etcd會快速的通知K8S的相關組件 |
| 5 | pod網絡(flannel ) 等 | Pod要能夠互相通信,K8S集群必須要能夠掌握Pod網絡;Pod網絡我們使用比較多的就是flannel(是K8S集群網絡互聯的一個可選方案) |
![]() | ||
| 序號 | Node節點運行的服務 | 說明 |
| 1 | Kubelet | 是Node的Agent(當kube-scheduler去確定在某個Node上進行Pod后,會將Pod的具體配置信息發送給改節點的Kubelet,Kubelet會根據這些信息去創建和運行容器,并向Master報告運行的狀態信息) |
| 2 | kube-proxy | 要了解Kube-proxy就需要先說一下Service,Service在邏輯上是代表了K8S后端的多個Pod,那么外界通過Service訪問Pod,Service接受到這個請求信息后是如何轉發到這個Pod上的呢?【這個就是Kube-proxy要完成的工作】。? ????????Kube-proxy是配合Service實現從Pod到Service,以及從外部Node到Service訪問的一個流程,每個Node上都會運行Kube-proxy服務,它負責將訪問Service的TCP、UDP的數據流轉發到后端的容器上;如果有多個副本,那么Kube-proxy還可以實現負載均衡。 |
| 3 | pod網絡(flannel ) | Pod和Pod之間(也就是不同Node之間多個Pod)要實現相互通信,那么K8S集群必須要部署Pod網絡,也是選用flannel(可以實現不同主機上、不同Pod之間的相互通信) |

