docker OCI runtime

  Open Container Initiative(OCI)目前有2個標準:runtime-spec以及image-spec。前者規定了如何運行解壓過的filesystem bundle。OCI規定了如何下載OCI鏡像並解壓到OCI filesystem bundle,這樣OCI runtime就能夠運行OCI bundle了。OCI(當前)至關於規定了容器的images和runtime的協議,只要實現了OCI的容器就能夠實現其兼容性和可移植性。implements中列出了部分OCI標準的實現。本文不討論windows下的實現,具體參見Open Container Initiative Runtime Specificationhtml

system bundle是個目錄,用於給runtime提供啓動容器必備的配置文件和文件系統。標準的容器bundle包含如下內容:node

config.json:該文件包含了容器運行的配置信息,該文件必須存在bundle的根目錄,且名字必須爲config.json
容器的根目錄,能夠由config.json中的root.path指定

下面使用runc來運行一個容器,runc是根據OCI標準生成的一個cli工具。前面兩個命令用於提取filesystem,最後一個用於生成config.json,二者組織在一塊兒就是一個filesystem bundlelinux

# mkdir rootfs
# docker export $(docker create busybox) | tar -C rootfs -xvf -
# runc spec

  使用runc來運行這個bundle,可使用state查看該容器的狀態git

# runc run busybox
# runc state busybox
{
  "ociVersion": "1.0.0",
  "id": "busybox",
  "pid": 41732,
  "status": "running",
  "bundle": "/home/test",
  "rootfs": "/home/test/rootfs",
  "created": "2018-12-25T14:41:58.82202891Z",
  "owner": ""

 

OCI runtime包含runtimeruntime-linuxconfigconfig-linuxgithub

  • runtime規定了以下內容
    • state
      • ociVersion:建立容器時的OCI版本
      • id:容器惟一的ID
      • status:容器的runtime狀態,能夠爲以下值
        • creating:容器正在被建立(lifecycle的第2步)
        • created:容器完成建立,但沒有返回錯誤且沒有執行用戶程序(lifecycle的第2步以後)
        • running:容器正在執行用戶程序且沒有返回錯誤(lifecycle的第5步以後)
        • stoped:容器進程退出(lifecycle的第7步)
      • pid:host上看到的容器進程
      • bundle:host上容器bundle目錄的絕對路徑
      • annotation:容器相關的標註,可選

因爲runc實現了OCI runtime,使用runc state查看上述busybox能夠獲得state相關的信息docker

{
   "ociVersion": "1.0.0",
    "id": "busybox",
    "pid": 41732,
    "status": "running",
    "bundle": "/home/test",
    "rootfs": "/home/test/rootfs",
    "created": "2018-12-25T14:41:58.82202891Z",
    "owner": ""
}
    • lifecycle 描述了容器從建立到退出的事件觸發點
      1. OCI runtime的create調用與bundle的路徑和id相關
      2. OCI runtime的必須依據config.json中的設置來建立環境,若是沒法建立config.json中指定的環境,則返回錯誤。此階段主要建立config.json中的資源,並無執行用戶程序。該步驟以後任何多config.json的修改都不會影響容器
      3. runtime使用容器的惟一id來執行start容器命令
      4. runtine必須執行 prestart hooks,若是 prestart hooks執行失敗,則返回錯誤,並中止容器,執行第9條操做
      5. runtime必須執行用戶程序
      6. runtime必須執行poststart hooks,若是poststart hooks執行失敗,則必須記錄warning日誌,而poststart hooks和lifecycle繼續運行
      7. 容器進程退出,可能由錯誤退出,人爲退出,程序崩潰或runtime 執行kill命令引發
      8. runtime使用容器的惟一id來執行delete容器操做
      9. 若是在容器建立階段(第2步)沒有完成某些步驟,則容器必須被銷燬
      10. runtime必須執行poststop hooks,若是poststop hooks執行失敗,則必須記錄warning日誌,而poststop hooks和lifecycle繼續運行
    • operation runtime必須支持以下操做
      • query state:state <container-id>,參見上述state描述
      • create:create <container-id> <path-to-bundle>,runtime應該提供檢測id惟一性的功能。該操做中會用到config.json除process以外的配置屬性(由於process實在start階段用到的)。實現中可能會與本規範不一致,如在create操做以前實現了pre-create
      • start:start <container-id>,執行config.json的process中定義的程序,若是process沒有設定,則返回錯誤
      • kill:kill <container-id> <signal>,向一個非running狀態的容器發送的信號會被忽略。此操做用於向容器進程發送信號
      • delete:delete <container-id>,嘗試刪除一個非stopped的容器會返回錯誤。容器刪除後其id可能會被後續的容器使用
# runc delete busybox
cannot delete container busybox that is not stopped: running
  • configuration定義了進程運行,環境變量等配置。現有jsongo版本的配置,其中go中定義了與平臺(linux,solaris,windows相關的tag),以下:
// Linux is platform-specific configuration for Linux based containers.
Linux *Linux `json:"linux,omitempty" platform:"linux"`
// Solaris is platform-specific configuration for Solaris based containers.
Solaris *Solaris `json:"solaris,omitempty" platform:"solaris"`
// Windows is platform-specific configuration for Windows based containers.
Windows *Windows `json:"windows,omitempty" platform:"windows"`
// VM specifies configuration for virtual-machine-based containers.
VM *VM `json:"vm,omitempty" platform:"vm"`
    • Specification version:必選,指定了bundle使用的OCI的版本
    • root:
      • path:容器的bundle路徑,能夠是相對路徑和絕對路徑,該值一般爲rootfs
      • readonly:當設置爲true時,容器的根文件爲只讀,默認false
    • mount:按照配置的順序進行掛載
      • destination:容器中的掛載點,必須是絕對路徑
      • source:掛載的設備名稱,文件或目錄名稱(bind mount時),當option中有bind或rbind時改mount類型爲bind mount
      • option:mount的選項,參見mount
    • process:定義了容器的進程信息
      • terminal:默認false,爲true時,linux系統會爲該進程分配一個pseudoterminal(pts),並使用標準輸入輸出流
      • consoleSize:指定terminal的長寬規格,width和height
      • cwd:執行命令的絕對路徑
      • env:環境變量
      • args:命令參數,至少須要指定一個參數,首參數即被execvp執行的文件

根據平臺不一樣支持以下配置json

POSIX process 支持設置POSIX和Linux平臺windows

    • rlimits:設置進程的資源,如cpu,內存,文件大小等,參見getrlimit。docker裏面使用--ulimit來設置單個進程的資源
      • type:linux和Solaris
      • soft:內核分配給該進程的資源
      • hard;可配置的資源的最大值,即soft的最大值。unprivileged進程(沒有CAP_SYS_RESOURCE capability)能夠將soft設置爲0-hard之間的值

Linux process:數組

    • apparmorProfile:指定進程的apparmor文件
    • capabilities:指定進程的capabilities
    • noNewPrivileges:設置爲true後能夠防止進程獲取額外的權限(如使得suid和文件capabilities失效),該標記位在內核4.10版本以後能夠在/proc/$pid/status中查看NoNewPrivs的設置值。更多參見no_new_privs
    • oomScoreAdj :給進程設置oom_score_adj值,進程的oom涉及如下3個文件,oom_adj和oom_score_adj功能相似,oom_adj主要用於兼容老版本,oomScoreAdj的功能就是設置/proc/$PID/oom_score_adj中的值(範圍-1000~1000),系統經過該值和oom_score來決定kill進程的優先級。oom_score爲只讀文件,oom經過對系統全部進程的oom_score進行排序,值越大,越可能在內存不足時被kill掉。(參見linux oom機制分析oom介紹
/proc/$PID/oom_adj
/proc/$PID/oom_score
/proc/$PID/oom_score_adj

能夠經過以下命令查看系統全部進程的oom_score網絡

ps -eo pid,comm,pmem --sort -rss | awk '{"cat /proc/"$1"/oom_score" | getline oom; print $0"\t"oom}'
    • selinuxLabel :設置進程的SELinux 標籤,即MAC值
    • user 用於控制運行進程的用戶
      • uid:指定容器命名空間的user id
      • gid:指定容器命名空間的group id
      • additionalGids:指定容器命名空間中附加的group id
    • hostname:指定容器進程看到的hostname
    • Platform-specific configuration:包含在linux,Windows,solaris,vm等host平臺上使用namespaces,cgroup等。下面以linux爲例
      • Default Filesystems:以下路徑須要正確掛載到容器中,以便容器進程的正確執行
Path        Type
/proc       proc
/sys        sysfs
/dev/pts    devpts
/dev/shm    tmpfs
      • namespaces,爲包含以下參數的數組
        • type:指定namespace類型,爲ipc,mount,user,network,uts,pid,cgroup,若是沒有指定namespace type,則繼承父namespace的屬性
        • path:namespace的文件,若是沒有指定,則生成一個新的namespace
      • User namespace mappings,uidMappings和gidMappings指定了user和group從host到容器的映射關係,爲結構圖數組,包含containerid,hostid和size這3個屬性
      • device:列出了必須在容器中存在的設備,爲結構體數組,有以下屬性
        • type:設備的類型
        • path:容器中的全路徑
        • major, minor:設備的主設備號和次設備號,主設備號表示類型,次設備號表示分區,可使用"ls -al /dev"查看主次設備號。設置能夠參見device
        • fileMode:文件ADC訪問權限
        • uid:容器中設備的uid
        • gid:容器中設備的gid
      • cgroup:用於控制容器的資源以及設備接入等。
        • Cgroups Path:cgroup的路徑,該路徑能夠是絕對路徑,也能夠是相對路徑。若是沒有設置該值,cgroup會使用默認的cgroup路徑

可使用resources字段來配置cgroup,注意:只有在須要更新cgroup的時候才配置該字段內容

    "cgroupsPath": "/myRuntime/myContainer",
    "resources": {
        "memory": {
        "limit": 100000,
        "reservation": 200000
        },
        "devices": [
            {
                "allow": false,
                "access": "rwm"
            }
        ]
   }

Device whitelist:用於配置設備白名單

  • allow (boolean, REQUIRED) -容許
  • type (string, OPTIONAL) - 設備相似: a (all), c (char), or b (block). 默認爲all
  • major, minor (int64, OPTIONAL) - 設備的主次號. 默認all
  • access (string, OPTIONAL) - 設備的cgroup權限.r (read), w (write), 和m (mknod).

Memory:具體能夠參見cgroup memory

  • limit (int64, OPTIONAL) - 設置內存使用limit
  • reservation (int64, OPTIONAL) - 設置內存的soft limit
  • swap (int64, OPTIONAL) - 設置memory+Swap使用limit
  • kernel (int64, OPTIONAL) -  設置內存的hard limit
  • kernelTCP (int64, OPTIONAL) - 設置內核TCP buffer的hard limit
  • swapness:設置swap的使用比例
  • disableOOMKiller:是否開啓oomkiller

CPU:具體能夠參見cgroup CPU

  • shares (uint64, OPTIONAL) - cgroup中task使用的cpu的相對比例
  • quota (int64, OPTIONAL) - 一個period中使用的cpu時間
  • period (uint64, OPTIONAL) - 以毫秒爲單位的cpu週期 (CFS scheduler only)
  • realtimeRuntime (int64, OPTIONAL) - 以毫秒爲單位的 cgroup tasks連續使用cpu資源的最長週期
  • realtimePeriod (uint64, OPTIONAL) - 實時調度的 period
  • cpus (string, OPTIONAL) - CPU列表
  • mems (string, OPTIONAL) - memory nodes列表

Block IO:

Huge page limits:

  • pageSize :大頁大小
  • limit:bytes爲單位限制的大頁的使用上限

Network:

  • classID:cgroup網絡報文的標籤
  • priorities

name:網卡名稱
priority:網卡優先級

PIDs:

limit:cgroup限制的pid的數目

RDMA

Sysctl:容許在容器運行過程當中修改內核參數

Seccomp:在linux內核中爲應用提供了一種沙盒機制。更多參見seccomp

seccomp

defaultAction:seccomp的默認動做,容許值類型爲syscalls[].action

architectures:系統調用的平臺,以下

SCMP_ARCH_X86
SCMP_ARCH_X86_64
SCMP_ARCH_X32
SCMP_ARCH_ARM
SCMP_ARCH_AARCH64
SCMP_ARCH_MIPS
SCMP_ARCH_MIPS64
SCMP_ARCH_MIPS64N32
SCMP_ARCH_MIPSEL
SCMP_ARCH_MIPSEL64
SCMP_ARCH_MIPSEL64N32
SCMP_ARCH_PPC
SCMP_ARCH_PPC64
SCMP_ARCH_PPC64LE
SCMP_ARCH_S390
SCMP_ARCH_S390X
SCMP_ARCH_PARISC
SCMP_ARCH_PARISC6

syscalls:匹配seccomp的系統調用,該屬性可選

name:系統調用的名稱,至少有一個

action:seccomp的動做規則。libseccomp v2.3.2中以下:

SCMP_ACT_KILL
SCMP_ACT_TRAP
SCMP_ACT_ERRNO
SCMP_ACT_TRACE
SCMP_ACT_ALLOW

args:

index (uint, REQUIRED) - 系統調用的index
value (uint64, REQUIRED) - 系統調用參數的值
valueTwo (uint64, OPTIONAL) - 系統調用參數的值
op (string, REQUIRED) - 系統調用參數的動做。 libseccomp v2.3.2以下

SCMP_CMP_NE
SCMP_CMP_LT
SCMP_CMP_LE
SCMP_CMP_EQ
SCMP_CMP_GE
SCMP_CMP_GT
SCMP_CMP_MASKED_EQ

Rootfs Mount Propagation

rootfsPropagation:設置rootfs的mount Propagation類型,slave,private或shared

      • Linux Runtime:該規範規定了容器文件描述符相關的內容。默認下runtime只會打開stdin, stdout和stderr這3個文件描述符

Masked Paths

maskedPaths:容器沒法讀取該設置的路徑

    "maskedPaths": [
        "/proc/kcore" ]

Readonly Paths

readonlyPaths:容器只讀該設置的路徑

    • POSIX-platform Hooks:支持使用hooks來設置lifecycle中用戶自定義動做
      • hooks
        • prestart:在用戶程序運行前以及容器命名空間建立後執行,包含以下屬性的數組:
          • path:相似execv的路徑,爲均對路徑
          • args:相似execv的參數
          • env:環境變量
          • timeout:終端hooks的超時時間
        • poststart:在用戶程序執行以後且在start步驟返回前執行,同 prestart的數組同樣
        • poststop:在容器刪除以後且在delete步驟返回前執行,同prestart的數組同樣
    • Annotations:爲key-value類型的任意字符串,若是沒有annotation,該字段能夠爲空,也能夠不存在
    • extensibility:遇到沒法識別的字段須要返回錯誤

 TIPS:

  • openshift 3.11版本的runc採用的是其本身實現的runtime,位於/usr/libexec/docker/docker-runc-current,實際與runc相似。

 

參考:

https://cizixs.com/2017/11/05/oci-and-runc/

https://github.com/opencontainers/runtime-spec/blob/master/config.md

https://github.com/opencontainers/runtime-spec/blob/master/specs-go/config.go

Rootfs Mount Propagation

相關文章
相關標籤/搜索