LoginSignup
2
1
記事投稿キャンペーン 「2024年!初アウトプットをしよう」

開発環境のコンテナ実行環境をモダンに構築する

Posted at

動機

  1. そういえば新環境に Docker 入れてないなあ
  2. そういえば Container Runtime って色々あるらしいよね
  3. せや! Docker やめたろ!

という訳で Docker をやめてみるという話です.

謝辞

多くの情報をこの記事から得ています. 感謝.
執筆時現在 (2024/01/24), 最終更新は 2023/11/14 です (i.e. 割と最近の情報なんじゃないかな).

環境

環境は ALARM (Arch Linux ARM) on Asahi Linux です. 雑になんか色々貼っておきます.

uname -a
Linux alarm 6.5.0-asahi-15-1-edge-ARCH #2 SMP PREEMPT_DYNAMIC Thu, 12 Oct 2023 08:22:22 +0000 aarch64 GNU/Linux
neofetch
                   -`                    nanai@alarm
                  .o+`                   -----------
                 `ooo/                   OS: Arch Linux ARM aarch64
                `+oooo:                  Host: Apple MacBook Pro (16-inch, M1 Pro, 2021)
               `+oooooo:                 Kernel: 6.5.0-asahi-15-1-edge-ARCH
               -+oooooo+:                Uptime: 10 hours
             `/:-:++oooo+:               Packages: 496 (pacman)
            `/++++/+++++++:              Shell: zsh 5.9
           `/++++++++++++++:             Resolution: 3456x2160
          `/+++ooooooooooooo/`           WM: sway
         ./ooosssso++osssssso+`          Terminal: alacritty
        .oossssso-````/ossssss+`         CPU: (10) @ 2.064GHz
       -osssssso.      :ssssssso.        Memory: 7392MiB / 15362MiB
      :osssssss/        osssso+++.
     /ossssssss/        +ssssooo/-
   `/ossssso+/:-        -:/+osssso+-
  `+sso+:-`                 `.-/+oso:
 `++:.                           `-/+/
 .`                                 `/ 

Firefox がメモリバカ食いしてるのがバレますね〜.

containerd と runC の話

containerd と runC はどちらとも docker において規定で使用される Container Runtime です.

特筆することはありません. Go で書かれています. ちゃんと動きます. みんな使ってます (多分).

Arch なら dockerx86_64 extra で入ると思います (うろ覚え). rootless にしたいなら AUR の docker-rootless-extrasaur を入れればすんなり動きます (体験談). あと docker-credential-passaur とか入れておくと幸せになれます (体験談). 兎にも角にも 聖書[ArchWiki のこと] を読んでおけばどうにかなります (世界の理). 大丈夫です, works well です.

CRI-O の話

CRI-O は立ち位置としては dockerd と同様です. 思想の違いとしては OCI1 の最低限の機能を実装するとしている点と, 内部の設計が若干違う点らしいです.

pacman から cri-ox86_64 extra は簡単に導入できますし動作しますが, rootless にしないことには始まらない2 ので, これを試してみます.

ただ, 文献が殆ど無い. 公式の man 5 crio.conf3 を読んで頑張ってみることに.

で出来上がった 1 つ目の産物がこちら. ちなみにちゃっかり runC じゃなくて crun (後述) を使うように変更してます.

sudo setcap cap_chown,cap_sys_admin=ep /usr/bin/crio

env _CRIO_ROOTLESS=1 crio                                                         \
    --listen                      $XDG_RUNTIME_DIR/crio/crio.sock                 \
    --default-runtime             crun                                            \
    --log-dir                     $HOME/log-crio-pods                             \
    --root                        /tmp/crio-root                                  \
    --runtimes                    crun:::oci:false:                               \
    --container-attach-socket-dir $XDG_RUNTIME_DIR/crio                           \
    --container-exits-dir         $XDG_RUNTIME_DIR/crio/exits                     \
    --version-file                $XDG_RUNTIME_DIR/crio/version                   \
    --clean-shutdown-file         $XDG_RUNTIME_DIR/crio/clean.shutdown            \
    --storage-driver              overlay                                         \
    --storage-opt                 "overlay.mount_program=/usr/bin/fuse-overlayfs"

悪戦苦闘の経緯:

  1. Permission Denied が頻発した
    s. 規定で特権の必要なディレクトリ構成になっているので, 全部 $XDG_RUNTIME_DIR に押し込めた
    r. それ自体は動いた
  2. chown が出来ないとか mount が出来ないとか言われた
    s. capabilities の問題かと思い, cap_chown,cap_sys_admin=ep を付与
    r. 動いた
  3. 結局なんかうまく動かなかった
    s. rootlesskit を使ってみることに

という訳で rootlesskit を使ってみた版が〜… コマンドを紛失しました. ガチうろ覚えですがこんな感じ…

wget https://raw.githubusercontent.com/cri-o/cri-o/2ead2413a7987de2e8a975f8a509233ce7bdcd47/contrib/cni/11-crio-ipv4-bridge.conflist
sudo mv 11-crio-ipv4-bridge.conflist /etc/cni/cfg.d

