ck_fm0211のブログ

書きたいことを書く。

『イラストでわかるDockerとKubernetes Software Design plus』を読んだ

この本を読んだメモ。

Docker/Kubernetesは仕事で使っているものの、きちんと勉強したことがないなと思ったので、まわりで評判の良かったこの本を丁寧に読むことにした。

本の感想

  • Docker使ってると「レイヤ」って言葉を見るけど、そのイメージがついた。イラスト付きでしっかり解説してくれるのはありがたい。
  • CRIランタイム/OCIランタイムって言葉をよく見かける。こないだも見た。これの意味を理解した。
    • CRIランタイム: 高レベルランタイム。kubeletからの命令を受け付ける部分。コンテナ・イメージ・ネットワーク等全般の管理。
    • OCIランタイム: 低レベルランタイム。CRIランタイムからの命令を受け付ける。ホストから隔離された実行環境をコンテナとして作り出し、操作可能にする。
  • コンテナを使う際に何が起きてるのか、ざっとだが理解できたと思う。書いてあるけど理解が追いつかない部分はあるのでまた読み返そう・・
  • 正直、最後の方はついていくのが大変だった。というかついていけなかった気がする。コンピュータの基礎についてちゃんと勉強したほうがいいな。

読んでてハマったこと

コマンドが書いてあるので一つ一つ模写しながら確認していった。
その中でいくつかハマったのでメモとして残しておく。

前提:検証時の環境

  • PC: MacBook Pro (13-inch, 2020)
  • OS: MacOS Catalina(10.15.7)
  • Docker Desktop(3.1.0)

overlay2のディレクトリが見つからない

2-2-4レイヤ構造のイメージからのルートファイルシステム作成に用いられる要素技術

Docker内のレイヤの重ね合わせの説明で、storage driveroverlay2」の説明がある。
Docker Imageの中で実際にレイヤがどう保存されているかを確認してみよう、というところがある。

/var/lib/docker/overlay2/

しかしこのパスがMacだと見つからない。

% ls /var/lib/docker/overlay2/
ls: /var/lib/docker/overlay2/: No such file or directory

なんでやねん、ということで調べてみると、MacのDocker DesktopはVM上で動いているため、ここで出てくるパスはローカルMacではなくてVM上のパスであるとのこと。たしかにそんなことを聞いたことがある気がする。

じゃあそのVMにはどうアクセスしたらええねん、と続けて調べてみると、以下のコマンドでアクセスできるとのことで試す。

% screen ~/Library/Containers/com.docker.docker/Data/vms/0/tty

が、できない。何も表示されない。
記事によってはttyを入れてないので、そこか?と試す。

% screen ~/Library/Containers/com.docker.docker/Data/vms/0/
[screen is terminating]

ダメ。なんか即切りされる。

screenコマンドに慣れていないので、何かが違うのか?といろいろ調べてみるが、すぐに表示されるはず、らしい。
https://qiita.com/kawanet/items/263acbb870e3d2a842cd

何がおかしいんやと追加でググる。すると以下のissueを見つけた。
https://github.com/docker/for-mac/issues/4822
StackOverFlowにも同じような悩みが。
https://stackoverflow.com/questions/63445657/why-i-am-getting-screen-is-terminating-error-in-macos/63595817#63595817
ということでworkaround1を試す
https://stackoverflow.com/questions/63445657/why-i-am-getting-screen-is-termination-error-in-macos/63595817#63595817

% docker run -it --privileged --pid=host debian nsenter -t 1 -m -u -n -i sh
/ # ls /var/lib/docker/overlay2/
04220f51e5fa4946d9ccc91265931d1ac12a9da8b8ac268eaf4d07d67b890ae2
0da11ec70bdaaecc4f570fc28082ab7ea6a268cf610d842054ff1ef5b30c7e5d
0f9284d24e5a01b131f58917b7177b96dfd9ddc519fdc8952bfd86fc99fca4ed
(後略)

いけた!

このコマンドが何をやっているのかよくわからんので分解してみる。

docker run \
-it \
--privileged \
--pid=host \
debian \
nsenter \
  -t 1 \
  -m \
  -u \
  -n \
  -i \
  sh

基本は Docker-docs-jaから引用。筆者による追記あり

  • docker run
    • 新しいコンテナを実行する命令
  • -it
    • -i(--interactive): コンテナの STDIN にアタッチ
      • Dockerを起動しているコンソールの標準出力とコンテナの標準入力が繋がる
    • -t(--tty): 疑似ターミナル (pseudo-TTY) を割り当て
      • Dockerを起動しているコンソールの標準出力とコンテナの標準出力が繋がる
  • --privileged: このコンテナに対して拡張権限を与える
    • 特権モード。ホスト(ここではMac)のすべてのデバイスへのアクセスが可能になる。
  • --pid=host
    • --pid: 使用する PID 名前空間
      • 指定したコンテナ(ホストも可)とPID名前空間を共有できる。
      • =hostとすることでホスト側のPID名前空間を共有することができる。
  • debian
    • pullするイメージ
  • nsenter
  • -t 1
    • nsenterのオプション
    • -t, --target <pid>: 名前空間を取得するターゲットプロセス
    • ここでは1を指定している。1ってなんやと調べてみると、起動プロセス。まあそうか。
root@3b877f756d3f:/# cat /proc/1/cmdline
/sbin/init
  • -m
    • nsenterのオプション
    • -m, --mount[=<file>]: マウント名前空間
  • -u
    • nsenterのオプション
    • -u, --uts[=<file>]: UTS名前空間
  • -n
    • nsenterのオプション
    • -n, --net[=<file>]: ネットワーク名前空間
  • -i
    • nsenterのオプション
    • -i, --ipc[=<file>]: システムV IPC名前空間
  • sh
    • nsenterで上記で指定した名前空間内でshellを起動する。

・・・調べてみたが結局よくわからん。特にnsenterのオプションのところがわからない。
なんとなくわかったような気がするところだけ書くと、

  • ホスト(Mac)とnamespaceを共有したdebianイメージを特権モードで起動する
  • 起動したコンテナ内でnsenterで別PIDに入り込もうとする。このときPIDに1を指定すると自分自身を指定したことになる(?)ので、ホスト側から見るとDockerコンテナを起動している場所=DockerDesktopのVMへ入ることになる(?)

なのかな、たぶん。-m -u -n -iのところが全然わからないのだけど。

あまり深追いしてもしょうがないと自分に言い聞かせることにした。だれか詳しい人教えてほしい。
とりあえず、上記コマンドでMac上で起動しているDockerDesktopのVMに入ることができる