RaspberryPi 3B+を持っているので、k3s環境をつくってみようと思い立ち、いろいろ調べたのですが以下の理由でOS自体をYoctoで作成してみました。
- raspbianは32bitOSだった。
- ubuntuは64bit版が存在するが、USBからうまく起動出来なかった。
- ArchLinuxは起動イメージ作成手順が面倒に思えた。
長くなったので(1)~(3)に分けていますが、k3s環境の構築は(2)までで終了します。
(3)はソフトウェアをパッケージ管理でソフトウェアを追加する方法になります。
OS作成
Yocto環境準備
-
ビルド環境(docker image)
Yoctoのビルド環境は公式マニュアル参照
私は、使用しているNASにdockerが搭載されているので、これを使用してビルドする環境を作成した。-
Dockerfile
DockerfileFROM ubuntu:18.04 ENV DEBIAN_FRONTEND noninteractive RUN apt-get update && apt-get dist-upgrade -y && apt-get autoremove --purge -y \ && apt-get install -y \ gawk wget git-core diffstat unzip texinfo gcc-multilib \ build-essential chrpath socat cpio python python3 python3-pip python3-pexpect \ xz-utils debianutils iputils-ping python3-git python3-jinja2 libegl1-mesa libsdl1.2-dev \ tmux locales libtinfo-dev libncurses5-dev \ && rm -rf /var/lib/apt/lists/* # Locales RUN dpkg-reconfigure locales \ && locale-gen en_US.UTF-8 \ && update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 ENV LC_ALL en_US.UTF-8 ENV LANG en_US.UTF-8 ENV LANGUAGE en_US.UTF-8
-
docker image 作成
$ docker build [ -t {イメージ名} [ :{タグ名} ] ] {Dockerfileのあるディレクトリ} $ docker build -t yocto_build:001 .
-
docker image 起動
$ docker run -it -u $(id -u):$(id -g) -v /home:/home -w /home yoctobuild:${TAG} /bin/bash
-vオプションは、ホストの/homeをdocker image上の/homeにマウントしてる。
-wオプションは、起動時のカレントディレクトリを指定。
これらオプションで作業ディレクトリをホストと共有し、docker image終了時にファイルが破棄されない様にしている。
-
-
ソース取得
適当なディレクトリに移動して以下コマンドで取得
$ git clone https://git.yoctoproject.org/git/poky -b zeus $ git clone https://git.yoctoproject.org/git/meta-raspberrypi -b zeus $ git clone https://github.com/openembedded/meta-openembedded.git -b zeus
YoctoLinux作成
環境変数・カレントディレクトリ設定
-
oe-init-build-env
pokyディレクトリ配下のoe-init-build-envを設定ファイルに使用。
引数に設定した文字列がカレントディレクトリになる。
例)$ cd poky $ source oe-init-build-env raspberrypi $ pwd ~/poky/raspberrypi
設定変更
-
基本設定・ソフトウェア
conf/local.confを修正
-
機種設定
以下を記載MACHINE ?= "raspberrypi3-64"
-
initのsystemd化
以下を追記
DISTRO_FEATURES_append = " systemd pam" VIRTUAL-RUNTIME_init_manager = "systemd" VIRTUAL-RUNTIME_dev_manager = "systemd" DISTRO_FEATURES_BACKFILL_CONSIDERED = "sysvinit" VIRTUAL-RUNTIME_initscripts = "" IMX_DEFAULT_DISTRO_FEATURES_append = " systemd"
-
wifi bluetooth
wifiとbluetoothを使ウカもしれないので機能FWを追加しておく
COMBINED_FEATURES_append = " wifi bluetooth" DISTRO_FEATURES_append = " bluez5"
-
出力ファイルサイズの指定
2GB SDカードに書き込めるサイズを指定
IMAGE_ROOTFS_SIZE = "1787436" IMAGE_OVERHEAD_FACTOR = "1.0"
-
ホストネーム設定
hostname_pn-base-files = "yoctopi3"
-
ユーザーの追加・変更
piユーザーを追加、パスワードとsudoサブグループを追加しシェルをbashに変更。
rootユーザーにパスワード追加とログイン禁止設定。INHERIT_append = " extrausers" EXTRA_USERS_PARAMS = " \ useradd -P raspberry -G sudo -s /bin/bash pi; \ usermod -P rootuser -s /sbin/nologin root; \ "
-
タイムゾーン
タイムゾーン設定で日本を指定
IMAGE_INSTALL_append = " tzdata" DEFAULT_TIMEZONE = "Asia/Tokyo"
-
追加設定
rootユーザーのホームディレクトリを指定
ROOT_HOME = "/root"
cmdline.txt の内容を編集
ルート領域をSDからUSBに変更(USBストレージからのbootを可能にする)CMDLINE_remove = " root=/dev/mmcblk0p2" CMDLINE_append = " root=/dev/sda2"
この設定を無効にすると、SDカード用のイメージになる。
cgroup機能有効化
CMDLINE_append = " cgroup_enable=memory cgroup_memory=1"
GPUメモリを16MBに変更
GPU_MEM = "16"
I2CとSPIを有効化
ENABLE_I2C = "1" ENABLE_SPI_BUS = "1"
-
キャッシュ類のディレクトリ変更
DL_DIR ?= "/home/ragnadragon/yocto_zeus/download" SSTATE_DIR ?= "/home/ragnadragon/yocto_zeus/sstate"
-
追加ソフト
IMAGE_FEATURES_append = " package-management" IMAGE_FEATURES_append = " ssh-server-openssh" IMAGE_FEATURES_append = " nfs-client nfs-server" IMAGE_INSTALL_append = " bash sudo" IMAGE_INSTALL_append = " openssh openssh-sftp-server" IMAGE_INSTALL_append = " acpid acpitool" IMAGE_INSTALL_append = " vim vim-tiny" IMAGE_INSTALL_append = " avahi-daemon" IMAGE_INSTALL_append = " util-linux usbutils" IMAGE_INSTALL_append = " net-tools iproute2" IMAGE_INSTALL_append = " wget curl python3-pip" IMAGE_INSTALL_append = " i2c-tools python-smbus bridge-utils hostapd" IMAGE_INSTALL_append = " linux-firmware-rpidistro-bcm43455 wpa-supplicant bluez5"
-
コメント無し全体
local.confMACHINE ?= "raspberrypi3-64" MACHINE ??= "qemux86" DISTRO_FEATURES_append = " systemd pam" VIRTUAL-RUNTIME_init_manager = "systemd" VIRTUAL-RUNTIME_dev_manager = "systemd" DISTRO_FEATURES_BACKFILL_CONSIDERED = "sysvinit" VIRTUAL-RUNTIME_initscripts = "" IMX_DEFAULT_DISTRO_FEATURES_append = " systemd" COMBINED_FEATURES_append = " wifi bluetooth" DISTRO_FEATURES_append = " bluez5" IMAGE_ROOTFS_SIZE = "1807436" IMAGE_OVERHEAD_FACTOR = "1.0" hostname_pn-base-files = "yoctopi3" INHERIT_append = " extrausers" EXTRA_USERS_PARAMS = " \ useradd -P raspberry -G sudo -s /bin/bash pi; \ usermod -P rootuser -s /sbin/nologin root; \ " IMAGE_INSTALL_append = " tzdata" DEFAULT_TIMEZONE = "Asia/Tokyo" ROOT_HOME = "/root" CMDLINE_remove = "root=/dev/mmcblk0p2" CMDLINE_append = "root=/dev/sda2" CMDLINE_append = " cgroup_enable=memory cgroup_memory=1" GPU_MEM = "16" ENABLE_I2C = "1" ENABLE_SPI_BUS = "1" DL_DIR ?= "~/download" SSTATE_DIR ?= "~/sstate" DISTRO ?= "poky" PACKAGE_CLASSES ?= "package_rpm" EXTRA_IMAGE_FEATURES ?= "debug-tweaks" USER_CLASSES ?= "buildstats image-mklibs image-prelink" PATCHRESOLVE = "noop" BB_DISKMON_DIRS ??= "\ STOPTASKS,${TMPDIR},1G,100K \ STOPTASKS,${DL_DIR},1G,100K \ STOPTASKS,${SSTATE_DIR},1G,100K \ STOPTASKS,/tmp,100M,100K \ ABORT,${TMPDIR},100M,1K \ ABORT,${DL_DIR},100M,1K \ ABORT,${SSTATE_DIR},100M,1K \ ABORT,/tmp,10M,1K" PACKAGECONFIG_append_pn-qemu-system-native = " sdl" CONF_VERSION = "1" IMAGE_FEATURES_append = " package-management" IMAGE_FEATURES_append = " ssh-server-openssh" IMAGE_FEATURES_append = " nfs-client nfs-server" IMAGE_INSTALL_append = " bash sudo" IMAGE_INSTALL_append = " openssh openssh-sftp-server" IMAGE_INSTALL_append = " acpid acpitool" IMAGE_INSTALL_append = " vim vim-tiny" IMAGE_INSTALL_append = " avahi-daemon" IMAGE_INSTALL_append = " util-linux usbutils" IMAGE_INSTALL_append = " net-tools iproute2" IMAGE_INSTALL_append = " wget curl python3-pip" IMAGE_INSTALL_append = " i2c-tools python-smbus bridge-utils hostapd" IMAGE_INSTALL_append = " linux-firmware-rpidistro-bcm43455" IMAGE_INSTALL_append = " wpa-supplicant iw bluez5"
-
-
レイヤー
bblayers.confの設定
-
レイヤー追加
ダウンロードした各ソースを登録
$ bitbake-layers add-layer ../../meta-raspberrypi $ bitbake-layers add-layer ../../meta-openembedded/meta-oe $ bitbake-layers add-layer ../../meta-openembedded/meta-networking $ bitbake-layers add-layer ../../meta-openembedded/meta-filesystems $ bitbake-layers add-layer ../../meta-openembedded/meta-webserver $ bitbake-layers add-layer ../../meta-openembedded/meta-multimedia $ bitbake-layers add-layer ../../meta-openembedded/meta-initramfs $ bitbake-layers add-layer ../../meta-openembedded/meta-perl $ bitbake-layers add-layer ../../meta-openembedded/meta-python
-
カスタムレイヤー追加
初期状態でデフォルトから変更したい設定などをレイヤー・レシピ化
-
初期設定
-
レイヤー作成
bitbake-layers create-layer ../sources/meta-local-bb
-
レイヤー追加
bitbake-layers add-layer ../sources/meta-local-bb
-
-
基本設定(base-files)
-
差分ファイル作成
基本設定に対する以下の変更を行う
- /usr/local以下のディレクトリを作成する
- ユーザーデフォルトプロファイルを変更する
標準ではsbin系がPATHに設定されないことへの対処
標準ではsudoのコマンドをTABで補完出来ないことへの対処
$ mkdir -p ../sources/meta-local-bb/recipes-core/base-files/files
../sources/meta-local-bb/recipes-core/base-files/base-files_%.bbappend
base-files_%.bbappendFILESEXTRAPATHS_prepend := "${THISDIR}/files:" SRC_URI += " \ file://dot.profile \ " do_install_append () { install -d ${D}/usr/local/bin install -d ${D}/usr/local/etc install -d ${D}/usr/local/include install -d ${D}/usr/local/lib install -d ${D}/usr/local/sbin install -d ${D}/usr/local/share install -d ${D}/usr/local/src install -d ${D}${sysconfdir}/skel install -m 0755 ${WORKDIR}/dot.profile ${D}${sysconfdir}/skel/.profile }
../sources/meta-local-bb/recipes-core/base-files/files/dot.profile
dot.profile# ~/.profile: executed by Bourne-compatible login shells. if [ -f ~/.bashrc ]; then . ~/.bashrc fi # path set by /etc/profile export PATH="/sbin:/usr/sbin:/usr/local/sbin:$PATH" complete -cf sudo # Might fail after "su - myuser" when /dev/tty* is not writable by "myuser". mesg n 2>/dev/null
-
-
sudo設定(sudo)
-
差分ファイル作成
標準ではrootユーザーのみsudo可能になっている
/etc/sudoers.d/配下にファイルを追加し、admin/sudoグループにもsudoを許可$ mkdir -p ../sources/meta-local-bb/recipes-core/sudo/files
../sources/meta-local-bb/recipes-core/sudo/sudo_%.bbappend
sudo_%.bbappendFILESEXTRAPATHS_prepend := "${THISDIR}/files:" SRC_URI += " \ file://01-sudoer \ " do_install_append() { install -d ${D}${sysconfdir}/sudoers.d install -m 0644 ${WORKDIR}/01-sudoer ${D}${sysconfdir}/sudoers.d/01-sudoer }
../sources/meta-local-bb/recipes-core/sudo/files/01-sudoer
01-sudoer# Members of the admin group may gain root privileges %admin ALL=(ALL) ALL # Allow members of group sudo to execute any command %sudo ALL=(ALL) ALL
-
-
-
ビルド
-
ビルドするイメージ
raspberry piで動作するイメージは以下の中から選ぶ
-
CUI
core-image-base
-
GUI(X11)
core-image-sato
-
GUI(Wayland/Weston)
core-image-weston
※起動確認以降の手順はcore-image-baseで進める。
そのほかにcore-image-minimalを選択出来るが、カーネルモジュールが取り込まれず、GPIOなどの使用に支障が出る模様。
conf/local.confに以下の設定を追加すればおおよそのモジュールは取り込まれる。MACHINE_ESSENTIAL_EXTRA_RRECOMMENDS += "kernel-modules"
core-image-baseと差分がほぼなくなるので積極的に選択する理由はない。
また、core-image-satoはコンポーネントgstreamerの依存パッケージ「faad2」のライセンスがcommercialとなっている、このライセンスを許容するためにconf/local.confに以下の設定を追加する必要がある。LICENSE_FLAGS_WHITELIST += "commercial"
※core-image-westonはGUIが起動しなかった。
-
-
core-image-baseをビルド
以下コマンドでビルドを実施$ bitbake core-image-base
以下のイメージが作成される
$ ls tmp/deploy/images/raspberrypi3-64 ・・・ core-image-base-raspberrypi3-64.rpi-sdimg (シンボリックリンク) core-image-base-raspberrypi3-64-<yyyyMMddHHmmss>.rootfs.rpi-sdimg ・・・
-
core-image-satoをビルド
以下コマンドでビルドを実施$ bitbake core-image-sato
以下のイメージが作成される
$ ls tmp/deploy/images/raspberrypi3-64 ・・・ core-image-sato-raspberrypi3-64.rpi-sdimg (シンボリックリンク) core-image-sato-raspberrypi3-64-<yyyyMMddHHmmss>.rootfs.rpi-sdimg ・・・
-
core-image-westonをビルド
以下コマンドでビルドを実施$ bitbake core-image-weston
以下のイメージが作成される
$ ls tmp/deploy/images/raspberrypi3-64 ・・・ core-image-weston-raspberrypi3-64.rpi-sdimg (シンボリックリンク) core-image-weston-raspberrypi3-64-<yyyyMMddHHmmss>.rootfs.rpi-sdimg ・・・
起動確認
-
balenaEtcherやddコマンドを使用して作成したイメージをメディアに書き込む。
USBからのブート用の場合はUSBメモリ・USB-SSDなどUSB接続のストレージに、SDカード用イメージであればSDカードに書き込む。
-
Raspberry Piにメディアを接続し、有線LANを接続して電源を投入する。
-
起動が完了するまで待って、sshコマンドでアクセスする。
ssh pi@yoctopi3.local
pi@yoctopi3.localの部分は、conf/local.confで設定したパラメータを使い、「<ユーザー名>@<ホスト名>.local」とする。
(windows10 1809以降であればopensshが取り込まれているため、powershellやコマンドプロンプトからでも上記コマンドでアクセス可能)
powershellで実行すると以下の様になる。PS C:\Users\ragna> ssh pi@yoctopi3.local The authenticity of host 'yoctopi3.local (2400:4053:c081:2d00:ba27:ebff:fe26:5877)' can't be established. ECDSA key fingerprint is SHA256:Wvo4trcK8bp79pVZkl3JASKZI829Rt6k4kfQaqNnM/U. Are you sure you want to continue connecting (yes/no)? <-yesを入力 Warning: Permanently added 'yoctopi3.local,2400:4053:c081:2d00:ba27:ebff:fe26:5877' (ECDSA) to the list of known hosts. pi@yoctopi3.local's password: <-パスワード[raspberry]を入力 yoctopi3:~$
-
sudoが有効である事とタイムゾーンがJSTになっている事を確認
以下コマンドで確認yoctopi3:~$ sudo date Password: <-パスワード[raspberry]を入力 Thu Mar 26 00:56:01 JST 2020 <-現在時刻がJSTで表示される事を確認 yoctopi3:~$
現在時刻は「systemd-timesyncd」サービスによって、NTPで時刻合わせが行われる。
-
ネットワーク設定変更
固定IPアドレス設定とホストネームの変更方法は以下になる-
固定IP化
systemd-networkのデフォルト設定ファイルを/etc/systemd/network/にコピーして編集
[Network]部分を修正$ sudo cp /lib/systemd/network/80-wired.network /etc/systemd/network/ $ sudo vi /etc/systemd/network/80-wired.network [Match] Name=en* eth* KernelCommandLine=!nfsroot [Network] DNS=192.168.25.1 Address=192.168.25.99/24 Gateway=192.168.25.1 [DHCP] RouteMetric=10 ClientIdentifier=mac
設定変更を読み込み、サービスを再起動
$ sudo systemctl daemon-reload $ sudo systemctl restart systemd-networkd
sshが切断されるので、再接続する。
ネットワークを確認$ ip a ・・・ 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether b8:27:eb:26:58:77 brd ff:ff:ff:ff:ff:ff inet 192.168.25.99/24 brd 192.168.25.255 scope global eth0 valid_lft forever preferred_lft forever inet6 2400:4053:c081:2d00:ba27:ebff:fe26:5877/64 scope global dynamic mngtmpaddr noprefixroute valid_lft 2591944sec preferred_lft 604744sec inet6 fe80::ba27:ebff:fe26:5877/64 scope link valid_lft forever preferred_lft forever ・・・
-
ホスト名変更
hostnamectlコマンドを使用する
「yoctopi3」から「yoctopi3-master」に変更yoctopi3:~$ hostname yoctopi3 yoctopi3:~$ sudo hostnamectl set-hostname yoctopi3-master yoctopi3:~$ hostname yoctopi3-master
シェルを再接続
yoctopi3-master:~$ hostname yoctopi3-master
-