隨著雲原生時代的來臨,雲以及分散式計算已經是時下最受歡迎的技術之一了。其中 Docker 作為最知名的容器平臺,到底有著怎樣的魅力來讓其無人不知無人不曉?廢話不多說,讓我們開始逐層掀開容器技術的神祕面紗吧!
Docker
從傳統 IT 到 IaaS 到 PaaS 的能力變遷
讓時間回到 2013 年,在該時候,虛擬機器和雲服務已經很流行了。主流使用者的常見做法,就是在雲平臺(比如騰訊雲、AWS、OpenStack 等),像管理物理伺服器一樣用指令碼來做管理和部署應用。
這樣的做法一直存在本地環境和線上環境不一致導致部署出現問題的風險,所以各家雲平臺的思路都是去模擬出更加接近本地伺服器的環境,來給使用者提供更好的上雲體驗。所以開源的 PaaS 專案提供“應用託管”的能力,就是解決該問題的一個最佳方案。
在眾多開源 PaaS 專案中,最熱門的 Cloud Foundry 基本上已經吸引了所有云廠商的目光,開啟了以開源 PaaS 為核心構建平臺層服務能力的變革。
大家可能並不是很熟悉 Cloud Foundry,簡單地說,Cloud Foundry 所做的就是提供一個 "cf push" 命令列工具,讓大家能夠對一些主流語言的程式碼進行打包上傳和分發。然後 Cloud Foundry 通過呼叫作業系統的 CGroups 和 Linux Namespace,單獨為每一個應用建立一個隔離的沙盒環境,然後在其中啟動這些應用的程式。
Cloud Foundry 的最核心命令 cf push 的業務流程圖
所以當時 Cloud Foundry 最核心的能力,就是提供隔離的執行環境,也就是“容器”了。
當時的 PaaS 風潮參與者,dotCloud 是最不起眼的公司之一
同期,有一家名叫 dotCloud 的公司,因為它的主打產品跟 Cloud Foundry 社群是脫節的,所以長期以來都無人問津。終於,dotCloud 公司決定開源自己的容器專案 Docker。
但很可惜在當時並沒有人關注 dotCloud 的該決定,因為“容器”該概念從來就不是什麼新鮮的東西,也不是 Docker 公司發明的。哪怕是在當時最熱門的 PaaS 專案 Cloud Foundry 裡,容器也只是其最底層,最沒人關注的那一部分。
而 Docker 專案,實際上和 Cloud Foundry 的容器並沒有太大的不同,所以在 Docker 釋出後不久,Cloud Foundry 的首席產品經理 James Bayer 就在社群裡做了一次詳細對比,告訴使用者 Docker 實際上只是一個同樣使用 Cgroups 和 Namespace 實現的“沙盒”而已,沒有什麼特別的黑科技,也不需要特別關注。
然而,幾個月後,James Bayer 就被打臉了。Docker 只用了短短几個月,就讓所有 PaaS 社群都出局了。事實上,Docker 專案確實和 Cloud Foundry 的容器在大部分功能和實現原理上並沒有什麼區別,但僅有的一個不一樣的功能,成了 Docker 專案的制勝關鍵。
該功能就是 Docker 映象。
當時主流的 PaaS 專案,如 Cloud Foundry,都通過提供一套應用打包功能,幫助使用者大規模部署到叢集。但就是該打包功能,需要使用者為每個應用做大量的配置工作和除錯工作,才能讓本地能供正確執行的應用,在叢集裡也能正確執行。
而 Docker 映象,恰好解決了該根本性的問題。Docker 映象的本質,就是一個壓縮包,但和 PaaS 的應用打包相比,該壓縮包裡則是多了完整的執行環境依賴內容,比如作業系統的所有檔案和目錄。只要使用者拿著該壓縮包,便可以通過某些技術手段在任何地方建立一個沙盒來執行使用者的應用了,因為其做到了本地環境和雲端環境高度的一致,再加上 Docker 充滿趣味性的推廣,比如 “1 分鐘部署一個 WordPress 網站”、“3 分鐘部署一個 Nginx 叢集”等,最終通過與開發者的親密關係,加上解決了打包的根本性難題,從而一舉登天。
Linux Namespace,Linux Cgroups ,rootfs
我們前面已經介紹了 Docker 的發展,那麼,迴歸到技術本身,容器到底是什麼呢?這裡可以先下一個定義:
一個“容器”,實際上是一個由 Linux Namespace、Linux Cgroups 和 rootfs 三種技術構建出來的程式的隔離環境。
- Linux Namespace 和 Linux Cgroups,提供了執行時的隔離和資源的授予。
- rootfs,也就是映象,提供了容器的執行內容。
比如對於如下 Dockerfile:
# 使用官方提供的 Python 開發映象作為基礎映象
FROM python:3.8-slim-buster
# 將工作目錄切換為 /app
WORKDIR /app
# 拷貝應用依賴描述檔案到工作目錄
COPY requirements.txt requirements.txt
# 使用 pip 命令安裝應用以及其所需的依賴
RUN pip3 install -r requirements.txt
# 拷貝應用檔案到工作目錄
COPY . .
# 設定容器程式為 "python3 app.py",也是該 Python 應用的啟動命令
CMD [ "python3", "app.py"]
在該 Dockerfile 裡,我們先通過一個基礎映象 python:3.8-slim-buster,安裝依賴並複製應用到工作目錄,最後指定應用的程式,即啟動命令。在該描述下,我們會得到如下容器檢視:
該容器的程式是“python3 app.py”,執行在由 Linux namespace + Linux cgroups 構成的隔離環境裡。而它所需要的各種檔案,包括 Python、app.py 和整個作業系統檔案,則由多個聯合掛載在一起的 rootfs 提供。該 rootfs 的最下層,是隻讀的 Docker 映象。在 Docker 映象之上,是 Docker 的管理器新增的 init 層,用於臨時存放被管理器修改過的 /etc/hosts 等檔案。在 rootfs 的最上層是讀寫層,以 Copy-On-Write 的方式存放所有對只讀層檔案的修改,和容器宣告的 Volume 掛載點。從該容器檢視裡,我們可以總結出一個執行中的 Linux 容器,由以下內容構成:
- 一組聯合掛載的 rootfs,這部分我們稱之為容器的“映象”(Image)。
- 一個由 Linux namespace + Linux cgouprs 構成的隔離環境,這部分我們稱之為容器的“執行時”(Runtime)。
Docker install
前文已經介紹了容器的本質和其背後的邏輯,我們現在以 Ubuntu 18 LTS
為例,介紹如何安裝 Docker,為後面的 Kubernetes 做好準備。
配置 REPOSITORY
1、更新 apt
包管理器索引和配置 apt
能夠使用 HTTPS 的倉庫。
sudo apt-get update
sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg \
lsb-release
2、新增 Docker 官方 GPG 公鑰。
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
3、指定使用穩定版的 Docker 版本。
echo \
"deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
安裝 Docker engine
1、更新 apt
包管理器索引,然後安裝最新的穩定版 Docker engine。
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
2、安裝完成後,通過執行 hello-world
映象,驗證 Docker engine。
sudo docker run hello-world
現在安裝完成,可以開始使用 Docker 了。
容器編排
作為一名開發者,我們其實並不關心容器執行時的差異,因為在整個“開發-釋出”流程中,真正釋出的其實是容器映象。對於雲服務商來說,則可以通過容器映象將他們和潛在使用者(如開發者)直接關聯起來。因此,能夠定義容器組織和管理規範的“容器編排”技術,成為了雲端計算最熱門的技術。這其中,最具代表性的容器編排工具有如下兩個:
• Docker 公司的 Compose+Swarm 組合;
• Google 與 RedHat 公司共同主導的 Kubernetes 專案。而目前該專案已經成為業界標準。
接下來的 Kubernetes 普及系列,將會帶大家深入瞭解目前承載著雲原生髮展的絕對主角——Kubernetes,讓我們下回再見!