天天看點

容器底層技術系列檔案目錄前言一、Namespace二、Cgroups三、容器種類總結

系列檔案目錄

第一章:容器技術發展程序

第二章:容器底層技術

目錄

  • 系列檔案目錄
  • 前言
  • 一、Namespace
  • 先從Linux提供的“命名空間API說起”
  • clone()
  • unshare()
  • setns()
  • mount命名空間
  • UTS命名空間
  • Network命名空間
  • User命名空間
  • IPC命名空間
  • PID命名空間
  • 二、Cgroups
  • 1. Cgroups功能介紹:
  • 2. Cgroups子系統介紹
  • 三、容器種類
  • 總結

前言

容器底層技術依賴核心的Cgroups和Namespace

一、Namespace

先從Linux提供的“命名空間API說起”

  • clone()

通過flags參數來控制建立新程序的特性,使得"新建立的程序"擁有獨立的Namespace

本質上clone()是一個通用的fork()版本,fork()的功能由flags參數控制。/proc/PID/ns目錄下為每個命名空間對應一個檔案,這些描述符連結可以用來判斷兩個命名空間是否在同一個命名空間。如果兩個程序在同一個命名空間,核心會保證/proc/PIC/ns導出的inode号是一樣的。

#define _GNU_SOURCE
#include <sched.h>
int clone(int (*fn)(void *), void *stack, int flags, void *arg);

/*
**int (*fn)(void *)    --子程序要執行的函數
**void *stack    --子程序棧
**int flags    --CLONE_NEW* flags的組合
**void *arg    --傳給子程序參數
*/
           
  • unshare()

将"目前程序"和所在的Namespace分離,并加入到一個新的Namespace中

#define _GNU_SOURCE
#include <sched.h>

int unshare(int flags);

/*
**int flags    --需要脫離的命名空間并建立新的命名空間CLONE_NEW*
*/
           
  • setns()

将“目前程序”關聯一個存在的命名空間

setns()将調用的程序和一個特定的命名空間解除關系并将該程序和一個同類型的命名空間關聯。使用setns()和execve()能建構一個簡單但有用的工具,一個和特定命名空間關聯的程式并且在命名空間中可以執行一個指令。

#define _GNU_SOURCE
#include <sched.h>

int setns(int fd, int nstype);

/*
**int fd    --fd引用/proc/[pid]/ns/ link連接配接,或者是一個PID file descriptor
**int nstype    --用來檢查fd關聯的Namespace是否與nstype表明的Namespace一緻,如果填0将不檢查
*/
           

mount命名空間

  1. 用于隔離一組程序看到的檔案系統挂載點集合(處于不同mount命名空間的程序看到的檔案系統不一樣,賦予容器不同的檔案系統)
  2. CLONE_NEWNS
  3. mount() / unmount()系統調用

UTS命名空間

  1. 隔離了兩個系統變量,節點名+域名(UTS賦予了每個容器各自的主機名+域名)
  2. CLONE_NEWUTS
  3. uname()系統調用傳回UTS
  4. setnodename()系統調用,設定節點名
  5. setdomainname()系統調用,設定域名

Network命名空間

  1. 隔離和網絡有關的資源,使得每個網絡命名空間有其自己的網絡裝置、IP位址、IP路由表、/proc/net目錄、端口号等。讓每個container擁有自己的網絡裝置(虛拟的)和網絡端口号。
  2. CLONE_NEWNET

User命名空間

  1. 隔離使用者ID群組ID,一個使用者ID在命名空間之外非特權,而在命名空間之内具有特權,讓不同User命名空間的container擁有不同的特權。
  2. CLONE_NEWUSER

IPC命名空間

  1. 隔離程序間通信資源
  2. CLONE_NEWIPC
  3. System V IPC表示符和POSIX消息隊列

PID命名空間

  1. 隔離程序ID号,不同命名空間的程序ID可以相同,保證了每個container能有自己的1号init程序。
  2. CLONE_NEWPID
  3. 一個程序有2個PID,一個ID屬于PID命名空間,一個ID屬于主機系統

二、Cgroups

Cgroups是控制組群的簡寫(Control groups),是Linux核心的一個功能,用來限制、控制與分離一個程序組的資源(如cpu、記憶體、磁盤、IO輸入輸出等)。Cgroups是LXC(Linux Container)實作容器虛拟化的基礎。

這個項目最早由Google的工程師在2006年發起,最早的名稱為“程序容器(process containers)”。但在Linux核心中,容器(container)這個詞有許多不同的意義,為了避免混亂,被重命名為cgroups,并合入到Linux kernel 2.6.24版本中。

1. Cgroups功能介紹:

