打造更持久的樹梅派

導讀

寫了那麼多期斐訊k3,想必諸位都視覺疲勞了,今天終於輪到樹梅派上場了。要想樹梅派長久穩定的運行,且可擴展能力強,可以把它打形成網盤,那麼擴展存儲是必然的,同時樹梅派最大的毛病就是意外斷電後文件系統易損壞,須要手動修復,那有沒有一勞永逸的法子,答案是確定的,接着看就是!linux

設計推導

示例硬件原料git

  • 樹梅派3B+
  • USB 無源移動機械硬盤
  • 有源 USB HUB

外置存儲建議諸位採用有源 usb 移動機械硬盤,容量大且價格適宜,無源的話能夠用有源 usb hub 轉接,就像易霧君這樣的github

image

設計暢想redis

我們這次是沒有準備 TF 卡的,移動文件也需放置於移動設備上,能夠考慮分三個區足矣,一個啓動分區,一個系統分區,一個數據分區。docker

爲了防止失竊形成數據泄漏,還要將數據分區進行加密。bash

系統分區做爲一個基礎支持性的分區,最好是不讓它變動,固化它,全部須要變動的數據只發生數據分區,這卻是能夠,系統分區咱給它用上 overlayfs ,數據分區呢主打跑 docker ,在部署階段設置讓系統分區可以寫入,將 docker 的存儲目錄改到數據分區,這樣就能確保 docker 建立的容器都寫在數據分區了,基本不與系統分區有何干系,最終部署好之後就可直接固化系統分區了,之後須要增長docker容器呀,就大膽操做吧。app

操做系統選型
樹梅派 3B+ 自己是基於 ARM 64 位的處理器,果斷選用 64 位的操做系統,易霧君用的是由 openfans 出品的 Debian-Pi-Aarch64 ,尤爲好用,項目地址: https://github.com/openfans-c... ,支持 2Bv1.2, 3B, 3B+, 3A+, 4B 衆多系列。dom

USB 啓動問題socket

  • 樹梅派 3B 是沒法直接從 usb 存儲啓動的,能夠參考《徹底拋棄TF卡,從 USB 啓動樹莓派》,進行設置,完成設置後,後邊就能夠不須要 TF 卡了
  • 樹梅派 3B+ 及以上則支持直接從 USB 存儲啓動系統

操練時刻

系統鏡像準備

易霧君採用了這個固件 2020-06-22-OPENFANS-Debian-Buster-Aarch64-ext4-v2020-2.0-U4-Release.img.xzide

  • 資源連接:https://pan.evling.me/s/g9pkS...
  • 訪問密碼:在公衆號 易霧山莊 回覆 獲取密碼 便可
  • 能夠到上面提供的項目地址那裏去下載,可能網速會比較慢而已

硬盤分區

這裏咱就不採用直接將鏡像 dd 到硬盤,而是先按照以下設定分好區。

  • 硬盤總大小:500G
  • 啓動分區:512MB fat32
  • 系統分區:10GB ext4
  • 數據分區:剩下的全部

易霧君使用 gparted 進行了分區及格式化,諸位也可以使用其餘工具,如 fdisk 等。第三個分區能夠暫時不用格式化,由於咱裝好系統以後打算對它進行加密處理。

image

固件刷寫

解壓 xz 壓縮形式的鏡像文件

xz -d 2020-06-22-OPENFANS-Debian-Buster-Aarch64-ext4-v2020-2.0-U4-Release.img.xz

轉換起始偏移

image

  • 8192 * 512 = 4194304
  • 524288 * 512 = 268435456

掛載 boot 分區並將文件同步到移動硬盤的 boot 分區。

mkdir /tmp/boot
mount -o loop,offset=4194304 ./2020-06-22-OPENFANS-Debian-Buster-Aarch64-ext4-v2020-2.0-U4-Release.img /tmp/boot
rsync -Pa /tmp/boot/ /media/root/28CD-91D9/
sync

掛載 system 分區並將文件同步到移動硬盤的 system 分區。

umount /tmp/boot
mkdir /tmp/system
mount -o loop,offset=268435456 ./2020-06-22-OPENFANS-Debian-Buster-Aarch64-ext4-v2020-2.0-U4-Release.img /tmp/system
sync
umount /tmp/system

更新新環境的分區 id ,先查看移動硬盤的分區 id 值

root@lab:/tmp# blkid
/dev/sdc1: UUID="28CD-91D9" TYPE="vfat" PARTUUID="87e06b5e-01"
/dev/sdc2: UUID="069d1748-472d-4ecb-a1c7-27d93234bf16" TYPE="ext4" PARTUUID="87e06b5e-02"
/dev/sdc3: UUID="0a4a8d70-6c7a-4efa-b941-1b7d28ac2fad" TYPE="ext4" PARTUUID="87e06b5e-03"

獲得 87e06b5e ,更新 boot 分區下文件/media/root/28CD-91D9/cmdline.txt 及系統分區下文件 /media/root/069d1748-472d-4ecb-a1c7-27d93234bf16/etc/fstab 對應的值。

