Files
Deploy-Laboratory/docs/01-04-armv7-nfs服务安装.md
2026-03-29 09:08:01 +08:00

8.8 KiB
Raw Blame History

01-04-armv7 NFS 服务安装

本文只讲 armv7 主机侧 NFS 服务安装与导出配置,目标是把 /sdcard 作为 NFS 共享目录导出给 K3s 节点使用。

TL;DR

  • 自动化验收./ansible/bin/verify.sh run 01-04
  • 关键前置:按本文「前置条件」准备环境变量/Secret/入口 IP
  • 成功判据:达到本文「预期」且 playbook 断言通过
  • 排障:见本文「排障」

前置条件

  • 已完成 01-03-armv7-standalone-docker.md
  • armv7 与 K3s 节点网络互通
  • armv7 上存在挂载点 /sdcard(先用 mount | grep /sdcard 确认)

操作步骤

  1. 在 armv7 安装 NFS 服务(nfs-utilsnfs-kernel-server
  2. /sdcard 目录配置为导出目录
  3. 配置 /etc/exports
  4. 使导出生效并启用开机自启
  5. (可选)配置防火墙

1) 安装 NFS 服务(按发行版二选一)

# RHEL/CentOS/Fedora
sudo dnf install -y nfs-utils
sudo systemctl enable --now nfs-server

# Debian/Ubuntu
# sudo apt update
# sudo apt install -y nfs-kernel-server
# sudo systemctl enable --now nfs-kernel-server

2) 确认 /sdcard 可用

mount | grep /sdcard
ls -ld /sdcard

如果 /sdcard 是外置存储SD 卡/U 盘),建议先确认它已在系统启动后自动挂载,再做 NFS 导出。

3) 配置 /etc/exports 导出 /sdcard

示例(允许 192.168.2.0/24 网段读写):

echo "/sdcard 192.168.2.0/24(rw,sync,no_subtree_check,no_root_squash)" | sudo tee /etc/exports
sudo exportfs -rav

参数说明(常用):

  • rw:允许读写
  • sync:同步写入,数据更稳妥
  • no_subtree_check:减少子目录检查开销
  • no_root_squash:客户端 root 保持 root 权限(仅在可信内网使用)

4) 防火墙(可选,按环境)

如果 armv7 启用了 firewalld

sudo firewall-cmd --add-service=nfs --permanent
sudo firewall-cmd --add-service=mountd --permanent
sudo firewall-cmd --add-service=rpc-bind --permanent
sudo firewall-cmd --reload

如果是 Debian/Ubuntu + UFW请按实际策略放行 NFS 相关端口/服务。

验证命令

showmount -e localhost
sudo exportfs -v
sudo systemctl status nfs-server --no-pager || sudo systemctl status nfs-kernel-server --no-pager

预期

  • showmount -e 可看到导出目录 /sdcard
  • NFS 服务为运行状态

客户端快速验证(在任一 K3s 节点)

sudo mkdir -p /mnt/nfs-sdcard-test
sudo mount -t nfs <armv7-ip>:/sdcard /mnt/nfs-sdcard-test
df -h | grep nfs-sdcard-test
ls -la /mnt/nfs-sdcard-test

若内网 DNS/主机名不可解析,请直接使用 armv7 的内网 IP例如 192.168.2.22:/sdcard)。

验证完成后可卸载:

sudo umount /mnt/nfs-sdcard-test

本次实机验证记录onecloud -> ylc61

  • 服务端onecloud
    • showmount -e localhost 返回 /sdcard 192.168.2.0/24
    • exportfs -v 显示 /sdcard 已按配置导出
  • 客户端ylc61
    • mount -t nfs 192.168.2.22:/sdcard /mnt/nfs-sdcard-test 成功
    • 可写入测试文件 .nfs_write_test
    • umount /mnt/nfs-sdcard-test 成功

NFS 安全验证与加固

先明确:默认 NFS 没有“用户名/密码登录”

