Kubernetes 普及系列:容器基礎入門

隨著雲原生時代的來臨,雲以及分散式計算已經是時下最受歡迎的技術之一了。其中 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 NamespaceLinux 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 //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] //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,讓我們下回再見!