Ref.

コンテナ技術入門 - 仮想化との違いを知り、要素技術を触って学ぼう

用語

  • proc:process

コンテナと仮想化

仮想マシンは仮想的なハードウェアレベルで隔離され、仮想マシンで実行されるアプリケーションはホストOSや他の仮想マシンから確認できません。

–https://eh-career.com/engineerhub/entry/2019/02/05/103000#%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E3%81%A8%E3%81%AF

コンテナはホストOSのプロセスのひとつとして動作するので、ホストOSのプロセスリストからコンテナプロセスを確認可能です。また、ホストOSのリソースを共有することから、リソースの隔離・制限が不十分なコンテナがデプロイされた場合、ホストOSや他のコンテナに影響を与える可能性があります。

– https://eh-career.com/engineerhub/entry/2019/02/05/103000#%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E3%81%A8%E3%81%AF

「コンテナはホストOSのプロセスのひとつとして動作する」
ref. https://eh-career.com/engineerhub/entry/2019/02/05/103000#%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E3%81%A8%E3%81%AF

Ubuntu必要パッケージインストール

$ apt install -y cgdb
$ apt install -y cgroup-tools

プロセスのコンテナ化

  • mktemp:適当な名前のファイル(dオプションはディレクトリ)を/tmpディレクトリに作成します
  • docker container export
    • コンテナのファイルシステムを tar アーカイブとして 出力export します。

      – https://docs.docker.jp/engine/reference/commandline/container_export.html

  • docker container save
    • saveと exportは、それぞれイメージとコンテナを圧縮ファイル(.tar)にまとめます。

      – https://uxmilk.jp/55512

# docker container export の場合は標準出力にエクスポート
# tarファイルにエクスポートする場合は以下のように入力
# docker container export  > container.tar
$ sudo docker container export $CID | tar -x -C $ROOTFS
  • $CIDコンテナをtarアーカイブを標準出力
  • tarCオプションは、ワーキングディレクトリを変更
  • ↑では$ROOTFSに変更
  • xオプションはアーカイブからファイルを抽出

cgcreate

$ cgexec -g cpu,memory:$UUID \
  unshare -muinpfr /bin/sh -c \
  "
    mount -t proc proc $ROOTFS/proc &&
    touch $ROOTFS$(tty); mount --bind $(tty) $ROOTFS$(tty) &&
    touch $ROOTFS/dev/pts/ptmx; mount --bind /dev/pts/ptmx $ROOTFS/dev/pts/ptmx &&
    ln -sf /dev/pts/ptmx $ROOTFS/dev/ptmx &&
    touch $ROOTFS/dev/null && mount --bind /dev/null $ROOTFS/dev/null &&
    /bin/hostname $UUID &&
    exec capsh --chroot=$ROOTFS --drop=cap_sys_chroot -- -c 'exec $CMD'
 "
$ mount -t タイプ デバイス マウント先ディレクトリ

タイプ形式でデバイスマウント先ディレクトリにマウント。

$ mount -t proc proc /proc

procディレクトリに配置されるファイルは通常のファイルと異なって、メモリ上に作成される。
なのでtypeにproc形式を明示する。

ref. https://linuc.org/study/knowledge/526/

  • mountコマンド
    • bindオプション:特定ディレクトリを別ディレクトリにマウント

Namespace

  • $$:現在のシェルのプロセス番号

Namespaceの確認

 /proc/$$/ns
 
