Docker與虛擬化技術淺析第一彈之docker與Kubernetes

京東雲發表於2022-08-24

1 前言

Docker是一個開源的引擎,可以輕鬆地為任何應用建立一個輕量級的、 可移植的、自給自足的容器。開發者在膝上型電腦上編譯測試透過的容器可以批次地在生產環境中部署,包括VMs (虛擬機器)、bare metal、OpenStack 叢集和其他基礎應用平臺。
Docker的目標:

  • 提供輕量簡單的建模方式;
  • 職責的邏輯分離;
  • 快速高效的開發生命週期;
  • 鼓勵使用面向服務的架構,即單個容器執行單個應用。

Docker本質上是執行在宿主機上的程式,它透過namespace實現了資源隔離,並透過cgroups實現了資源限制,同時透過寫時複製(copy-on-write)實現了高效的檔案操作。

cgroups是Linux核心提供的一種機制,這種機制可以根據需求把一系列系統任務及其子任務整合(或分隔)到按資源劃分等級的不同組內,從而為系統資源管理提供一個統一的框架。也就是說,cgroups可以限制、記錄任務組所使用的物理資源(包括CPU、memory、IO等),為容器實現虛擬化提供了基本保證,是構建Docker等一系列虛擬化管理工具的基石。

cgroups提供瞭如下四大功能:

  • 資源限制:cgroups可以對任務使用的資源總額進行限制。
  • 優先順序分配:透過分配的CPU時間片數量以及磁碟IO頻寬大小,實際上就相當於控制了任務執行的優先順序。
  • 資源統計:cgroups可以統計系統的資源使用量,如CPU使用時長等。
  • 任務控制:cgroups可以對任務執行掛起、恢復等操作。

    2 docker與虛擬機器

Docker守護程式可以直接與主作業系統進行通訊,為各個Docker容器分配資源;它還可以將容器與主作業系統隔離,並將各個容器互相隔離。虛擬機器啟動需要數分鐘,而Docker容器可以在數毫秒內啟動。由於沒有臃腫的從作業系統,Docker可以節省大量的磁碟空間以及其他系統資源。

說了這麼多Docker的優勢,大家也沒有必要完全否定虛擬機器技術,因為兩者有不同的使用場景。虛擬機器更擅長於徹底隔離整個執行環境。例如,雲服務提供商通常採用虛擬機器技術隔離不同的使用者。而Docker通常用於隔離不同的應用,例如前端後端以及資料庫,類似一個“沙箱”。

3 docker基礎

3.1 Docker三大概念和兩句口號

三大核心概念:

  • 映象(Image)
  • 容器(Container)
  • 倉庫(Repository)

兩句口號:
Build, Ship and Run
Build once,Run anywhere

3.2 認識Dockerfile

dockerfile僅僅是用來製作映象的原始碼檔案,是構建容器過程中的指令,docker能夠讀取dockerfile檔案,進行指定容器的自動構建。

除了dockerfile這種自定義構建映象的方式以外,還支援從公共倉庫(dockerHub)拉取的方式:https://hub.docker.com/ 、或者基於現有的映象進行最佳化docker commi,以下是一個自定義的Dockerfile,以及根據Dockerfile檔案構建mytest映象的過程

