構成
- dnsmasq Proxy DHCPで構成
- matchbox
- NETBOOT.XYZ
- dnsmasq, matchbox, netboot.xyz はdocker-composeで起動
- CentOS 7
- KVM と Dockerが混在
こんな感じで起動
それ以外の場合は NETBOOT.XYZ でブートメニュー出す
matchbox
CoreOSの起動に必要なIgnitionファイルやカーネルパラメータをホストしてくれるやつです。
PXEブートする際に、MACアドレスやアーキテクチャによって起動するイメージを変えたくなると思うのですが、
matchboxの仕様に沿ってセットアップすると仕組みを自前で用意するより楽になります。
netboot.xyz
LinuxディストリビューションのインストールにはDVD、USBメディアを用意する事が多いですが、メディアの用意が必要です。
ネットワークインストールの仕組みで解決できるのですが、OSのバージョンアップごとにPXE用のメニューファイルの更新も必要です。
PXEブートのメニューファイルを各ディストリビューションのアップデートに追随してくれるのが netboot.xyz
※ netboot.xyz は、デフォルトで、カーネルイメージやinitramfsをインターネットの向こう側から取得するようです
非常に遅いので、管理画面から事前にファイルを取得しておくことをオススメします。
docker-compose用のディレクトリ構成
docker-compose.ymlが置いてあるディレクトリに containers というディレクトリを作り、
配下に各コンテナ用サブディレクトリを作り管理。
matchboxの動作に必要なファイルはDockerfileでCOPYではなく、
docker-compose.yml の volumes:
でマウントしています。
.
├── README.md
├── containers
│ ├── dnsmasq
│ │ ├── Dockerfile
│ │ ├── dnsmasq.conf
│ │ └── tftpboot
│ ├── matchbox
│ │ ├── etc
│ │ └── var
└── docker-compose.yml
docker-compose.yaml
dnsmasqはAlpineLinuxからDockerfileでビルド、
matchbox、netbootxyzはイメージをそのまま使わせてもらい、必要なディレクトリはマウント。
version: '3'
services:
dnsmasq:
container_name: dnsmasq
build:
context: containers/dnsmasq
network_mode: "host"
volumes:
- ./containers/dnsmasq/tftpboot/linux-install:/var/ftpd
- ./containers/dnsmasq/dnsmasq.conf:/etc/dnsmasq.conf
restart: always
matchbox:
container_name: 'matchbox'
image: quay.io/poseidon/matchbox:latest
volumes:
- ./containers/matchbox/var/lib/matchbox:/var/lib/matchbox:Z
- ./containers/matchbox/etc/matchbox:/etc/matchbox:Z,ro
ports:
- '8080:8080'
command: -address=0.0.0.0:8080 -rpc-address=0.0.0.0:8081
restart: always
netbootxyz:
image: linuxserver/netbootxyz
container_name: netbootxyz
environment:
- PUID=1000
- PGID=1000
ports:
- 3000:3000
- 8081:80
restart: always
dnsmasq関連
DHCPが既にネットワーク内に立っているので、dhcp proxyで構成します
containers/dnsmasq/Dockerfile
FROM alpine:edge
RUN apk --no-cache add dnsmasq
EXPOSE 67/udp 69/udp 4011/udp
CMD ["dnsmasq", "-k", "-d"]
下記ポートDockerfileでEXPOSEしています。
ポート | サービス |
---|---|
67/udp | dhcp |
69/udp | TFTP |
4011/udp | PXE Proxy |
dnsmasq.conf
コンテナで動かす際に
network_mode: "host"
ホストのポートに直接紐付けて起動しています。
このモードの場合、ホストのネットワークインターフェースが見えるため、
dnsmasqが既存のvirbr0( libvirt のネットワークインターフェース )に悪さをしないように except-interface=virbr0
の設定を入れています。
( すみません、自宅サーバで検証に時間が取れず... )
ただ、libvirtdが立てるdnsmasqが立っていると、コンテナで立てるdnsmasqと競合するため、
サーバ起動後、手動でlibvirtdのdnsmasqのプロセスをkillしています( ここはもう少し調べたい... )
netboot.xyzを用いての初期セットアップを行いたいマシンは
dhcp-mac=set:netboot,02:1a:4a:16:01:9c
の様にして、netbootのタグを付けて振り分けています。
except-interface=virbr0
dhcp-range=10.10.254.0,proxy
pxe-service=tag:#ipxe,x86PC,"PXE chainload to iPXE",undionly.kpxe
# iPXE user classからのリクエストの場合はipxeタグをセットする
dhcp-userclass=set:ipxe,iPXE
# netboot.xyzでセットアップしたいMACアドレスを追記していく
dhcp-mac=set:netboot,02:1a:4a:16:01:9c
tag-if=set:netboot-xyz, tag:ipxe, tag:netboot
# netboot.xyz
pxe-service=tag:netboot-xyz,x86PC,"iPXE",http://10.10.254.200:8081/menus/menu.ipxe
# matchbox
pxe-service=tag:ipxe,x86PC,"iPXE",http://10.10.254.200:8080/boot.ipxe
enable-tftp
tftp-root=/var/ftpd
log-queries
log-dhcp
dnsmasqでの起動順序
- パソコンの電源投入、PXEブートを開始、ネットワークカードが頑張ってIPアドレスとPXEサーバを探す
- パソコンは dnsmasqのTFTPを経由してiPXEプロジェクトの undionly.kpxe をダウンロード、カーネルのチェインロードを始める
- undionly.kpxeがHTTPプロトコルでmatchboxやnetboot.xyzとやり取りする
- dnsmask.confでnetbootタグが設定されている場合は、 http://10.10.254.200:8080/assets/default.ipxe をPXEのメニューにしています
- netbootタグがついてないマシンはmatchboxの http://10.10.254.200:8080/boot.ipxe で処理
- matchboxはMACアドレスやアーキテクチャに応じてPXEのメニューファイルを作成し、パソコンに返す
という流れになります。
余談ですが、この辺、サイボウズのsabakan https://febc-yamamoto.hatenablog.jp/entry/2019/02/09/181927 で簡単にできるかな? とも思っているのですが、
CoreOSのIgnition周りなんかを生で触って理解したいというのもありmatchboxを使ってみています。
matchbox
docker-compose.ymlのmatchbox関連の設定ですが下記のようにしています。
オフィシャルのDockerイメージをそのまま使い、
設定ファイルやアセットはVolumesの設定でマウント。
ログは docker logs matchbox
というようにコンテナの出力を見ています。
matchbox:
container_name: 'matchbox'
image: quay.io/poseidon/matchbox:latest
volumes:
- ./containers/matchbox/var/lib/matchbox:/var/lib/matchbox:Z
- ./containers/matchbox/etc/matchbox:/etc/matchbox:Z,ro
ports:
- '8080:8080'
command: -address=0.0.0.0:8080 -rpc-address=0.0.0.0:8081
restart: always
/var/lib/matchbox 配下のファイル構成は下記のようにしています。
.
├── assets
│ ├── default.ipxe
│ ├── fedora-coreos-31.20200113.3.1-live-initramfs.x86_64.img
│ └── fedora-coreos-31.20200113.3.1-live-kernel-x86_64
├── groups
│ └── fs01.json
├── ignition
│ ├── fedora-core-1.ign
│ └── netboot-xyz-1.ign
└── profiles
├── fedora-core-1.json
└── netboot-xyz-1.json
それぞれのディレクトリですが
group MACアドレスにどのプロファイルを割り当てるか
{
"id": "fedora-core-1",
"name": "Fedora Core - 1",
"profile": "fedora-core-1",
"selector": {
"mac": "00:24:1d:18:28:09"
}
}
profile PXEブート時のカーネルイメージの指定とカーネルパラメータ
sshkey, ignition.config.url はそれぞれの環境に応じて変更する必要あり。
基本的には Fedora CoreOS のPXEブートのパラメータ を参照
パラメータの意味については CoreOSの説明 が役に立つかも。
Fedora CoreOSのサイトから私が変更した箇所が2点あり
- 2020/05時点ではdockerが cgroup v2 に対応していないので v1 に切り替え
- selinuxのoff
cgroup v2 ではなく v1 に変更した手順
Fedoraの新しめのカーネルは cgroup v2 だが、docker側が対応していないのでv1にしておく必要がある カーネルパラメータに systemd.unified_cgroup_hierarchy=0
を追加した
Fedora CoreOSのPXEでのセットアップ手順 には乗ってないので注意
( Fedora CoreOS はdockerではなく、podman推しなのかもしれませんが )
またカーネルオプションで selinux=0
を追加して selinuxをオフにしました。
matchboxのインストールディレクトリ配下の
profiles/fedora-core-1.json に下記のように設置。
{
"id": "fedora-core-1",
"name": "Fedora Core - 1",
"ignition_id": "fedora-core-1.ign",
"boot": {
"kernel": "/assets/fedora-coreos-31.20200407.3.0-live-kernel-x86_64",
"initrd": [
"/assets/fedora-coreos-31.20200407.3.0-live-initramfs.x86_64.img"
],
"args": [
"ip=dhcp",
"rd.neednet=1",
"console=tty0",
"console=ttyS0",
"selinux=0",
"ignition.firstboot",
"ignition.platform.id=metal",
"systemd.unified_cgroup_hierarchy=0",
"sshkey=ssh-rsa himitu naisho@kaoru-no-MacBook-Pro.local",
"ignition.config.url=http://10.10.254.200:8080/ignition?mac=${mac:hexhyp}"
]
}
}
assets CoreOS起動時に必要なカーネルイメージ、initramfsファイルなど
fedora CoreOSのダウンロードページ からダウンロードもできるのですが、
都度ダウンロードするのは面倒なので、そのページにあるjsonファイルを参考にして、下記のようにもダウンロードできます。
matchboxのインストールディレクトリのassetディレクトリ配下に移動し
coreos_stable=$(curl https://builds.coreos.fedoraproject.org/streams/stable.json)
kernel_url=$(echo $coreos_stable | jq --raw-output '.architectures.x86_64.artifacts.metal.formats.pxe.kernel.location')
initramfs_url=$(echo $coreos_stable | jq --raw-output '.architectures.x86_64.artifacts.metal.formats.pxe.initramfs.location')
curl -O $kernel_url
curl -O $initramfs_url
でstableなカーネル、initramfsイメージをダウンロードしています。
併せてmatchbox/profile配下のプロファイル用のファイルも更新する必要があります。
またmatchboxのこのディレクトリは、カーネルイメージやinitramfsを置く場所として使うのですが、
Webサーバのように公開されるので、インストール関連で使うものを置いておくのも便利かもしれません。
私はnetboot.xyzのファイルなどを置いています。
ignition OS内の各種設定( ユーザー追加、ストレージ、サービスの設定などなど )
はまったポイントなのですが、いろいろなサイトの事例のjsonをコピペして編集してみたのですが、
ユーザー追加ができてないようでハマってました( ログインできないので調査しずらい... )
Container Linuxの後継となる新たなコンテナ向けOS「Fedora CoreOS」の「Ignitionの設定ファイルとfcctコマンド」を参考にしつつ、fcctコマンドでjsonを作成しました。
fcctコマンドのインストールだけどpodman経由でインストールする手順もあるみたい 手軽なのよい( プロダクション環境だとpodmanのレポジトリが落ちてるケースも考える必要がありそうだけど )
下記のようなyamlファイルを作成し、
variant: fcos
version: 1.0.0
passwd:
users:
- name: inoue
groups:
- adm
- sudo
ssh_authorized_keys:
- ssh-rsa ssh公開鍵 hogehoge@hogehoge-no-MacBook-Pro.local
systemd:
units:
- name: shell.service
enabled: true
contents: |
[Unit]
Description=Alpine CLI Shell
After=network.target
[Service]
Type=simple
ExecStart=/usr/bin/podman run --rm --privileged -v /:/host -ti alpine:latest /bin/ash
[Install]
WantedBy=multi-user.target
./fcct --input fcc_test.yaml --pretty --output fedora-core-1.ign
のように実行すると下記のものができました。
{
"ignition": {
"config": {
"replace": {
"source": null,
"verification": {}
}
},
"security": {
"tls": {}
},
"timeouts": {},
"version": "3.0.0"
},
"passwd": {
"users": [
{
"groups": [
"adm",
"sudo"
],
"name": "inoue",
"sshAuthorizedKeys": [
"ssh-rsa SSHの公開鍵 hogehoge@hogehoge-no-MacBook-Pro.local"
]
}
]
},
"storage": {},
"systemd": {
"units": [
{
"contents": "[Unit]\nDescription=Alpine CLI Shell\nAfter=network.target\n[Service]\nType=simple\nExecStart=/usr/bin/podman run --rm --privileged -v /:/host -ti alpine:latest /bin/ash\n[Install]\nWantedBy=multi-user.target\n",
"enabled": true,
"name": "shell.service"
}
]
}
このjsonファイルをignitionディレクトリ配下に設置します。
firewalld設定
CentOS7だとファイアーウォールで開ける必要があります。
firewall-cmd --zone=public --add-service=tftp-client --permanent
firewall-cmd --zone=public --add-service=tftp --permanent
firewall-cmd --zone=public --add-service=proxy-dhcp --permanent
firewall-cmd --zone=public --add-service=dhcp --permanent
firewall-cmd --zone=public --add-port=69/udp --permanent # TFTP
firewall-cmd --zone=public --add-service=dns --permanent
firewall-cmd --zone=public --add-port=4011/udp --permanent # PXE proxy
firewall-cmd --zone=public --add-port=8080/tcp --permanent # 私がmatchboxに割り当てたポート
firewall-cmd --reload
firewall-cmd --list-all