OverlayFS를 올바르게 사용하여 루트 파일 시스템을 보호하려면 어떻게 해야 합니까?
SD 카드에서 부팅하고 실행하는 내장 시스템이 있습니다. 갑작스러운 정전이 발생하므로 루트 파일 시스템을 보호하고 싶습니다.파일 시스템 덮어쓰기가장 간단한 해결책처럼 보이지만 내가 찾은 예제에는 일반적으로 루트 파일 시스템이 포함되지 않거나 tmpfs를 사용하지 않는데, 이는 메모리가 거의 없기 때문에 나에게 좋지 않습니다.
저는 CONFIG_OVERLAY_FS=y
Linux 커널 4.4.0을 사용하고 있습니다. 내 파일 시스템은 xenial-base-armhf.tar.gz
끝났습니다 apt install -y overlayroot
.
내 SD 카드는 다음과 같습니다
# fdisk -l /dev/mmcblk1
Disk /dev/mmcblk1: 29 GiB, 31104958464 bytes, 60751872 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x7f56a0ab
Device Boot Start End Sectors Size Id Type
/dev/mmcblk1p1 * 2048 1050623 1048576 512M c W95 FAT32 (LBA)
/dev/mmcblk1p2 1050624 1052671 2048 1M da Non-FS data
/dev/mmcblk1p3 1052672 7344127 6291456 3G 83 Linux
/dev/mmcblk1p4 7344128 60751871 53407744 25.5G 5 Extended
/dev/mmcblk1p5 7346176 13637631 6291456 3G 83 Linux
/dev/mmcblk1p6 13639680 60751871 47112192 22.5G 83 Linux
OverlayFS를 생성하기 전에 모든 것이 다음과 같이 설치됩니다.
# mount
/dev/mmcblk1p3 on / type ext4 (rw,noatime,data=ordered)
devtmpfs on /dev type devtmpfs (rw,relatime,size=170440k,nr_inodes=42610,mode=755)
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime)
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev)
devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620)
tmpfs on /run type tmpfs (rw,nosuid,nodev,mode=755)
tmpfs on /run/lock type tmpfs (rw,nosuid,nodev,noexec,relatime,size=5120k)
tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,mode=755)
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/lib/systemd/systemd- cgroups-agent,name=systemd)
configfs on /sys/kernel/config type configfs (rw,relatime)
tmpfs on /run/user/0 type tmpfs (rw,nosuid,nodev,relatime,size=35752k,mode=700)
/dev/mmcblk1p6 on /opt type ext4 (rw,noatime,data=ordered)
/dev/mmcblk1p5 on /overlay type ext4 (rw,noatime,data=ordered)
/dev/mmcblk1p5
내 계획은 이를 오버레이 파일 시스템 으로 사용하여 /overlay
.
# tree /overlay
/overlay
├── lost+found
├── root-fs
└── work
내가 뭔가 잘못하고 있거나 다음과 같은 이유로 구성 문제가 있습니다.
# mount -t overlay overlay -o lowerdir=/,upperdir=/overlay/root-fs,workdir=/overlay/work /
# mount
/dev/mmcblk1p3 on / type ext4 (rw,noatime,data=ordered)
devtmpfs on /dev type devtmpfs (rw,relatime,size=170440k,nr_inodes=42610,mode=755)
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime)
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev)
devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620)
tmpfs on /run type tmpfs (rw,nosuid,nodev,mode=755)
tmpfs on /run/lock type tmpfs (rw,nosuid,nodev,noexec,relatime,size=5120k)
tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,mode=755)
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/lib/systemd/systemd-cgroups-agent,name=systemd)
configfs on /sys/kernel/config type configfs (rw,relatime)
tmpfs on /run/user/0 type tmpfs (rw,nosuid,nodev,relatime,size=35752k,mode=700)
/dev/mmcblk1p6 on /opt type ext4 (rw,noatime,data=ordered)
/dev/mmcblk1p5 on /overlay type ext4 (rw,noatime,data=ordered)
overlay on / type overlay (rw,relatime,lowerdir=/,upperdir=/overlay/root-fs,workdir=/overlay/work)
작동하는 것처럼 보이지만 다음과 같은 파일을 생성하면:
# touch /root/test_file_write
그러다가 전원을 끄고 데스크탑에 있는 SD카드를 보니 /dev/mmcblk1p3/root/test_file_write
예상했던 것과는 달랐습니다 /dev/mmcblk1p5/root-fs/root/test_file_write
.
이것이 작동해야합니까?
답변1
이 답변은 내 경험을 바탕으로 한 것이지만 임베디드 장치에는 적용되지 않습니다. 어쩌면 이 설정을 우연히 발견한 사람에게 유용할 수도 있습니다. 특정 상황에 맞게 조정하거나 적어도 한두 가지를 배워야 합니다.
간단한 접근 방식은 루트 파일 시스템을 마운트할 때(initramfs에서, 그렇지 않으면 프로세스를 하이재킹 init
) 해당 위치를 하이재킹하고 거기에 오버레이를 마운트하고 평소대로 계속하는 것입니다. initramfs 없이 마운트하는 경우 /proc
일반 ./sys
init
만약 너라면아니요initramfs를 원하면 Mathieu Maret의 Raspberry Pi에서 이를 수행하는 방법에 대한 링크된 솔루션이 작동해야 합니다. 기본적으로 init
커널 명령줄을 통해 자신만의 프로세스/스크립트를 재정의 할 수 있습니다 . 루트 파일 시스템에서 스크립트를 생성했다고 가정하고 , 부트로더 구성의 커널 부팅 매개변수에 /sbin/init-overlay
이를 추가해야 합니다 .init=/sbin/init-overlay
스크립트 init-overlay
는 제어권을 전달하기 전에 무엇이든 할 수 있습니다 init
. 이 경우 오버레이를 다른 디렉토리에 설치한 다음 chroot
여기에 마운트합니다.
initramfs를 사용하여 이를 수행하는 한 가지 가능한 방법은 /init
루트 파일 시스템을 마운트한 후 initramfs 내의 스크립트를 하이재킹하는 것입니다. 예를 들어, 오버레이 루트를 갖고 싶지만 시스템을 가동한 후 /run/rootfs/ro
원래 마운트 지점에 액세스 하려고 한다고 가정해 보겠습니다 /run/rootfs/rw
(전자는 읽기 전용 루트이고 후자는 수정된 루트입니다) upperdir
. 또한 시스템이 부팅되는 드라이브에 root.squashfs
읽기 전용 루트 파일 시스템이 포함된 파일이 있고 이를 마운트하려고 한다고 가정합니다. /media/drive
편의를 위해 시스템이 가동되어 실행되면 이 드라이브에 다시 액세스 하고 싶다고 가정해 보겠습니다 .
initramfs 스크립트를 하이재킹하는 이유는 궁극적으로 기본 스크립트 명령을 실행하는 미리 만들어진 일부 매개변수를 사용하는 것보다 더 많은 유연성을 제공하기 때문입니다. 따라서 root.squashfs
나중에 마운트할 것이므로 "루트" 파일 시스템이 실제로 발견된 파일 시스템이라는 것을 커널과 통신하려면 부팅 구성을 편집해야 합니다 .
VFAT 파티션의 일반적인 명령은 syslinux.cfg
다음과 같습니다(필요한 경우 UUID 변경).
label linux
linux vmlinuz
append root=UUID=ABCD-1234 rootfstype=vfat rootflags=ro,umask=022,quiet ro quiet splash
initrd initrd.img
이는 이상적이지 않을 수 있는 VFAT 파티션을 배치한다고 가정합니다 root.squashfs
(위에서 root=로 지정해야 하는 것은 포함하거나 root.squashfs
유사한 파티션 또는 파일 시스템(예: 실제 루트 파일 시스템)입니다. 압축됩니다). 그러나 부팅 파티션 자체에 배치한다는 가정하에 설명하고 있습니다.나는 당신이 어떤 종류의 임베디드 시스템을 실행하고 있는지 모르므로 여기서는 스스로 판단해야 합니다.
/init
먼저 스크립트를 수정할 수 있도록 initramfs를 /tmp의 위치로 추출해야 합니다 . 백업을 패키징하기 전에 root
소유권을 적절하게 유지하려면 (수퍼유저)로 이 작업을 수행하는 것을 잊지 마십시오. 수행 방법을 이해한 후에는 아마도 전체 내용을 스크립트로 작성할 수 있을 것입니다. 예를 들어, /tmp/initramfs
편집을 위해 압축을 푸십시오.
mkdir /tmp/initramfs 2>/dev/null; (cd /tmp/initramfs && zcat /initrd.img | sudo cpio -idmv)
이제 기본 스크립트 마운트 루트의 위치를 찾아야 합니다. /tmp/initramfs/init
(루트로 편집)에서 비슷한 것을 찾으십시오 .
maybe_break mount
log_begin_msg "Mounting root file system"
. /scripts/${BOOT}
parse_numeric ${ROOT}
maybe_break mountroot
mountroot
log_end_msg
이것이 어떻게 작동하는지 이해할 필요는 없습니다. 당신이 이해해야 할 것은 이것이 쉘 변수를 통해 root.squashfs
분명히 주어진 마운트 지점에 당신을 포함하는 일반 파일 시스템을 마운트한다는 것입니다.${rootmnt}
즉, 현재 우리가 갖고 있는 것은 ${rootmnt}
VFAT 파티션(또는 root=
명령줄 인수를 통해 지정한 파티션)입니다. 이제 스크립트는 모든 가상 파일 시스템을 ${rootmnt}
마운트 지점으로 이동하는 등의 다른 작업을 수행하므로 모든 사용자 정의 작업을 수행해야 합니다.뒤쪽에위의 코드.
여러분이 해야 할 일은 initramfs에서 위 코드 뒤에 다음과 같은 내용을 삽입하는 것뿐입니다 /init
.
# create some temporary directories under the initramfs's /run
# they will be our mountpoints and such, which will get moved
# by the default script to the actual root filesystem...
mkdir -m 755 /run/rootfs
mount -t tmpfs -o size=90%,mode=755,suid,exec tmpfs /run/rootfs
mkdir -m 755 /run/rootfs/drive /run/rootfs/ro /run/rootfs/rw /run/rootfs/.workdir
# move the original root that was mounted, temporarily
mount -n -o move "${rootmnt}" /run/rootfs/drive
# mount the squashfs and then the overlay to our designated locations
mount -t squashfs -o defaults,ro /run/rootfs/drive/root.squashfs /run/rootfs/ro
mount -t overlay -o lowerdir=/run/rootfs/ro,upperdir=/run/rootfs/rw,workdir=/run/rootfs/.workdir root "${rootmnt}"
# at this point we have our overlay root at ${rootmnt}!
# however, move the drive's filesystem mount to the new root
# this allows it to be accessed afterwards from /media/drive
# NOTE: this assumes you have the /media/drive dir in the root squashfs
mount -n -o move /run/rootfs/drive "${rootmnt}/media/drive"
rm -d /run/rootfs/drive
그게 다야. 스크립트는 평소대로 계속 진행되지만 루트 파일 시스템은 오버레이이므로 그 모든 부분에 쉽게 액세스할 수 있습니다. 그렇단 점 참고해주세요오류 검사 없음overlay
, 위 명령을 추가하거나 모듈이 로드되었는지 확인하는 것은 사용자의 몫입니다 .
이제 initramfs를 패키징하세요.
sudo sh -c 'cd /tmp/initramfs && find . -print0 | cpio --null -ov --format=newc' | gzip -9 > /tmp/initrd.img
그리고 /tmp/initrd.img를 SD 카드나 다른 곳에 복사하세요. VFAT 파티션의 루트 디렉터리에 배치하는 것을 잊지 마십시오 root.squashfs
. 물론 쉽게 사용자 정의할 수 있고 그럴 필요도 없습니다. 이것은 syslinux(또는 UEFI 부팅)를 수행하는 "가장 쉬운" 방법일 뿐이며, 결코 최선의 방법은 아닙니다.
죄송합니다. 임베디드 장치를 요청하신 것은 알고 있지만 부팅 프로세스가 어떻게 작동하는지 모르겠습니다. 방금 x86의 예를 사용했지만 그 부분은 덜 중요합니다(일부만 syslinux.cfg
).
참고하세요overlayfs
이렇게 하면 쓰기 가능한 부분이 tmpfs
원하는 대로 만들어집니다. 그러나 그것은변경하기 쉬운, 위 내용을 보면 /run/rootfs
쓰고 싶은 곳에 tmpfs 대신 다른 것을 설치하면 됩니다.
답변2
한 가지 해결책은 initramfs를 사용하여 rootfs 및 overlayfs를 마운트하는 것입니다.
당신은 볼 수 있습니다Raspberry Pi에서 수행되는 방법
또는 ARM 장치를 사용하지 않는 경우우분투 overlayroot
패키지
답변3
디렉터리에 대한 읽기 전용 "보호" 재정의
전체 루트 파일 시스템에서 작동하도록 할 수 없거나 /boot/inird
솔루션을 사용할 수 없습니다. 하지만 특정 폴더에서 작동하도록 만들 수는 있습니다.
보드/시스템이 "생산" 준비가 되면 아래 코드를 실행해야 합니다.필요에 맞게 조정할 수 있습니다.내 사건은 SOC 보드를 운영하고 있습니다네트워크 비디오 레코더(네트워크 비디오 레코더).
이 코드는 '보호하다' 시스템의 모든 디렉터리. 디렉토리에 많은 I/O가 있다는 것을 알고 있습니다. 그리고 당신은 로그 등과 같이 거기에 쓰여진 내용에 관심이 없습니다.
"보호" /var
폴더 예
저는 /dev/shm
ramdisk 폴더를 사용합니다. 배포판에 없으면 RAM 디스크를 직접 마운트해야 합니다(tmpfs 등).
# create folders needed by overlay filesystem on /dev/shm (RAM)
mkdir -p /dev/shm/var_upper /dev/shm/var_workdir /dev/shm/var_overlay
mkdir -p /var_
# since /var will be 'hidden' by overlay mouting 'over' it
# we need it 'visible' somewhere to be usable as lowerdir
# mount --bind does that to /var_
mount --bind /var /var_
sudo mount -t overlay overlay -o lowerdir=/var_,upperdir=/dev/shm/var_upper,workdir=/dev/shm/var_workdir /var
약간의 설명
오버레이는 상위 디렉토리가 보호되는 연합 파일 시스템(또는 디렉토리 트리)을 설치합니다. 이 예에서는 /var
읽기 전용 으로 만듭니다 . 쓰기는 RAM에서만 이루어지므로 /dev/shm
재부팅 시 로그 등이 손실됩니다. 바인딩 해제는 자동으로 수행되고 모든 것이 기본 위치로 돌아가므로 재부팅해도 안전합니다. 읽기 전용 "보호"가 필요한 다른 폴더에 복사할 수 있습니다.
나의 초기 검색은 SOC 보드의 전원이 끊길 때 SD 카드 손상을 방지하는 솔루션을 찾는 것이었습니다.