天天看點

Docker 核心技術導讀:Docker 核心技術預覽

該文章搬運于https://gitchat.csdn.net/column/59e464726958416d85ae9207/topic/59e46f246958416d85ae95fd,僅為友善自己與他人學習。

導讀:Docker 核心技術預覽

2017年3月 Docker 官方釋出消息,原 SAP 高管 Steve Singh 接任 Ben Golub 成為新的首席執行官。這是一個特别時期,經過四年的長足發展,Docker 已經成為一家高速發展的雲計算開源技術上司品牌,但是其商業模式至今不太明朗。

Steve 的商業經驗至少可以說是目前最合适成為 Docker 領軍人物的人選,在距離 IPO 上市近在咫尺的路上,本文期望通過深入預覽 Docker 核心技術的概念,讓大家全面了解 Docker 技術對雲計算發展的深遠意義。

背景

由 PaaS 到 Container

2013年2月,前 Gluster 的 CEO,Ben Golub 和 dotCloud 的 CEO,Solomon Hykes 坐在一起聊天時,Solomon 談到想把 dotCloud 内部使用的 Container 容器技術開源出來,并圍繞這項技術開一家新公司并提供商業技術支援。

這一想法源于28歲的 Solomon 在研發 dotCloud 的 PaaS 雲平台時發現的機會。通過使用 Ubuntu 社群的 LXC(Linux Container)技術可以便捷的建構應用環境鏡像并釋出到主機平台運作。這種容器技術可以把開發者從日常部署更新應用環境配置的繁雜工作中解脫出來。事實上,自從進入 DevOps 理念之後,開發團隊迫切需要從各種混亂的部署環境中解脫出來。他們越深入交談,越覺得這是一次雲計算技術的變革。不久之後在2013年3月 Docker 0.1釋出,從此拉開了基于雲計算容器技術的變革序幕。

Docker 簡介

Docker 核心技術導讀:Docker 核心技術預覽

Docker 是 Docker Inc 公司開源的一項基于 Ubuntu LXC 技術之上建構的應用打包運作時引擎,源代碼托管在 GitHub 上,完全基于 go 語言開發并遵守 Apache2.0 協定開源。 Docker 在2014年6月召開的 DockerCon 2014 技術大會上,吸引了 IBM、Google、RedHat 等業界知名公司的關注和技術支援。無論是從 GitHub 上的代碼活躍度,還是開源巨頭紅帽宣布在 RHEL7 中正式支援 Docker 技術,都可以說明 Docker 技術是一項創新型的技術解決方案,就連 Google 公司的 Compute Engine 也很快支援 Docker 在其之上運作。國内 BATJ(百度雲、阿裡雲、騰訊雲、京東雲)也相繼推出容器服務緊追雲計算發展趨勢。

Docker 核心技術導讀:Docker 核心技術預覽

Docker 技術解決以下問題:

  • 複雜的環境配置管理:從各種 OS 環境到各種中間件環境以及各種應用環境。

在軟體行業中任何應用要做到成功釋出,開發團隊需要關心的東西太多且難于統一管理,這個問題普遍存在并需要直接面對。Docker 技術旨在簡化部署多種應用執行個體環境依賴,如 Web 應用、背景應用、資料庫應用、大資料應用(例如Hadoop叢集)、消息隊列(例如Kafka)等等都可以打包成一個鏡像部署。如圖所示:

Docker 核心技術導讀:Docker 核心技術預覽
  • 雲計算時代的到來:AWS 的成功,引導開發者将應用轉移到雲上,解決了硬體管理的問題,然而軟體配置和管理相關的問題依然存在(AWS cloudformation 是這個方向的業界标準,樣例模闆可參考這裡)。Docker 的出現正好能幫助軟體開發者開闊思路,嘗試新的軟體管理方法來解決這個問題。
  • 虛拟化手段的變化:雲時代采用标配硬體來降低成本,采用虛拟化手段來滿足使用者按需配置設定的資源需求以及保證可用性和隔離性。然而無論是 KVM 還是 Xen,在 Docker 看來都在浪費資源,因為使用者需要的是高效運作環境而非 OS,GuestOS 既浪費資源又難于管理,輕量級的 LXC 更加靈活和快速。如圖所示:
Docker 核心技術導讀:Docker 核心技術預覽
  • 容器技術的便攜性:LXC 在 Linux2.6 的 Kernel 裡就已經存在了,但是其設計之初并非為雲計算考慮的,缺少标準化的描述手段和容器的可便攜性,決定其建構出的環境難于分發和标準化管理(相對于 KVM 之類 image 和 snapshot 的概念)。Docker 就在這個問題上做出了實質性的創新方法。