total 0
lrwxrwxrwx 1 ubuntu ubuntu 0 May 21 05:44 cgroup -> 'cgroup:[4026531835]'
lrwxrwxrwx 1 ubuntu ubuntu 0 May 21 05:44 ipc -> 'ipc:[4026531839]'
lrwxrwxrwx 1 ubuntu ubuntu 0 May 21 05:44 mnt -> 'mnt:[4026531840]'
lrwxrwxrwx 1 ubuntu ubuntu 0 May 21 05:44 net -> 'net:[4026532040]'
lrwxrwxrwx 1 ubuntu ubuntu 0 May 21 05:44 pid -> 'pid:[4026531836]'
lrwxrwxrwx 1 ubuntu ubuntu 0 May 21 05:44 pid_for_children -> 'pid:[4026531836]'
lrwxrwxrwx 1 ubuntu ubuntu 0 May 21 05:44 time -> 'time:[4026531834]'
lrwxrwxrwx 1 ubuntu ubuntu 0 May 21 05:44 time_for_children -> 'time:[4026531834]'
lrwxrwxrwx 1 ubuntu ubuntu 0 May 21 05:44 user -> 'user:[4026531837]'
lrwxrwxrwx 1 ubuntu ubuntu 0 May 21 05:44 uts -> 'uts:[4026531838]'

Namespaceの作成

$ unshare --mount-proc -uipr --fork /bin/sh
  • Mount Namespace: マウントポイントを隔離してプロセス独自のファイルシステムを扱えるようにします。
  • PID Namespace: PID番号空間を隔離してユニークなPIDを持ちます。新しいNamespaceで最初に作成されたプロセスはPID1となり、通常のPID1プロセスと同様の特性を持ちます。
  • Network Namespace: ネットワークスタックを隔離します(後に解説あり)。
  • IPC Namespace: SysV IPCオブジェクト、 POSIXキューを隔離します。
  • UTS Namespace: ホスト名やNISドメイン名など、 unameシステムコールで返される情報を隔離します。
  • User Namespace: User ID, Group IDを隔離します。Namespace内ではUser IDが0で特権ユーザーである一方、他のNamespaceからは非特権ユーザーとして扱われる、という状態を持つことができます。
  • Cgroup Namespace: cgroupルートディレクトリを隔離します。新しくCgroup Namespaceを作成すると現在のcgroupディレクトリがcgroupルートディレクトリになります。

    – https://eh-career.com/engineerhub/entry/2019/02/05/103000#%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E3%81%A8%E3%81%AF

リソース unshareコマンドオプション
Mount –mount-proc
UTS -u, –uts
IPC -i, –ipc
PID -p, –pid
User Namespace -U, –user

Linux のコンテナ仮想化を構成する要素の 1 つに、カーネルの Namespace (名前空間) という機能がある。 Namespace には色々とあるけど、今回はホスト名と NIS (Network Information Service) 1 ドメイン名を隔離する仕組みを提供している UTS Namespace について扱ってみる。

– https://blog.amedama.jp/entry/linux-uts-namespace

$ touch ns_uts $ sudo unshare --uts=ns_uts /bin/sh -c 'hostname foobar' こちらの例では前の例と違いUTS Namespaceを隔離したプロセスは終了していますが、UTS Namespaceは ns_uts ファイルにbind mountされて維持されています。 $ mount | grep ns_uts nsfs on /home/vagrant/ns_uts type nsfs (rw) nsenterでこのファイルを指定すると以前のNamespaceをプロセスに関連付けることができます。 $ sudo nsenter --uts=ns_uts hostname foobar

cgroup

$ mount | grep cgroup
tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,mode=755,inode64)
cgroup2 on /sys/fs/cgroup/unified type cgroup2 (rw,nosuid,nodev,noexec,relatime,nsdelegate)
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,name=systemd)
cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,net_cls,net_prio)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,pids)
cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpu,cpuacct)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)
cgroup on /sys/fs/cgroup/misc type cgroup (rw,nosuid,nodev,noexec,relatime,misc)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event)
cgroup on /sys/fs/cgroup/rdma type cgroup (rw,nosuid,nodev,noexec,relatime,rdma)
cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,hugetlb)

cgroupの確認

$ ls -l /proc/$$/cgroup
-r--r--r-- 1 ubuntu ubuntu 0 May 21 06:33 /proc/1105/cgroup