1 Linux のユーザーランドを init から全てまるごと Golang で書く Tetsuyuki Kobayashi 2018.4.15 Go Conference 2018 Spring
2  The latest version of this slide will be available from here  http://www.slideshare.net/tetsu.koba/presentati ons
3 Who am I?  20+ years involved in embedded systems  10 years in real time OS, such as iTRON  10 years in embedded Java Virtual Machine  Now GCC, Linux, QEMU, Android, …  Blogs  https://qiita.com/tetsu_koba  http://d.hatena.ne.jp/embedded/  http://kobablog.wordpress.com/(English)  Twitter  @tetsu_koba
はじめに  golang の実行ファイルは自己完結的  基本ライブラリ (libc に相当するもの ) は自前で持っている  インストールするときに依存性が少ない  後、何を追加したら、 Linux カーネルと golang の実行ファ イルだけで動かせる?
最小構成を理解するのは エンジニアリングの基本  削って削って、残ったものが本質。  本日の「最小限」の定義  ホスト名を解決してネットワークに アクセスできること  TLS( 暗号化通信 ) はオプション  現在時刻を UTC で扱えること  タイムゾーンはオプション
本日話すること  gokrazy の紹介  docker での最小限のコンテナの 実験  最小限のルートファイルシステム  miminumgo: 最小限の初期化処理 をする go パッケージ
Gokrazy の紹介
Gokrazy とは  https://gokrazy.org/  golang だけで Linux のユーザーランドを 構築してくれる  ラズパイ 3 用のマイクロ SD カードを作成  init, dhcp, ntp とユーザーのプロセスが実 行される  WebUI でプロセスの状態が見られる
Gokrazy 動作中のルートファイ ルシステム /dev (mount devtmpfs) /dev/pts (mount devpts) /etc/hosts (auto generated) /etc/localtime /etc/resolv.conf -> /proc/net/pnp /etc/ssl/ca-bundle.pem /gokrazy/dhcp /gokrazy/init /gokrazy/ntp /proc (mount proc) /sys (mount sysfs) /tmp (mount tmpfs) /user/hello
Gokrazy の制限  sh など通常のコマンドは含んでいない  参考 gobox  カーネルモジュールをロードするしくみ は無い  必要なモジュールはあらかじめカーネル にビルトインしておく  デバイスの抜き差しは扱わない
docker での 最小限のコンテナの実験
docker で busybox 一個のファ イルを動かしてみた  docker では実マシンでの初期 化処理を自動で行ってくれる  具体的にそれが何かを実験で調べ てみた。  dockerでbusybox一個だけのファイルを含むイメージを作って動かしたらどうなるか
docker が自動生成したファイル /dev (mount devtmpfs) /dev/pts (mount devpts) /etc/hostname /etc/hosts /etc/mtab -> /proc/mounts /etc/resolv.conf /proc (mount proc) /sys (mount sysfs)
最小限のルートファイルシステム
最小限のルートファイルシステム /dev (mount devtmpfs) /dev/pts (mount devpts) /etc/hosts (auto generated) /etc/resolv.conf -> /proc/net/pnp /proc (mount proc) /sys (mount sysfs) /tmp (mount tmpfs) /etc/hostname が無い場合のデフォルトの hostname は IP アドレスの ASCII 表現
時刻に関して  最小限では UTC のみが扱える  ローカルタイムを扱うには /etc/localtime を追加  その他のタイムゾーンを扱うには  /usr/share/zoneinfo/ 以下のファイルが 必要  または、 runtime.GOROOT 以下に /lib/time/zoneinfo.zip を置く
TLS( 暗号化通信 ) に関して  最小限では TLS は扱えない  /etc/ssl/certs/ 以下のファイルが必要  ルート証明書だけでも  /etc/ssl/certs/ca-certificates.crt
minimumgo: 最小限の初期化処理を してくれる go パッケージ
minimumgo  最小限の初期化処理をしてくれる go パッケージを自作した  ブランク (_) import するだけ  その golang の実行ファイルを init として動かせる  設定はカーネルパラメータで  ntp サーバの指定
使用例 package main import ( "log" "net/http" ) func main() { log.Fatal(http.ListenAndServe(":80", http.FileServer(http.Dir("/")))) } この golang のプログラムを一個だけ動かしたい場合
使用例 package main // This should be imported at first import _ "github.com/tetsu-koba/minimumgo" import ( "log" "net/http" ) func main() { log.Fatal(http.ListenAndServe(":80", http.FileServer(http.Dir("/")))) } minimumgo パッケージを import するだけで、 これを init として動かせる。
minimumgo  https://github.com/tetsu-koba/minimumgo  example に ラズパイ用にビルドして initramfs のイメージを作成して動かす 方法を書きました
最後に  本セッションの観察や実験を通して、 Linux の 起動時に行っていることが明らかに。  「 Linux のユーザーランドを golang で init から まるごと全部書く」 -> 達成。  minimumgo パッケージは実験用。  ブラックボックスとして使うのでなくてソー スコードを参考にしてください。 
References  gokrazy  Linuxのユーザーランドをinitから全てまるごと golangで書く  dockerでbusybox一個だけのファイルを 含むイメージを作って動かしたらどうなるか  dockerでgolangの実行ファイル1個だけを 含むイメージを作って動かす  https://github.com/tetsu-koba/minimumgo 
25 Q & A @tetsu_koba Thank you for listening!

Linuxのユーザーランドをinitから全てまるごとgolangで書く