image

正式環境初始化配置

這時拔出 usb 移動硬盤插到樹梅派上去,加電稍等幾分鐘便可進入系統。

image

加密數據分區

apt update && apt install -y cryptsetup 
cryptsetup luksFormat /dev/sda3
# 按照提示輸入大寫的 YES ,緊接着輸入加密磁盤的口令
dd if=/dev/urandom of=/root/enc.key bs=1 count=4096
cryptsetup luksAddKey /dev/sda3 /root/enc.key
# 輸入你設定的磁盤口令進行受權
cryptsetup luksOpen /dev/sda3 data -d /root/enc.key 
mkfs.ext4 /dev/mapper/data
mkdir /data
mount /dev/mapper/data /data

開機自動掛載加密的數據分區

獲取數據分區的 uuid 值 57978b4c-b5ac-4c9e-80ca-13aa34d0c6ab

image

/etc/crypttab 增長以下一行

data    UUID=57978b4c-b5ac-4c9e-80ca-13aa34d0c6ab      /root/enc.key

/etc/fstab 增長以下一行

/dev/mapper/data /data ext4 defaults 0 0

配置交換分區,大小設定爲 8 GB

fallocate -l 8G /data/swapfile
chmod 600 /data/swapfile
mkswap /data/swapfile
swapon /data/swapfile

/etc/fstab 下交換分區文件的路徑更新爲新路徑 /data/swapfile,交換分區那行應形如

/data/swapfile swap swap defaults 0 0

docker 配置

安裝 docker-compose

apt update && apt install docker-compose

修改 docker 的存儲目錄到 /data/docker ,在系統服務 /lib/systemd/system/docker.service 增長一個啓動參數 --graph=/data/docker