Docker 的 Hello World

以 Fedora25 作為主機為例,直接安裝

$ sudo dnf install docker-ce
           

啟動 Docker 背景 Daemon:

$ sudo systemctl start docker
           

跑第一個 Hello World 容器執行個體:

$ sudo docker run hello-world
           

随後可以看到在指令行控制台中列印出經典的Hello World 字元串。

核心技術預覽

Docker 核心是一個作業系統級虛拟化方法,了解起來可能并不像 VM 那樣直覺。我們從虛拟化方法的四個方面:隔離性、可配額/可度量、便攜性、安全性來詳細介紹 Docker 的技術細節。

隔離性:Linux Namespace(ns)

每個使用者執行個體之間互相隔離,互不影響。一般的硬體虛拟化方法給出的方法是 VM,而 LXC 給出的方法是 container,更細一點講就是 kernel namespace。其中 pid、net、ipc、mnt、uts、user 等 namespace 将 container 的程序、網絡、消息、檔案系統、UTS(“UNIX Time-sharing System”)和使用者空間隔離開。

pid namespace

不同使用者的程序就是通過 pid namespace 隔離開的,且不同 namespace 中可以有相同 pid。所有的 LXC 程序在 Docker中的父程序為 Docker 程序,每個 lxc 程序具有不同的 namespace。同時由于允許嵌套,是以可以很友善的實作 Docker in Docker。

net namespace

有了 pid namespace,每個 namespace 中的 pid 能夠互相隔離,但是網絡端口還是共享 host 的端口。網絡隔離是通過 net namespace 實作的,每個 net namespace 有獨立的 network devices,IP addresses,IP routing tables,/proc/net 目錄。這樣每個 container 的網絡就能隔離開來。Docker 預設采用 veth 的方式将 container 中的虛拟網卡同 host 上的一個 docker bridge:docker0連接配接在一起。

ipc namespace

container 中程序互動還是采用 linux 常見的程序間互動方法(interprocess communication - IPC),包括常見的信号量、消息隊列和共享記憶體。然而同 VM 不同的是,container 的程序間互動實際上還是 host 上具有相同 pid namespace 中的程序間互動,是以需要在 IPC 資源申請時加入 namespace 資訊——每個 IPC 資源有一個唯一的32位 ID。

mnt namespace

類似 chroot,将一個程序放到一個特定的目錄執行。mnt namespace 允許不同 namespace 的程序看到的檔案結構不同,這樣每個 namespace 中的程序所看到的檔案目錄就被隔離開了。同 chroot 不同,每個 namespace 中的 container 在/proc/mounts 的資訊隻包含所在 namespace 的 mount point。

uts namespace

UTS(“UNIX Time-sharing System”)namespace 允許每個 container 擁有獨立的 hostname 和 domain name,使其在網絡上可以被視作一個獨立的節點而非 Host 上的一個程序。

user namespace

每個 container 可以有不同的 user 和 group id,也就是說可以在 container 内部用 container 内部的使用者執行程式而非 Host 上的使用者。

可配額/可度量 Control Groups (cgroups)

cgroups 實作了對資源的配額和度量。 cgroups 的使用非常簡單,提供類似檔案的接口,在/cgroup 目錄下建立一個檔案夾即可建立一個 group,在此檔案夾中建立 task 檔案,并将pid 寫入該檔案,即可實作對該程序的資源控制。groups 可以限制 blkio、cpu、cpuacct、cpuset、devices、freezer、memory、net_cls、ns 九大子系統的資源,以下是每個子系統的詳細說明:

  1. 有序清單 blkio 這個子系統設定限制每個塊裝置的輸入輸出控制。例如:磁盤,CD光牒以及 usb 等等。
  2. cpu 這個子系統使用排程程式為 cgroup 任務提供 cpu 的通路。
  3. cpuacct 産生 cgroup 任務的 cpu 資源報告。
  4. cpuset 如果是多核心的 cpu,這個子系統會為 cgroup 任務配置設定單獨的 cpu 和記憶體。
  5. devices 允許或拒絕 cgroup 任務對裝置的通路。
  6. freezer 暫停和恢複 cgroup 任務。
  7. memory 設定每個 cgroup 的記憶體限制以及産生記憶體資源報告。
  8. net_cls 标記每個網絡包以供 cgroup 友善使用。
  9. ns 名稱空間子系統。