rootlesskit \
    --copy-up /run            \
    --copy-up /var/cache/crio \
    --copy-up /var/run/crio   \
    crio                      \
        --listen                      $XDG_RUNTIME_DIR/crio/crio.sock \
        --default-runtime             crun                            \
        --runtimes                    crun:::oci:false:
  1. ファイルを書き込めないとか騒ぎ始めた
    s. 全部 --copy-up に指定した
    r. 起動まで漕ぎ付いた
  2. pod 作成時に cni 関係が準備できないと言われた
    s. 適当な cni の設定を落として配置した
    r. 動いた
  3. container 作成時に pinns に関する ns file が作れないとか言われた
    s. 無理

pin ってなんすか (無知). いや Linux の namespace 絡みなんですけども. 驚くほど文献が無かった… 1 作業日くらい丸ごと費やしましたが動作までは辿り着けませんでした… ぐぬぬ. 仕方ない.

後出しですが1 rootlesskit は Arch だと rootlesskitx86_64 extra にあります. 先に挙げた docker-rootless-extrasaur で内部的に使われていたりします.

後出しですが2 CLI には crictl を使っていました (Arch なら crictlx86_64 extra).

これにて私の CRI-O + crun という浪漫, 野望, 願望は潰えたのでした. おしまい.

Container Runtime の話

container.conf のキーを見るに, Runtime は containerd らを指すのに対して runC らは engine, Container Engine な気もするのだが, ちょっと詳しいことは分からないので割愛.

runC [Go]

runC は前述した通り Go で書かれており, docker における規定の Container Runtime です. Arch では crunx86_64 extra が提供しています.

crun [C]

crun は C で書かれた Container Runtime です. README に記載のある公式ベンチマークを見るにめっちゃ速いです. すげー. ただ production ready ではないらしい. Arch では crunx86_64 extra が提供.

scrun (gVisor) [Go]

scrun, もとい gVisor の Container Runtime は Go で書かれています. Arch なら AUR に gvisor-binaur があります. ただ runC などと違うのは, scrun もとい gVisor が runC らとは異なるアプローチで抽象化を行っており, 非常にセキュアな設計である事だとか.

ちなみに弊環境では動きませんでした. ちゃんと設定すれば動いたのかもしれません.

panic: Only 4K page size is supported on arm64!

goroutine 1 [running]:
gvisor.dev/gvisor/pkg/hostarch.init.0()
    pkg/hostarch/hostarch_arm64.go:59 +0x44

youki [Rust]

youki は Rust で書かれた Container Runtime です. crun に並んで高速ですが, それよりも若干遅いらしい (その分コンパイラによってメモリ安全性が担保されていると思いたい). こちらも多分 production ready ではないのだと思います (知らんけど). Arch だと AUR に youkiaur があります.


さて, runC は試してませんがきっと動くんでしょう (弊環境では未確認). scrun は先に述べたとおり動かず. crun と youki は動くことを雑に確認しましたが, 私は Rustacean なので youki を使ってみます. 今の所問題には遭遇してません.

Podman + youki の話

Podman は Container Runtime で containerd や CRI-O と同様の立ち位置ですが, daemon-less である点が非常に特徴的な設計となっています. ところで, 元を辿ると Podman は crun と同じ RedHat 社絡みのプロジェクトらしいです. Arch なら podmanx86_64 extra が提供しています.

Podman は規定で crun を使いますが, youki を使いたいので規定の Container Runtime に設定してみましょう. rootless なら $HOME/.config/containers/containers.conf を読んでくれるらしい4 のでここに設定を記入します.

.config/containers/containers.conf
[engine]
runtime = "youki"

おっけー. これだけ. いざ実行.

podman run -it alpine:latest busybox sh

動いた. easy ですね.

ちなみに弊環境は aarch64 なので archlinux は動かないのです (というか pull が拒否される). そして, 有志の docker.io/menci/archlinuxarm5 があったりするので, ALARM on ALARM しましょう.

podman run -it docker.io/menci/archlinuxarm sh

動きました (地味).

他の話

rkt が使いたかった. 既に EoL が宣言されています.

後記

もうちょっと ドラマチック な環境構築になるかと期待したのですが, 結局 rootless OCI-O は頓挫してしまったので悔いが残る感じです. ちょっと残念. 誰か教えてください.

最近は別プロジェクトで Linux の共有メモリとかに触れていましたが, 常用かリッチアプリケーション程度の開発では触れない機能, 知らない機能が沢山あるなーと思います (今回だと Linux の仮想化技術). まあこれを直接触って運用… という機会は中々無いと思いますが, 詳しく知りたいですね.

参考

読んで参考になったなーってものを羅列しておきます.

  1. https://opencontainers.org/

  2. 特権持ちとして container を動かすと root 持ちのファイルが散乱するので嫌なんですよね. セキュリティの観点とかは詳しく知らないのでパス… 強いて言えば, container から突然 rm -rf / とかされたらキレるよね, みたいな部分もある.

  3. https://man.archlinux.org/man/crio.conf.5

  4. https://man.archlinux.org/man/containers.conf.5

  5. https://hub.docker.com/r/menci/archlinuxarm

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1