虛擬機器(virtual machine),可建立一個環境模擬完整硬體的功能,可在上面安裝與宿主機器不同的作業系統,進而形成一個隔離環境進行測試。常見的免費軟體有VMware Workstation Player、VirtualBox。
容器化本質上是一種沙盒技術,透過將作業系統的應用程式進行隔離,讓該應用程式誤以為擁有作業系統所有資源,但不同容器間卻是彼此隔離的。實踐容器化技術大多以Docker為主,除此之外還有LXD、Podman等等。
相關架構圖參考如下,
來源: Difference between VM vs Docker
在解說原理前先來觀察一下容器的內部情況。
步驟如下 :
步驟如下 :
是不是稍微可以感受到資源隔離的感覺,從宿主端、容器端會觀察到不同的結果,彷彿容器與宿主機是兩個不同的機器裡面。但實際上容器技術只是將目標 process 隔離出來,讓其彷彿處於一個獨立的執行環境中。與虛擬機的差別在於虛擬機需要多模擬一層 Guest OS,所以虛擬機的效能較差,但虛擬機的隔離性比較好。容器的效能比較好,但是隔離性較差。
接下來感受一下所謂容器隔離性差的這件事情,這邊可以從 process 跟 file system 的角度切入看看。
# 容器內睡個 87878787 秒
sleep 87878787 ;
#在宿主機上觀察一下,會發現這個 8787 是用 root 權限在睡的
ps aux | grep 87878 ;
# 容器內在 /tmp 底下建立個 87878787 檔案
echo "I am 87" > /tmp/87878787 ;
#在宿主機上觀察一下,會發現這個檔案躺在 /var/lib/docker/overlay2 的某個資料夾內
sudo find /var/lib/docker/overlay2 -name "87878787" ;
上述的方式如果把用虛擬機去取代容器的話,無法得到相同的結果,甚至從宿主機的指令也無法看到虛擬機內部的狀態。這也就是為什麼大家都說虛擬機的隔離性比容器來的好。
那接下來就要開始簡單介紹 Linux 使用的隔離技術為何。資源隔離的概念會包含兩個面向,一個是隔離了哪些資源,另一個則是如何限制資源的使用量。而在 Linux 中則是透過 namespcae 以及 cgroup 來達到上述講的兩個目的。此篇就從 namespace 觀念說起,並且簡單透過 unshare 指令來作觀念驗證。
namespace 是一種 Linux 的隔離機制,目前有個隔離類型包含 Cgroup、IPC、Network、Mount、PID、Time、User以及 UTS。
其中 PID 的掛載以及隔離部分可以參考 Day 13: Mount Namespace 的坑,這篇系列探討相當的完整。
至於本次會透過 unshare 指令模擬出一個類似容器環境的方式,相關資料都是參考 使用Linux Namespace把进程一步一步隔离起来。
pid namespace 步驟如下 :
cp `which unshare` ./ ;
#並非使用 root 執行,因此需要針對該程式增加權限
sudo setcap 'cap_sys_admin+ep' ./unshare ;
# --pid 代表要建立一個獨立的 pid namespace,mount-proc 則是將這個獨立的process 資料掛載到 /proc 底下
# 如此一來 ps aux 才會看到真正的結果
./unshare --pid --mount-proc --fork bash ;
ps aux ;
exit ;
docker run -it --name my-nginx nginx bash ;
apt update && apt-get install procps net-tools -y ;
exit ;
docker export my-nginx --output=nginx.tar ;
mkdir nginx ;
tar -xvf nginx.tar -C nginx/;
sudo setcap 'cap_sys_admin+ep cap_sys_chroot+ep' ./unshare ;
./unshare --mount --root nginx --pid --mount-proc --fork bash ;
# 可以觀察 bash 的狀態
ps aux ;
透過在容器以及宿主機執行 ls /proc/$$/ns -al 可以觀察到當前執行 process 的各項 namespace,可以發現上述環境的 mount、pid、pid_fork 的 namespace 是有差異的。
做到這邊差不多就利用 unshare 隔離出 pid、mount namespace 的執行狀態出來,算是針對容器的隔離概念有點小小的了解,下一次則是要開始學習如何逃逸出容器的隔離環境,進而得到操控宿主機的能力。
今日總結 :