from tomcatMAINTAINER yangjianmin@jd.comRUN rm -rf /usr/local/tomcat/webapps/*COPY jhjkhkj.zip   /usr/local/tomcat/webappsENV TZ=Asia/ShanghaiRUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

3.3 映象與分層

映象由多個層組成,每層疊加之後,從外部看來就如一個獨立的物件。映象內部是一個精簡的作業系統(OS),同時還包含應用執行所必須的檔案和依賴包。因為容器的設計初衷就是快速和小巧,所以映象通常都比較小。映象可以理解為一種構建時(build-time)結構,而容器可以理解為一種執行時(run-time)結構。

以我本地的nginx為例,透過docker image inspect命令檢視映象分層的方式:

% docker image inspect nginx:latest[    {        "Id": "sha256:605c77e624ddb75e.....9dc3a85",        "RepoTags": [            "nginx:latest"        ],略過一些內容。。。        "RootFS": {            "Type": "layers",            "Layers": [                "sha256:2edcec3590a4ec7f40.....41ef9727da6c851f",                "sha256:e379e8aedd4d72bb4c.....80179e8f02421ad8",                "sha256:b8d6e692a25e11b0d3.....e68cbd7fda7f70221",                "sha256:f1db227348d0a5e0b9.....cbc31f05e4ef8df8c",                "sha256:32ce5f6a5106cc637d.....75dd47cbf19a4f866da",                "sha256:d874fd2bc83bb3322b.....625908d68e7ed6040a6"            ]        },        "Metadata": {            "LastTagTime": "0001-01-01T00:00:00Z"        }

可以看到,我從遠端拉下來的最新的nginx映象是由六層結構組成的,當我們拉取映象時也可以看到分層拉取的記錄,為了儘量減少映象層數,在寫Dockerfile時應儘量整合RUN命令,因為每執行一次RUN命令,層數就會加1。

3.4 映象執行

docker images:檢視映象列表,TAG相當於jar包版本描述了映象的版本
docker run -d -p 91:80 nginx:執行nginx映象,-d表示相關啟動日誌後臺展示,-p是將本機作業系統的埠和容器內部埠做對映,起到將docker容器指定埠對外暴露的作用。我們便可以透過訪問91埠請求到剛剛啟動的nginx。

docker ps:可以檢視已經執行的容器的情況。
有關docker的操作命令不在本文展開介紹,感興趣的小夥伴可以自行學習。

% docker imagesREPOSITORY               TAG       IMAGE ID       CREATED        SIZEmytest                   latest    26d746eb2c68   26 hours ago   680MBnginx                    latest    605c77e624dd   13 days ago    141MBtomcat                   latest    fb5657adc892   2 weeks ago    680MBdocker/getting-started   latest    26d80cd96d69   5 weeks ago    28.5MByangjianmin@192 ~ % docker run -d -p 91:80 nginx  dcf193ebf5dd1b3267eddff37158535036918451938c4c90f98d2b12edf6c608yangjianmin@192 ~ % docker psCONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS         PORTS                NAMESdcf193ebf5dd   nginx     "/docker-entrypoint.…"   10 seconds ago   Up 9 seconds   0.0.0.0:91->80/tcp   nifty_stonebraker

4 docker-compose、docker-machine

Compose 是用於定義和執行多容器 Docker 應用程式的工具。透過 Compose,您可以使用 YML 檔案來配置應用程式需要的所有服務。然後,使用一個命令,就可以從 YML 檔案配置中建立並啟動所有服務。

Compose允許使用者透過一個單獨的docker-compose.yml模板檔案(YAML 格式)來定義一組相關聯的應用容器為一個專案(project)。
Docker-Compose專案由Python編寫,呼叫Docker服務提供的API來對容器進行管理。因此,只要所操作的平臺支援Docker API,就可以在其上利用Compose來進行編排管理。
docker-compose.yml

mysql: image: daocloud.io/yjmyzz/mysql-osx:latest volumes:   - ./mysql/db:/var/lib/mysql ports:   - 3306:3306 environment:   - MYSQL_ROOT_PASSWORD=123456service1: image: java:latest volumes:   - ./java:/opt/app expose:   - 8080 #ports: #  - 9081:8080 links:   - mysql:default command: java -jar /opt/app/spring-boot-rest-framework-1.0.0.jarservice2: image: java:latest volumes:   - ./java:/opt/app expose:   - 8080 #ports: #  - 9082:8080 links:   - mysql:default command: java -jar /opt/app/spring-boot-rest-framework-1.0.0.jarnginx1:  image: nginx:latest  volumes:   - ./nginx/html:/usr/share/nginx/html:ro   - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro   - ./nginx/conf.d:/etc/nginx/conf.d:ro  #expose:  #  - 80  ports:   - "80:80"  links:   - service1:service1   - service2:service2

可以將上述檔案看成docker run的批次版本,以最小單元來看,包含了映象名和版本(nginx:latest)、檔案掛載路徑(Volumes)、暴露埠(expose,但這個只允許容器內部訪問,不對映到宿主機)、埠對映(ports)、連結其他服務(links)。可以透過docker compose build和docker compose up等命令操作構建和執行,相應過程不再展示,感興趣的小夥伴可以本地實踐。

4.1 docker-machine

Docker Machine是一個用於配置和管理Dockerized主機(帶有Docker Engine的主機)的工具。 您可以使用Machine在一個或多個虛擬系統上安裝Docker Engine。 這些虛擬系統可以是本地的(如使用Machine在Mac或Windows上的VirtualBox中安裝和執行Docker Engine時)或遠端(如使用Machine在雲提供商上配置Dockerized主機時)。 可以想到Dockerized主機本身,有時也稱為託管“機器”。

5 雲原生

這個話題比較大,此處選取了部分解釋,存在很大侷限性。
雲原生從字面意思上來看可以分成雲和原生兩個部分。雲是和本地相對的,傳統的應用必須跑在本地伺服器上,現在流行的應用都跑在雲端,雲包含了IaaS,、PaaS和SaaS。

原生就是土生土長的意思,我們在開始設計應用的時候就考慮到應用將來是執行雲環境裡面的,要充分利用雲資源的優點,比如️雲服務的彈性和分散式優勢。
雲原生 = 微服務 + DevOps + 持續交付 + 容器化

6 Kubernetes(K8S)

Docker主張的是“容器即服務”,面對大型複雜的實際應用場景,將面臨著多容器的管理、排程、叢集擴充套件等問題,人們迫切需要一套容器管理系統,對Docker及容器進行更高階更靈活的管理。
於是,Kubernetes出現了。

6.1 K8S名字的由來

這個其實和矽谷的人起名有關係,他們有一個壞習慣,就是喜歡把一個單詞首字母+跳過的字母數來進行縮寫,目的是讓爺爺奶奶們讀不懂,比如亞馬遜的Algorithms被縮寫成A9,而kubernetes縮寫為k8s,意思就是k後面跳過8個字母后到s,就變成了k8s。

6.2 Kubernetes 特點

  • 可移植: 支援公有云,私有云,混合雲,多重雲(multi-cloud)
  • 可擴充套件: 模組化, 外掛化, 可掛載, 可組合
  • 自動化: 自動部署,自動重啟,自動複製,自動伸縮/擴充套件

Kubernetes(k8s)是自動化容器操作的開源平臺。這些容器操作包括:部署、排程和節點叢集間擴充套件。

具體功能:

  • 自動化容器部署和複製。
  • 實時彈性收縮容器規模。
  • 容器編排成組,並提供容器間的負載均衡。

6.3 K8S架構和元件


pod:pod是k8s最小的排程單位,一個pod裡面可以包含一個或者多個container,一個pod共享一個namespace,它們之前可以透過localhost來進行通訊。

K8s叢集核心元件如下:

  • etcd:一個高可用的K/V鍵值對儲存和服務發現系統。
  • flannel:實現跨主機的容器網路的通訊。
  • kube- apiserver:提供Kubernetes叢集的API呼叫。
  • kube- controller-manager:確保叢集服務。
  • kube- scheduler:排程容器,分配到Node。
  • kubelet:在Node節點上按照配置檔案中定義的容器規格啟動容器。
  • kube-proxy:提供網路代理服務。

6.4 私有云架構

本文如有不妥之處,望批評指正,後續會推出K8S實踐和核心元件解析,持續關注!

7 參考文章:


相關文章