嵌入式Linux容器技術
一、Linux容器技術
-
Linux Container容器是一種內核虛擬化技術,可以提供輕量級的虛擬化,以便隔離進程和資源。
-
LXC爲Linux Container的簡寫。可以提供輕量級的虛擬化,以便隔離進程和資源,而且不需要提供指令解釋機制以及全虛擬化的其他複雜性。相當於C++中的NameSpace。容器有效地將由單個操作系統管理的資源劃分到孤立的組中,以更好地在孤立的組之間平衡有衝突的資源使用需求。與傳統虛擬化技術相比,它的優勢在於:
(1)與宿主機使用同一個內核,性能損耗小;
(2)不需要指令級模擬;
(3)不需要即時(Just-in-time)編譯;
(4)容器可以在CPU核心的本地運行指令,不需要任何專門的解釋機制;
(5)避免了準虛擬化和系統調用替換中的複雜性;
(6)輕量級隔離,在隔離的同時還提供共享機制,以實現容器與宿主機的資源共享。
總結:Linux Container是一種輕量級的虛擬化的手段。
-
Linux Container提供了在單一可控主機節點上支持多個相互隔離的server container同時執行的機制。Linux Container有點像chroot,提供了一個擁有自己進程和網絡空間的虛擬環境,但又有別於虛擬機,因爲lxc是一種操作系統層次上的資源的虛擬化。
-
LXC與docker的關係
(1)Docker並不是LXC的替代品,Docker的底層就是使用了LXC來實現的。LXC將Linux進程沙盒化,使得進程之間相互隔離,並且能夠控制各
進程的資源分配。
(2)在LXC的基礎之上,Docker提供了一系列更強的功能。
二、嵌入式Linux容器
Linux主流的容器包括LXC和Docker,其中LXC是Linux原生的輕量化的容器技術。Docker基於LXC實現,但是,Docker的主要應用場景是雲服務
器,其功能十分的強大,但是,其對於嵌入式Linux開發平臺的支持可能不那麼友好。balenaOS號稱對Docker進行了精簡,使其可以可靠的運行
於嵌入式Linux環境中。它基於Yocto框架開發,systemd作爲init系統。相比較而言,LXC更爲輕量化,對於系統資源的要求更低,所以,其天然
的適於嵌入式Linux環境。不過,(balenaOS)docker和LXC各有千秋,需要深度體驗之後,才能得出最後的結論。
三、體驗容器
3.1 LXC
3.1.1硬件環境
- allwinner T3
- Cortex-A7 四核
- 1G RAM
- Ubuntu Core 18.04(Linux kernel 3.10.108)
3.1.2 LXC安裝
系統要求:
-
硬性要求:
- glibc、libc、uclib中的一種C庫
- Linux kernel >= 2.6.32
-
lxc-attach額外要求:
- Linux kernel >= 3.8
-
非特權容器額外要求:
- libpam-cgfs,cgmanager或其他CGroup管理器爲非特權CGroups操作配置系統
- 最新版本的shadow,包括newuidmap和newgidmap
- Linux kernel >= 3.12
-
推薦庫:
- libcap (to allow for capability drops)
- libapparmor (to set a different apparmor profile for the container)
- libselinux (to set a different selinux context for the container)
- libseccomp (to set a seccomp policy for the container)
- libgnutls (for various checksumming)
- liblua (for the LUA binding)
- python3-dev (for the python3 binding)
Ubuntu環境下,LXC的安裝十分的簡單,只需一個命令就可以完成LXC的安裝,包括其依賴的所有庫文件:
$sudo apt-get install lxc
3.1.3 創建非特權容器
無特權容器是最安全的容器。那些使用uid和gid的映射來爲容器分配一系列uid和gids。這意味着容器中的uid 0(root)實際上就像容器外的uid 100000。因此,如果出現問題並且攻擊者設法逃離容器,他們將發現自己擁有與無人用戶一樣多的權利。
不幸的是,這也意味着不允許以下常見操作:
- 安裝大多數文件系統
- 創建設備節點
- 針對映射集之外的uid / gid的任何操作
注:,因爲本次測試的Ubuntu Core環境的內核版本爲3.10.108,所以,系統不支非特權容器。
3.1.4 創建特權容器
**注:**下面創建的容器爲特權容器,即,容器通過root創建和啓動。
lxc安裝完成之後,可以使用lxc-checkconfig檢測Linux內核是否支持容器。
$ lxc-checkconfig
--- Namespaces ---
Namespaces: enabled
Utsname namespace: enabled
Ipc namespace: enabled
Pid namespace: enabled
**User namespace: missing**
Network namespace: enabled
Multiple /dev/pts instances: enabled
--- Control groups ---
Cgroups: enabled
Cgroup v1 mount points:
/sys/fs/cgroup/systemd
/sys/fs/cgroup/blkio
/sys/fs/cgroup/cpuset
/sys/fs/cgroup/devices
/sys/fs/cgroup/perf_event
/sys/fs/cgroup/cpu,cpuacct
/sys/fs/cgroup/memory
/sys/fs/cgroup/freezer
Cgroup v2 mount points:
Cgroup v1 clone_children flag: enabled
Cgroup device: enabled
Cgroup sched: enabled
Cgroup cpu account: enabled
Cgroup memory controller: enabled
Cgroup cpuset: enabled
--- Misc ---
Veth pair device: enabled, loaded
Macvlan: enabled, not loaded
Vlan: enabled, not loaded
Bridges: enabled, loaded
Advanced netfilter: enabled, not loaded
CONFIG_NF_NAT_IPV4: enabled, loaded
CONFIG_NF_NAT_IPV6: enabled, not loaded
CONFIG_IP_NF_TARGET_MASQUERADE: enabled, not loaded
CONFIG_IP6_NF_TARGET_MASQUERADE: enabled, not loaded
CONFIG_NETFILTER_XT_TARGET_CHECKSUM: enabled, loaded
CONFIG_NETFILTER_XT_MATCH_COMMENT: enabled, not loaded
FUSE (for use with lxcfs): enabled, not loaded
--- Checkpoint/Restore ---
checkpoint restore: enabled
CONFIG_FHANDLE: enabled
CONFIG_EVENTFD: enabled
CONFIG_EPOLL: enabled
CONFIG_UNIX_DIAG: enabled
CONFIG_INET_DIAG: enabled
CONFIG_PACKET_DIAG: enabled
CONFIG_NETLINK_DIAG: enabled
File capabilities:
Note : Before booting a new kernel, you can check its configuration
usage : CONFIG=/path/to/config /usr/bin/lxc-checkconfig
該命令會根據內核的.config文件,檢測內核對於容器的支持情況。
lxc-create用於創建一個容器,lxc在創建一個容器時,提供了很多模板,這些模板的位置:/usr/share/lxc/templates/目錄下。
sudo lxc-busybox lxc-download lxc-local lxc-oci
下面,通過lxc-download,創一個distribution爲Ubuntu,release爲bionic,並且arch爲armhf的容器:
sudo lxc-create -n c1 -t download
上面的命令用於創建一個名爲c1的容器,鍵入該命令後,其會提示輸入系統、系統的版本、架構等參數,之後,lxc會下載對應的容器的rootfs。rootfs下載的時間可能比較長,其下載成功之後,說明容器已經下載成功了。rootfs的目錄位於:/var/lib/lxc/c1目錄,其包括一個config配置文件和rootfs系統。
通過lxc-ls可以看到系統中已經部署了c1容器,lxc-info可以查看c1當前的運行狀態。
lxc-start用於啓動一個容器,具體參數可以通過lxc-start -h查看。
sudo lxc-start -n c1 -o logfile -d
問題
1.apparmor配置問題
1 lxc-start c1 20190812055509.777 ERROR apparmor - lsm/apparmor.c:apparmor_process_label_set:223 - If you really want to start this container, set
2 lxc-start c1 20190812055509.812 ERROR apparmor - lsm/apparmor.c:apparmor_process_label_set:224 -lxc.apparmor.allow_incomplete = 1
3 lxc-start c1 20190812055509.822 ERROR apparmor - lsm/apparmor.c:apparmor_process_label_set:225 - in your container configuration file
4 lxc-start c1 20190812055509.842 ERROR sync - sync.c:__sync_wait:62 - An error occurred in another process (expected sequence number 5)
5 lxc-start c1 20190812055509.908 ERROR lxccontainer - lxccontainer.c:wait_on_daemonized_start:842 - Received container state "ABORTING" instead of "RUNNING"
6 lxc-start c1 20190812055509.953 ERROR lxc_start - tools/lxc_start.c:main:330 - The container failed to start
7 lxc-start c1 20190812055509.970 ERROR lxc_start - tools/lxc_start.c:main:333 - To get more details, run the container in foreground mode
8 lxc-start c1 20190812055509.984 ERROR lxc_start - tools/lxc_start.c:main:336 - Additional information can be obtained by setting the --logfile and --logpriority options
9 lxc-start c1 20190812055509.577 ERROR start - start.c:__lxc_start:1939 - Failed to spawn container "c1"
通過分析日誌,可知需要在容器的配置文件裏,添加一條"lxc.apparmor.allow_incomplete = 1"。c1容器的配置文件爲/var/lib/lxc/c1/config,將這一條配置添加到config末尾。
完成如上步驟之後,再次啓動容器c1,仍然沒有啓動成功,錯誤日誌爲:
1 lxc-start c1 20190812034836.659 ERROR lsm - lsm/lsm.c:lsm_process_label_set_at:174 - No such file or directory - Failed to set AppArmor label "lxc-container-default"
2 lxc-start c1 20190812034836.659 ERROR apparmor - lsm/apparmor.c:apparmor_process_label_set:245 - Failed to change apparmor profile to lxc-container-default
3 lxc-start c1 20190812034836.660 ERROR sync - sync.c:__sync_wait:62 - An error occurred in another process (expected sequence number 5)
4 lxc-start c1 20190812034836.660 ERROR lxccontainer - lxccontainer.c:wait_on_daemonized_start:842 - Received container state "ABORTING" instead of "RUNNING"
5 lxc-start c1 20190812034836.661 ERROR lxc_start - tools/lxc_start.c:main:330 - The container failed to start
6 lxc-start c1 20190812034836.662 ERROR lxc_start - tools/lxc_start.c:main:333 - To get more details, run the container in foreground mode
7 lxc-start c1 20190812034836.662 ERROR lxc_start - tools/lxc_start.c:main:336 - Additional information can be obtained by setting the --logfile and --logpriority options
8 lxc-start c1 20190812034836.719 ERROR start - start.c:__lxc_start:1939 - Failed to spawn container "c1"
分析日誌,AppArmor找不到 "lxc-container-default"配置文件。AppArmor是Linux內核提供的下類似於SeLinux的安全模塊,Ubuntu默認
支持該功能。但是,Ubuntu Core默認並不支持apparmor_status和apparmor_parser工具,而且系統中自帶的profile配置文件很少,可以
通過可以通過sudo apt-get install apparmor-profiles進行安裝,上面的apparmor_status、apparmor_parser工具也會一併安裝。
apparmor profile安裝完成之後,需要重啓apparmor,啓動方法如下:
Start : sudo /etc/init.d/apparmor start
Stop : sudo /etc/init.d/apparmor stop
reload: sudo /etc/init.d/apparmor reload
Show status: sudo /etc/init.d/apparmor status
通過sudo lxc-info -n c1可以查看,容器的運行狀態:
sudo lxc-info -n c1
Name: c1
State: RUNNING
PID: 2993
IP: 10.0.3.81
CPU use: 1.87 seconds
BlkIO use: 18.83 MiB
Memory use: 22.02 MiB
KMem use: 0 bytes
Link: vethLWC02H
TX bytes: 1.04 KiB
RX bytes: 1.12 KiB
Total bytes: 2.16 KiB
可以看到當前c1容器當前的系統資源使用率。
通過lxc-attach命令,可以得到一個與容器進行交互的shell,例如
sudo lxc-attach -n c1
attach成功之後,會進入到一個shell終端,
#root@c1:
可以通過lxc-attach執行容器中任何命令,例如:
sudo lxc-attach -n c1 ls
sudo lxc-attach -n c1 top
可以將APP打包成deb,然後將deb拷貝到容器rootfs的適當的位置,最後,通過lxc-attach命令執行進行deb的安裝。
sudo lxc-attach -n c1 -- dpkg -i /home/ubuntu/app.deb //安裝app.deb
sudo lxc-attach -n c1 -- dpkg -r /home/ubuntu/app.deb //卸載app.deb
該終端提供了Ubuntu幾乎所有的功能,例如,apt,但是,該Ubuntu卻是以容器的方式運行與Ubuntu Core物理主機下的。
最後,lxc-stop可以關閉容器,lxc-destroy刪除容器相關的一切配置文件,包括rootfs。
3.2 LXD
未完待續 。。。 。。。
3.3 BalenaOS
未完待續 。。。。。。