Cgroups功能 描述
資源限制 對資源可以設定一個不超過的上線值。例如:控制組可以被設定不超過設定值的記憶體限制,也包括虛拟記憶體。
優先級 設定資源的占有比例,讓占有比例多的獲得更多的資源,間接達到優先級的效果。例如:一些組可能會得到大量的CPU或者磁盤IO吞吐量。
結算 用來度量系統實際用了多少資源
控制 當機組或檢查點和重新開機動

2. Cgroups子系統介紹

Cgroups子系統 描述
cpu 使用排程程式提供對CPU的cgroup任務通路
cpuset 為cgroup中的任務配置設定獨立CPU(在多核系統)和記憶體節點
cpuacct 自動生成cgroup中任務所使用的CPU報告
memory 設定cgroup中任務使用記憶體的限制,并自動生成由那些任務使用的記憶體資源報告
blkio 為塊裝置設定輸入/輸出限制,比如實體裝置(磁盤、固态硬碟、USB等)
devices 可允許或者拒絕cgroup中的任務通路裝置
freezer 挂起或者恢複cgroup中的任務

三、容器種類

容器類型 技術路線 注釋
lxc(linux container)

LXC容器常常被考慮為介于chroot和virtual machine之間的一個事物。LXC的目标是建立一個和标準安裝的linux系統盡可能一樣的環境,但不需要單獨的kernel。

LXC可以為容器綁定特定的cpu和memory,配置設定特定比例的cpu時間,IO時間,限制可以使用的記憶體大小,提供device通路控制,提供獨立的namespace(network、pid、ipc、mnt、uts)

LXC用了一下kernel feature:

  1. kernel namespace(ipc,uts,mount,pid,network,user)
  2. Apparmor and SELinux profiles
  3. Seecomp policies
  4. Chroot(using pivot_root)
  5. Kernel capabilities
  6. CGroups(control groups)

lxc-checkconfig  用于判斷linux核心是否支援LXC

lxc-create  用于建立一個容器

lxc-execute  用于在一個容器執行應用程式

lxc-cgroup  用于擷取或調整與cgroup相關的參數

systemd-nspawn
  1. systemd-nspawn可以在輕量級的命名空間容器中運作command或OS,和chroot相似,但更強大,它完全虛拟化了檔案系統層次結構,以及程序樹、各種IPC子系統、主機名和域名。
  2. systemd-nspawn将容器中各種核心接口的通路限制為隻讀(例如:/sys,/proc/sys,/sys/fs/selinux)。host的網絡接口和系統時鐘不能再容器内修改,不能建立裝置節點。
  3. systemd-nspawn可以以命名啟動容器,也可以作為systemd的service啟動。
  4. 根據systemd-nspawn的man page介紹,其預期用途是用于調試、測試以及建構與引導和系統管理有關的軟體包、發行版和軟體。

以systemd服務啟動systemd-nspawn容器:

[Service]

ExecStart=/usr/bin/systemd-nspawn --quiet --keep-unit --boot --link-journal=try-guest --network-veth --machine =%I

cells linux kernel的namespace和cgroups機制

哥倫比亞大學論文:http://systems.cs.columbia.edu/projects/cells/

浙大github項目:http://condroid.github.io/

以色列公司網址:https://www.cellrox.com/

containerd

Containerd是一個行業标準的容器運作時container runtime,強調簡單性、健壯性和可移植性。它可以作為Linux和Windows的守護程序,也可以管理其主機系統的容器完整的生命周期:image鏡像的傳輸和存儲、容器執行和監督、低級存儲和網絡附件等。

Containerd被設計為嵌入到更大的系統中,而不是被開發人員或最終使用者直接使用。

containerd是CNCF成員,是已經畢業狀态,很穩定

github項目:https://github.com/containerd/containerd

CRI-O

基于oci的Kubernetes容器運作時接口的實作。

crio的目的是在符合OCI的運作時和kubelet之間提供內建路徑。具體來說,它使用符合OCI的運作時實作了Kubelet容器運作時接口(CRI)。CRI- o的範圍與CRI的範圍綁定在一起。

  1. 支援多種image鏡像格式,包括已經存在的docker image鏡像格式。
  2. 支援多種下載下傳image鏡像的方式,包括信任和鏡像校驗。
  3. 容器鏡像管理(管理image layer鏡像層,overlay檔案系統等)。
  4. 容器生命周期管理。
  5. 滿足CRI要求的監控和日志記錄。
  6. CRI要求的資源隔離。
  7. 這是一個Kubernetes容器運作時接口(CRI)的實作,它将允許Kubernetes直接啟動和管理Open Container Initiative (OCI)容器。
不支援:編譯、簽名、push鏡像image到各種image存儲倉庫;
github項目:https://github.com/cri-o/cri-o

總結

  1. mount命名空間、UTS命名空間、Network命名空間、User命名空間,這4個命名空間可以了解為建構container環境Env的。
  2. IPC命名空間、PID命名空間,這2個命名空間可以了解為container運作時相關的。