深入理解 nvidia-docker 2.0

HULK一線技術雜談發表於2019-01-04

女主宣言上篇推送我們介紹了 nvidia-docker 2.0 在我司大規模 Kubernetes 叢集上的實踐,本篇文章就將介紹相較於舊版本,nvidia-docker 2.0 的設計優勢及其實現機制,希望能對大家有所幫助。本文首發於 OpsDev.cn,轉載已獲取作者授權。

深入理解 nvidia-docker 2.0

The 50th Anniversary of Apollo 8's Launch

by NASA IOTD

NVIDIA於2016年開始設計NVIDIA-Docker已便於容器使用NVIDIA GPUs。 第一代nvidia-docker1.0實現了對docker client的封裝,並在容器啟動時,將必要的GPU device和libraries掛載到容器中。

1   nvidia-docker 存在的問題

但是這種設計的方式高度的與docker執行時耦合,缺乏靈活性。存在的缺陷具體如下:

  • 設計高度與docker耦合,不支援其它的容器執行時。如: LXC, CRI-O及未來可能會增加的容器執行時。

  • 不能更好的利用docker生態的其它工具。如: docker compose。

  • 不能將GPU作為排程系統的一種資源來進行靈活的排程。

  • 完善容器執行時對GPU的支援。如: 自動的獲取使用者層面的NVIDIA Driver libraries, NVIDIA kernel modules, device ordering等。

基於上面描述的這些弊端,NVIDIA開始了對下一代容器執行時的設計: nvidia-docker2.0。

2  nvidia-docker 2.0 的實現機制

基礎知識

先簡單介紹下nvidia-docker 2.0, nvidia-container-runtime,libnvidia-container以及runc直接的關係。

  • nvidia-docker2.0

    () 是一個簡單的包,它主要透過修改docker的配置檔案/etc/docker/daemon.json來讓docker使用NVIDIA Container runtime。

  • nvidia-container-runtime 

    () 才是真正的核心部分,它在原有的docker容器執行時runc的基礎上增加一個 prestart hook 

    (), 用於呼叫libnvidia-container庫。

  • libnvidia-container 

    () 提供一個庫和一個簡單的CLI程式,使用這個庫可以使NVIDIA GPU使用Linux容器。

  • runc 

    () 一個命令列工具,會根據標準格式的Open Containers Initiative 

    (https://developer.nvidia.com/nvidia-container-runtime) 建立容器。也是docker預設的容器執行時。

實現機制

它們之間的關係可以透過下面這張圖關聯起來:

深入理解 nvidia-docker 2.0

上面已經介紹了各個元件的作用以及它們之間的關係,接下來詳細的描述下這張圖:


正常建立一個容器的流程

docker --> dockerd --> docker-containerd-shm -->runc --> container-process

docker客戶端將建立容器的請求傳送給dockerd, 當dockerd收到請求任務之後將請求傳送給docker-containerd-shm 

(其實就是containerd)。

前面沒有介紹到containerd。這裡簡單的介紹下,containerd,它主要負責的工作是:

  • 管理容器的生命週期(從容器的建立到銷燬)

  • 拉取/推送容器映象

  • 儲存管理(管理映象及容器資料的儲存)

  • 呼叫runc 執行容器

  • 管理容器的網路介面及網路

containerd的定位是:

containerd 被設計成嵌入到一個大系統中,而不是給開發人員和終端的裝置使用。

關於containerd的詳細說明,請檢視 containerd ()。

當containerd接收到請求之後,做好相關的準備工作,會去呼叫runc,而runc基於OCI檔案對容器進行建立。這是容器建立的整體流程。

建立一個使用GPU容器的流程

docker--> dockerd --> docker-containerd-shim-->nvidia-container-runtime -- > container-process

基本流程和普通不使用GPU的容器差不多,只是把docker預設的執行時替換成了NVIDIA自家的nvidia-container-runtime。 這樣當nvidia-container-runtime建立容器時,先執行nvidia-container-runtime-hook這個hook去檢查容器是否需要使用GPU(透過環境變數NVIDIA_VISIBLE_DEVICES來判斷)。如果需要則呼叫libnvidia-container來暴露GPU給容器使用。否則則走預設的runc邏輯。

3  總結

說到這裡nvidia-docker2.0的大體機制基本就通了。但是涉及到的nvidia-container-runtime, libnvidia-container, containerd,runc這些專案, 這本篇文章裡面就不一一介紹了。如果感興趣可以自行去探索學習。這些地址在文章中都已經做過相關的連結。

4  參考

  1. https://developer.nvidia.com/nvidia-container-runtime https://devblogs.nvidia.com/gpu-containers-runtime/

  2.  

  3. /issues/815

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31555491/viewspace-2305576/,如需轉載,請註明出處,否則將追究法律責任。