以上九個子系統之間也存在着一定的關系。詳情請參閱官方文檔。

便攜性

AUFS(AnotherUnionFS)是一種 Union FS,簡單來說就是支援将不同目錄挂載到同一個虛拟檔案系統下(unite several directories into a single virtual filesystem)的檔案系統。更進一步地了解,AUFS 支援為每一個成員目錄(類似Git Branch)設定 readonly、readwrite 和 whiteout-able 權限。同時 AUFS 裡有一個類似分層的概念,對 readonly 權限的 branch 可以邏輯上進行修改(增量地,不影響 readonly 部分的)。

通常 Union FS 有兩個用途,一方面可以實作不借助 LVM、RAID 将多個 disk 挂到同一個目錄下;另一個更常用的就是将一個 readonly 的 branch 和一個 writeable 的 branch 聯合在一起,Live CD 正是基于此方法可以允許在 OS image 不變的基礎上允許使用者在其上進行一些寫操作。Docker 在 AUFS 上建構的 container image 也正是如此,接下來我們從啟動 container 中的 linux 為例來介紹 Docker 對 AUFS 特性的運用。

典型的啟動Linux運作需要兩個FS:bootfs + rootfs

Docker 核心技術導讀:Docker 核心技術預覽

bootfs(boot file system)主要包含 bootloader 和 kernel,bootloader 主要是引導加載 kernel,當 boot 成功後 kernel 被加載到記憶體中後 bootfs 就被 umount 了。 rootfs(root file system)包含的就是典型 Linux 系統中的/dev,/proc,/bin,/etc 等标準目錄和檔案。

對于不同的 linux 發行版,bootfs 基本是一緻的。但 rootfs 會有差别,是以不同的發行版可以公用 bootfs。如下圖:

Docker 核心技術導讀:Docker 核心技術預覽

典型的 Linux 在啟動後,首先将 rootfs 設定為 readonly,進行一系列檢查,然後将其切換為 “readwrite”供使用者使用。在 Docker 中,初始化時也是将 rootfs 以 readonly 方式加載并檢查,然而接下來利用 union mount 的方式将一個 readwrite 檔案系統挂載在 readonly 的 rootfs 之上,并且允許再次将下層的 FS(file system)設定為 readonly,并且向上疊加,這樣一組 readonly 和一個 writeable 的結構構成一個 container 的運作時态,每一個 FS 被稱作一個 FS 層。如下圖:

Docker 核心技術導讀:Docker 核心技術預覽

得益于 AUFS 的特性,每一個對 readonly 層檔案/目錄的修改都隻會存在于上層的 writeable 層中。這樣由于不存在競争,多個 container 可以共享 readonly 的 FS 層。是以 Docker 将 readonly 的 FS 層稱作“image”-——對于 container 而言整個 rootfs 都是 read-write 的,但事實上所有的修改都寫入最上層的 writeable 層中,image 不儲存使用者狀态,隻用于模闆、建立和複制使用。

Docker 核心技術導讀:Docker 核心技術預覽

上層的 image 依賴下層的 image,是以 Docker 中把下層的 image 稱作父 image,沒有父 image 的 image 稱作 base image。是以想要從一個 image 啟動一個 container,Docker 會先加載這個 image 和依賴的父 images 以及 base image,使用者的程序運作在 writeable 的 layer 中。所有 parent image 中的資料資訊以及 ID、網絡和 lxc 管理的資源限制等具體 container 的配置,構成一個 Docker 概念上的 container。如下圖:

Docker 核心技術導讀:Docker 核心技術預覽

安全性:AppArmor,SELinux,GRSEC

安全永遠是相對的,這裡有三個方面可以考慮Docker 的安全特性:

  • 由 kernel namespaces 和 cgroups 實作的 Linux 系統固有的安全标準;
  • Docker Deamon 的安全接口;
  • Linux 本身的安全加強解決方案,例如 AppArmor,SELinux;

由于安全屬于非常具體的技術,這裡不在贅述,請直接參閱 Docker 官方文檔。

總結

Docker 社群一直在面對技術挑戰,從容地給出自己的解決方案。雲計算發展至今,有很多重要的問題沒有得到妥善解決,Docker 正在嘗試讓主流廠商接受并應用它的解決方案。至此,以上 Docker 技術的預覽到此告一段落,筆者也希望讀者能結合自己的實際情況,嘗試使用 Docker 技術。隻有在親自體會的基礎之上,Docker 技術才會産生更大的商業價值。

繼續閱讀