Rancher OSのState Partitionをsdb1で使う

# TL;DR

Rancher OSをISO運用するときにState Partitionの自動マウントが"/dev/sda"と"/dev/vda"のラベルが"B2D_STATE"の時だけで"/dev/sda1"とか使いたい時に困るので，"/dev/sda1"と"/dev/sdb"と"/dev/sdb1"を自動マウントするカスタムISOを作ります．

# はじめに

DockerがKubenetesを公式サポートしたらしいですが，インストールめんどくさいです．でもRancherなら簡単でいいですね．弊研究室もRancher OSでKubernetesクラスタ建てようと思います．

ただ，マシンをバンバン導入するほど余裕はないので，使っていないPCを使いたい…けど，すでに導入済みのWindowsを消すわけにはいかないのでEasyBCDからRancher OSのisoを直接ブートして使う事になりました．

でも，状態保存するにはState Partitionをマウントさせなければならないですが，カーネルパラメータとかいじれない状況なので"/dev/sda"に"B2D_STATE"っていうラベル設定するしかない．
[Persistent State Partition](http://rancher.com/docs/os/v1.1/en/storage/state-partition/)

なので，"/dev/sda1"とか"/dev/sdb"とか"/dev/sdb1"とかも対象にしてみました．

# Rancher OSのソースをクローンする

まず，Rancher OSのソースをクローンしましょう．

```bash
$ git clone https://github.com/rancher/os
$ cd os
```

# 書き換えれば良さそうなところを探す

```bash
$ grep -r "B2D_STATE" -I ./
.//init/init.go:			if dev := util.ResolveDevice("LABEL=B2D_STATE"); dev != "" {
.//init/init.go:				cfg.Rancher.State.Dev = "LABEL=B2D_STATE"
.//init/init.go:						cfg.Rancher.State.Dev = "LABEL=B2D_STATE"
.//images/02-bootstrap/auto-format.sh:            mkfs.ext4 -L B2D_STATE ${dev}
.//tests/boot2docker_autoformat_test.go:	s.CheckCall(c, "blkid | grep B2D_STATE")
.//tests/boot2docker_autoformat_test.go:	s.CheckCall(c, "blkid | grep B2D_STATE")
.//tests/boot2docker_autoformat_test.go:	s.CheckCall(c, "sudo ros config get rancher.state.dev | grep LABEL=B2D_STATE")
grep: .//build/initrd/usr/var/lib/cni/bin/host-local: No such file or directory
grep: .//build/initrd/usr/var/lib/cni/bin/bridge: No such file or directory
grep: .//build/initrd/usr/lib/modules/4.9.78-rancher2/source: No such file or directory
grep: .//build/initrd/usr/lib/modules/4.9.78-rancher2/build: No such file or directory
grep: .//build/kernel/lib/modules/4.9.78-rancher2/source: No such file or directory
grep: .//build/kernel/lib/modules/4.9.78-rancher2/build: No such file or directory
```

お，`init/init.go`が怪しそうです．

開いてみましょう．

```go:init/init.
...
config.CfgFuncData{"b2d env", func(cfg *config.CloudConfig) (*config.CloudConfig, error) {
			if dev := util.ResolveDevice("LABEL=B2D_STATE"); dev != "" {
				boot2DockerEnvironment = true
				cfg.Rancher.State.Dev = "LABEL=B2D_STATE"
				log.Infof("boot2DockerEnvironment %s: %s", cfg.Rancher.State.Dev, dev)
				return cfg, nil
			}

			devices := []string{"/dev/sda", "/dev/vda"}
			data := make([]byte, len(boot2DockerMagic))

			for _, device := range devices {
				f, err := os.Open(device)
				if err == nil {
					defer f.Close()

					_, err = f.Read(data)
					if err == nil && string(data) == boot2DockerMagic {
						boot2DockerEnvironment = true
						cfg.Rancher.State.Dev = "LABEL=B2D_STATE"
						cfg.Rancher.State.Autoformat = []string{device}
						log.Infof("boot2DockerEnvironment %s: Autoformat %s", cfg.Rancher.State.Dev, cfg.Rancher.State.Autoformat[0])

						break
					}
				}
			}
...
```

ありました．ここの`devices := []string{"/dev/sda", "/dev/vda"}`を`devices := []string{"/dev/sda", "/dev/sda1", "/dev/sdb", "/dev/sdb1"}`に書き換えましょう．

# Rancher OSをビルドする

書き換えが終わったのでビルドしてみましょう．おっとその前に，macOSではビルドに必要なツールの[dapperがSEGVする](https://github.com/rancher/dapper/issues/47)ので，ビルドしておきましょう．


dapperのリポジトリをcloneしてビルドします．

```bash
$ cd ..
$ git clone https://github.com/rancher/dapper
$ cd dapper
$ docker run --rm -v $(pwd):/go/src/github.com/rancher/dapper -w /go/src/github.com/rancher/dapper -e GOOS=darwin golang:latest go build
```

dapperのバイナリがあるのでコピーしましょう．

```bash
$ cd ../os
$ cp ../dapper/dapper ./.dapper
```

いよいよRancher OSのビルドです．

```bash
$ make
```

ビルドが終わったら`dist/artifacts/rancheros.iso`を起動してみてください．`sudo ros config export`で`state`が表示されていれば成功です．

# カーネルパラメータでどうにかする

ソースコードいじるのはいろいろと問題ありそうなので，他の方法探してみました．
どうやら，`APPEND`っていう環境変数にカーネルパラメータが設定できるみたいなので，
makeするときに渡してみましょう．

```bash
$ make APPEND='rancher.state.dev="/dev/sdb1"'
```

正常にmountされてますね．最初からこれに気がつけばよかった．