[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
BindsTo=containerd.service
After=network-online.target firewalld.service containerd.service
Wants=network-online.target
Requires=docker.socket

[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd -H fd:// --graph=/data/docker --containerd=/run/containerd/containerd.sock
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always

# Note that StartLimit* options were moved from "Service" to "Unit" in systemd 229.
# Both the old, and new location are accepted by systemd 229 and up, so using the old location
# to make them work for either version of systemd.
StartLimitBurst=3

# Note that StartLimitInterval was renamed to StartLimitIntervalSec in systemd 230.
# Both the old, and new name are accepted by systemd 230 and up, so using the old name to make
# this option work for either version of systemd.
StartLimitInterval=60s

# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity

# Comment TasksMax if your systemd version does not support it.
# Only systemd 226 and above support this option.
TasksMax=infinity

# set delegate yes so that systemd does not reset the cgroups of docker containers
Delegate=yes

# kill only the docker process, not all processes in the cgroup
KillMode=process

[Install]
WantedBy=multi-user.target

重啓 docker 服務

systemctl restart docker

固化腳本

根據前面的需求,咱只但願對系統分區,即 /dev/sda2 進行固化,新增腳本文件/sbin/overlayRoot.sh,注意變量 rootDev 需指定爲你實際的分區。

#!/bin/sh
#  Read-only Root-FS for Raspian using overlayfs
#  Version 1.0
#
#  Created 2017 by Pascal Suter @ DALCO AG, Switzerland
#  to work on Raspian as custom init script
#  (raspbian does not use an initramfs on boot)
#
#  Modified 2017-Apr-21 by Tony McBeardsley
#
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see
#    <http://www.gnu.org/licenses/>.
#
#
#  Tested with Raspbian mini, 2017-01-11
#
#  This script will mount the root filesystem read-only and overlay it with a temporary tempfs
#  which is read-write mounted. This is done using the overlayFS which is part of the linux kernel
#  since version 3.18.
#  when this script is in use, all changes made to anywhere in the root filesystem mount will be lost
#  upon reboot of the system. The SD card will only be accessed as read-only drive, which significantly
#  helps to prolong its life and prevent filesystem coruption in environments where the system is usually
#  not shut down properly
#
#  Install:
#  copy this script to /sbin/overlayRoot.sh and add "init=/sbin/overlayRoot.sh" to the cmdline.txt
#  file in the raspbian image's boot partition.
#  I strongly recommend to disable swapping before using this. it will work with swap but that just does
#  not make sens as the swap file will be stored in the tempfs which again resides in the ram.
#  run these commands on the booted raspberry pi BEFORE you set the init=/sbin/overlayRoot.sh boot option:
#  sudo dphys-swapfile swapoff
#  sudo dphys-swapfile uninstall
#  sudo update-rc.d dphys-swapfile remove
#
#  To install software, run upgrades and do other changes to the raspberry setup, simply remove the init=
#  entry from the cmdline.txt file and reboot, make the changes, add the init= entry and reboot once more.

fail(){
        echo -e "$1"
        /bin/bash
}


# Load overlay module
modprobe overlay
if [ $? -ne 0 ]; then
    fail "ERROR: missing overlay kernel module"
fi


# Mount /proc
mount -t proc proc /proc
if [ $? -ne 0 ]; then
    fail "ERROR: could not mount proc"
fi


# Create a writable fs on /mnt to then create our mountpoints
mount -t tmpfs inittemp /mnt
if [ $? -ne 0 ]; then
    fail "ERROR: could not create a temporary filesystem to mount the base filesystems for overlayfs"
fi


# Mount a tmpfs under /mnt/rw
mkdir /mnt/rw
mount -t tmpfs root-rw /mnt/rw
if [ $? -ne 0 ]; then
    fail "ERROR: could not create tempfs for upper filesystem"
fi



# Identify root fs device, PARTUUID, mount options and fs type

#rootDev=`blkid -o list | awk '$3 == "/" {print $1}'`
# Changed here(point to / ) in case the cmd above doesn't work # By ChenYang 20171122
rootDev=/dev/sda2
rootPARTUUID=`awk '$2 == "/" {print $1}' /etc/fstab`
rootMountOpt=`awk '$2 == "/" {print $4}' /etc/fstab`
rootFsType=`awk '$2 == "/" {print $3}' /etc/fstab`


# Mount original root filesystem readonly under /mnt/lower
mkdir /mnt/lower
mount -t ${rootFsType} -o ${rootMountOpt},ro ${rootDev} /mnt/lower
if [ $? -ne 0 ]; then
    fail "ERROR: could not ro-mount original root partition"
fi


# Mount the overlay filesystem
mkdir /mnt/rw/upper
mkdir /mnt/rw/work
mkdir /mnt/newroot
mount -t overlay -o lowerdir=/mnt/lower,upperdir=/mnt/rw/upper,workdir=/mnt/rw/work overlayfs-root /mnt/newroot
if [ $? -ne 0 ]; then
    fail "ERROR: could not mount overlayFS"
fi


# Create mountpoints inside the new root filesystem-overlay
mkdir /mnt/newroot/ro
mkdir /mnt/newroot/rw

# Remove root mount from fstab (this is already a non-permanent modification)
grep -v "$rootPARTUUID" /mnt/lower/etc/fstab > /mnt/newroot/etc/fstab
echo "#the original root mount has been removed by overlayRoot.sh" >> /mnt/newroot/etc/fstab
echo "#this is only a temporary modification, the original fstab" >> /mnt/newroot/etc/fstab
echo "#stored on the disk can be found in /ro/etc/fstab" >> /mnt/newroot/etc/fstab


# Change to the new overlay root
cd /mnt/newroot
pivot_root . mnt
exec chroot . sh -c "$(cat <<END

        # Move ro and rw mounts to the new root
        mount --move /mnt/mnt/lower/ /ro
        if [ $? -ne 0 ]; then
            echo "ERROR: could not move ro-root into newroot"
            /bin/bash
        fi
        mount --move /mnt/mnt/rw /rw
        if [ $? -ne 0 ]; then
            echo "ERROR: could not move tempfs rw mount into newroot"
            /bin/bash
        fi

        # Unmount unneeded mounts so we can unmout the old readonly root
        umount /mnt/mnt
        umount /mnt/proc
        umount /mnt/dev
        umount /mnt

        # Continue with regular init
        exec /sbin/init
END
)"

給予執行權限

chmod a+x /sbin/overlayRoot.sh

/boot/cmdline.txt 文件下增長 init=/sbin/overlayRoot.sh,形如

dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=PARTUUID=87e06b5e-02 rootfstype=ext4 elevator=deadline fsck.repair=yes net.ifnames=0 cgroup_enable=1 cgroup_memory=1 cgroup_enable=cpuset cgroup_enable=memory swapaccount=1 zswap.enabled=1 zswap.zpool=z3fold zswap.compressor=lz4 zswap.max_pool_percent=25 rootwait init=/sbin/overlayRoot.sh

爲了後邊有時必須對系統做出更改,咱仍是作個切換可寫只讀模式的命令,如reboot_rw 重啓系統後作出改動,隨後執行 reboot_ro 恢復到只讀模式,省心。定義這兩個函數以下

cat << EOF >> ~/.bashrc
function reboot_rw(){
  sed -i 's/ init=\/sbin\/overlayRoot.sh//g' /boot/cmdline.txt
  reboot
}
function reboot_ro() {
  sed -i 's/\($\)/ init=\/sbin\/overlayRoot.sh/g' /boot/cmdline.txt
  reboot
}
EOF

結語

樹梅派基礎環境弄好了就放心的 24 小時開機吧,能跑個網盤應用、站點、博客應用就很不錯了,敬請期待下篇《樹梅派 docker 跑 kodbox 網盤》

對了對了,更多精彩不要錯過,掃碼關注我喲!諸位有心的話請前往「易霧山莊」公衆號進行多多點贊,點得越兇,那我也更得越猛。要不要告哈嘛,都是準備好的乾貨。

image

參考

相關文章
相關標籤/搜索