当前这种 /etc/exports 用法(如 192.168.2.0/24(...))主要基于:

  • 客户端来源 IP/网段控制
  • UID/GID 映射(root_squash/all_squash

它不是“账号密码”或“密钥登录”模型。若需要强身份认证与加密,应使用 NFSv4 + Kerberos见下文

基础安全加固(内网实用版)

先解释你关心的几个参数(核心差异):

  • no_root_squash:客户端 root 在服务端仍是 root权限非常大不推荐默认使用
  • root_squash:客户端 root 会被压缩为匿名用户(更安全,推荐默认)。
  • all_squash:不仅 root连普通用户也统一映射为匿名用户最“收敛”但权限控制最粗

你说的“通常 NFS 只是数据目录,普通读写就够了”,这个判断是对的。
对大多数家庭实验室,优先 root_squash 即可,不必一上来 no_root_squash

推荐配置 A默认推荐保留普通用户语义仅压缩 root

echo "/sdcard 192.168.2.0/24(rw,sync,no_subtree_check,root_squash)" | sudo tee /etc/exports
sudo exportfs -rav

适用:一般数据目录读写场景,既降低 root 风险,又不过度收紧普通用户行为。

若切到 root_squash 后客户端出现 Permission denied,通常是导出目录权限还停留在 root:root。可在服务端先调整目录属主与权限(按你的风险接受度选择更细粒度权限):

sudo chown nobody:nogroup /sdcard
sudo chmod 0777 /sdcard

说明:这是“保证先可写”的快速做法。更严格场景建议用更小权限(例如按业务 UID/GID 精细授权),不要长期依赖 0777

更小权限的实操示例(推荐)

多容器/多应用共享 NFS 时,不建议只改 /sdcard 根目录权限;更推荐“根目录只做入口,每个应用单独子目录分权”。

示例:应用 A 用 UID/GID=1000,应用 B 用 UID/GID=1001

# 1) 根目录:保守权限(可遍历,不建议直接 0777
sudo chown root:root /sdcard
sudo chmod 0755 /sdcard

# 2) 应用A子目录
sudo mkdir -p /sdcard/app-a
sudo chown 1000:1000 /sdcard/app-a
sudo chmod 0770 /sdcard/app-a

# 3) 应用B子目录
sudo mkdir -p /sdcard/app-b
sudo chown 1001:1001 /sdcard/app-b
sudo chmod 0770 /sdcard/app-b

如果你选择 all_squash,再配合匿名映射到同一业务账号:

echo "/sdcard 192.168.2.0/24(rw,sync,no_subtree_check,root_squash,all_squash,anonuid=1000,anongid=1000)" | sudo tee /etc/exports
sudo exportfs -rav

验证(服务端):

sudo exportfs -v
ls -ldn /sdcard
ls -ldn /sdcard/app-a /sdcard/app-b

你应能看到:

  • exportfs -v 中导出参数已是目标策略(如 root_squash / all_squash,anonuid=1000
  • 导出参数符合目标策略
  • 各应用子目录的属主属组与业务 UID/GID 一致(如 app-a1000:1000

在 K8s Pod 侧,建议与之对应:

  • 应用 ArunAsUser/runAsGroup/fsGroup 使用 1000
  • 应用 BrunAsUser/runAsGroup/fsGroup 使用 1001

这样比把 /sdcard 全盘 0777 更可控:权限边界在“每个业务子目录”,不同应用互不踩权限。

推荐配置 B更严格所有用户都匿名

echo "/sdcard 192.168.2.0/24(rw,sync,no_subtree_check,root_squash,all_squash,anonuid=65534,anongid=65534)" | sudo tee /etc/exports
sudo exportfs -rav

“所有用户都匿名”的含义与影响:

  • 含义:客户端不论是 root 还是普通用户,服务端都按同一个匿名身份(通常 nobody:nogroup)处理。
  • 影响:权限简单统一,但会丢失“按用户区分权限”的能力;某些应用可能因属主/权限不匹配而报错。
  • 建议:仅在你明确要“统一身份写入”时启用。

不推荐长期保留(除非明确必须)

echo "/sdcard 192.168.2.0/24(rw,sync,no_subtree_check,no_root_squash)" | sudo tee /etc/exports
sudo exportfs -rav

no_root_squash 只建议临时排障或已做严格网络隔离时短期使用。

配套建议:

  • 防火墙只放行必要客户端 IP不要整段网段
  • NFS 服务只暴露在可信内网/VLAN
  • 客户端挂载可加 nosuid,nodev,noexec(按业务兼容性评估)

安全验证命令(基础版)

# 服务端:确认导出参数
sudo exportfs -v

# 客户端:确认挂载参数
mount | grep nfs

核对点:

  • 采用推荐配置 A/B 时,exportfs -v 中不应出现 no_root_squash
  • 挂载后普通读写符合预期
  • 若启用 all_squash,需额外确认应用对匿名 UID/GID 的权限兼容性

强认证路线进阶NFSv4 + Kerberos

如果你需要“身份认证/完整性/加密”而不是仅靠 IP 白名单:

  • 使用 sec=krb5(认证)
  • sec=krb5i(认证 + 完整性)
  • sec=krb5p(认证 + 完整性 + 加密,安全最高)

这条路线需要额外建设 KDC、principal、keytab、时钟同步复杂度明显高于内网基础版家庭实验室通常先做“基础加固版”再按需要升级。

与 K3s 对接(入口)

在 K3s 里使用 NFS通常不需要先把 NFS 手工挂到每台节点主机。
详细做法Pod 直挂 / PV+PVC请见03-06-k3s-使用nfs存储.md

下一步

  • 03-06-k3s-使用nfs存储.md

排障

  • 先看 playbook 输出:失败时先定位是 deploy/wait/http_check 哪一步。
  • 集群侧总览kubectl get nodes -o widekubectl -n kube-system get pods -o wide
  • 事件与日志kubectl -n <ns> describe ...kubectl -n <ns> logs ... --tail=200