摘要 :生产环境里部署企业级数据库时,NFS挂载配置和Shell环境的初始化这两件事特别容易被忽略。本文拿 KingbaseES(KES) 在NFS环境下遇到的一次典型
Operation not permitted报错当引子,把问题的来龙去脉一层层剥开讲清楚,顺便整理了一份 KES安装前的环境检查清单 、一套 NFS存储下的部署策略 ,以及日常运维中 排查Shell脚本报错 的实用技巧。
@[toc]
一、现场什么样?------ KES安装时的诡异报错
1.1 把当时的场景还原一下
有个金融行业的客户在做 KingbaseES 集群部署 ,想着统一管理方便,就把KES安装包放到了NFS共享目录里。结果跑 setup.sh 安装引导程序的时候,一连串报错扑面而来:
bash
# 进到NFS挂载的KES安装目录
[test@localhost ~]$ cd /home/test/pan/cluster_nfs
[test@localhost cluster_nfs]$ ls
setup.sh install data README.txt
# 跑KES安装脚本 → 炸了!
[test@localhost cluster_nfs]$ sh setup.sh
bash: ./usr/bin/sh: Operation not permitted
# 试改权限 → 也炸了!
[test@localhost cluster_nfs]$ chmod 777 *
bash: ./usr/bin/chmod: Operation not permitted
bash: ./#chmod: Operation not permitted
# 试着写个日志 → 还炸!
[test@localhost cluster_nfs]$ tee installer.log
tee: installer.log: Read-only file system
把这些报错梳理了一下:
| 做什么操作 | 报什么错 | 对KES安装的影响 |
|---|---|---|
执行 setup.sh |
Operation not permitted |
KES安装器根本起不来 |
用 chmod 改权限 |
Operation not permitted |
KES二进制文件没法赋予执行权限 |
用 tee 写日志 |
Read-only file system |
KES的安装日志写不进去 |
1.2 第一反应会怎么查?
碰到这种报错,大多数运维同学脑子里大概会蹦出这么一条排查路线:
(KES setup.sh 跑不起来)"] --> B{文件系统类型?} B -->|本地文件系统| C[看看属主和权限] B -->|NFS/CIFS这类网络存储| D[检查挂载参数] C --> E[chmod/chown 搞定] D --> F{挂载参数对不对?} F -->|rw已经有了| G[去看服务端exports配置] F -->|ro或者压根没有| H[重新挂载加上rw] G --> I{是不是root_squash搞的鬼?} I -->|是的| J[服务端加no_root_squash] I -->|不是| K[查SELinux/AppArmor] H --> L[搞定收工] J --> L K --> M{再深挖一下Shell环境} M --> N[KES的环境变量加载了吗?]
但这回按这套路子走完一遍,KES还是装不上。那就说明问题藏得更深,得继续往下挖。
二、根因到底是什么?------ 几层因素叠加在一起
2.1 第一层:NFS挂载的那些"坑"
NFS(Network File System)在企业里用得挺广,多台机器之间共享KES安装介质、备份归档啥的都靠它。但它自带的一些安全机制,在部署KES的时候经常给人"背刺"。
root_squash 这个机制会搞事情
NFS服务端如果不显式写上 no_root_squash,默认就会开 root_squash------这对 KES安装过程中需要以root身份执行的操作 来说影响很大:
bash
# 服务端 /etc/exports 的写法 ------ 有隐患的那种
/data/nfs-share *(rw,sync)
# 推荐写法(适合KES批量部署的场景,安全方面也要自己评估)
/data/nfs-share *(rw,sync,no_root_squash,no_subtree_check,fsid=0)
root_squash 到底干了什么,以及对KES有啥影响:
| 客户端是谁 | 到了服务端变成了谁 | KES那边会怎样 |
|---|---|---|
| root (UID=0) | nfsnobody(一般是65534) | KES setup.sh 里那些setuid操作、创建系统目录之类的全被挡 |
| 普通用户 (UID≥500) | 还是原UID | KES数据文件的创建受NFS POSIX权限管着 |
| 匿名用户 | nobody | KES安装介质只能看,写不了日志 |
说白了就是:你在客户端明明是root在跑KES安装,NFS服务端却悄悄把你降成了低特权用户,chmod、chown 这些操作,还有KES安装器内部干的那些脏活累活,全给拒了。
只读挂载这个坑也很隐蔽
还有一种情况:客户端挂载的时候漏写了读写选项。要知道 KES安装过程中是要在当前目录生成临时文件和日志的,只读挂载直接就把它卡死了:
bash
# 客户端查看挂载状态的命令
mount | grep nfs
# 输出示例(留意那个ro标记 ------ KES安装必须是rw才行)
10.0.1.100:/data/nfs on /home/test/nfs type nfs4
(rw,relatime,vers=4.2,rsize=1048576,wsize=1048576,namlen=255,hard,
proto=tcp,timeo=600,retrans=2,sec=sys,...)
# 要是显示 ro 而不是 rw,那KES肯定装不上
2.2 第二层:Shell环境变量没生效------ 这才是真凶
回到这个案例本身,NFS挂载参数排查完也没发现问题,最后才找到真正的根因:用户的Shell环境变量(尤其是PATH和umask)在当前会话中没正确加载好,而KES安装器偏偏很依赖这些预置好的环境变量。
来看当时现场的情况:
bash
# 问题现场还原 ------ KES环境的典型症状
[test@localhost ~]$ pwd
/home/test
[test@localhost ~]$ echo $PATH
/usr/local/bin:/bin:/usr/bin # PATH短得离谱,KES的自定义路径没在里面
[test@localhost ~]$ umask
0022 # umask值可能不符合KES的安全基线
[test@localhost ~]$ source .bashrc # ← 关键修复动作(把KES环境加载回来)
# source之后再查
[test@localhost ~]$ echo $PATH
/opt/kes/prog/bin:/opt/kes/prog/../python3/bin:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin
# ^^^^^^^^^^^^^^^^
# KES的bin目录已经加进来了
[test@localhost ~]$ echo $umask
0007 # 符合KES安全基线要求
[test@localhost ~]$ echo $KES_HOME
/opt/kes/prog # KES主目录变量也有了
为啥一个 source .bashrc 就能把KES安装的问题解决了?
KingbaseES 的安装和运行依赖一组关键环境变量,这些通常写在 .bashrc 或者 .profile 里面由初始化脚本去设。如果 .bashrc 根本没被执行过:
- PATH 不完整 :KES的工具链(像
ksql、sys_ctl、initdb这些)找不到正确的路径,系统可能退回去用了某个受限的内置命令或者缓存里的旧路径 - umask 太松:新建文件的权限掩码不对,可能触发KES的安全策略拦截
- KES专用的环境变量缺失 :
LD_LIBRARY_PATH(动态链接库路径)、KES_HOME(KES主目录)这些没定义的话,KES二进制程序加载动态链接库时会失败 - 别名和函数没加载:KES管理工具的包装函数或别名没生效
KES的环境变量有多重要? KingbaseES 设计上走的是严格的路径依赖规范。
KES_HOME变量指向KES的安装根目录,所有子组件------数据库引擎、开发工具包、扩展插件什么的------都基于这个路径去找资源。这个变量一旦缺了或者指错了,轻则安装器找不到配置模板,重则运行的时候连核心模块都加载不了。
三、怎么修?------ 从应急到根治的实操步骤
3.1 先把火灭了(应急处理)
如果KES安装已经报错了,按这个顺序来救:
bash
# 第一步:确认当前在哪个目录
pwd
# 应该显示:/home/test 或你实际的KES用户家目录
# 第二步:重新加载Shell配置(把KES环境变量拉回来)
source .bashrc
# 或者这样写也行
source ~/.bashrc
# 第三步:验证关键的KES环境变量有没有到位
echo "PATH=$PATH"
echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH"
echo "KES_HOME=$KES_HOME"
echo "umask=$(umask)"
# 第四步:回到KES安装目录重新跑
cd /path/to/kes-installer
sh setup.sh
# 这次KES的图形化界面应该能正常起来了,或者进入命令行交互模式
多说一句 :如果跑了
source .bashrc之后还报错,那建议再去看看KES用户(默认一般叫kes或kingbase)的家目录下.bashrc文件是不是存在、内容是不是完整。
3.2 把NFS配置调对(根治措施)
要从根本上解决KES在NFS场景下的部署问题,服务端这边也需要做些优化:
编辑 /etc/exports:
ini
# 配置模板(实际网段和安全策略请根据自己情况改)
# KES安装介质专用共享目录 ------ 生产环境推荐这种配法
/database/share 192.168.1.0/24(rw,sync,no_root_squash,no_subtree_check,fsid=0)
# 各个参数的意思:
# rw : 读写权限(必须有!不然KES就会报Read-only file system)
# sync : 同步写入,保数据一致性(KES WAL日志一致性要靠它)
# no_root_squash : 客户端的root过来还是root身份(KES安装需要干些特权操作的)
# no_subtree_check: 关掉子树检查,性能能提一提,还能避免某些兼容性毛病
# fsid=0 : 设个文件系统ID,NFSv4根导出用的
重启NFS让配置生效:
bash
# RHEL/CentOS 系统
sudo systemctl restart nfs-server
sudo exportfs -rv # 强制重新导出所有目录
# Ubuntu/Debian 系统
sudo systemctl restart nfs-kernel-server
sudo exportfs -rv
# 看看导出列表对不对(确认KES的共享目录已经发出去了)
showmount -e localhost
客户端挂载参数建议(针对KES安装场景做过优化的):
bash
# 建个KES挂载点
sudo mkdir -p /mnt/kes-installer
# 用优化过的参数挂载(KES安装包动不动就好几个G,缓冲区大小很影响速度)
sudo mount -t nfs -o \
vers=4.2,\
rsize=1048576,\
wsize=1048576,\
hard,\
intr,\
timeo=600,\
retrans=2 \
192.168.1.100:/database/share /mnt/kes-installer
# 验证挂载结果(确认有 rw ------ 这是KES安装的前置条件)
mount | grep mnt/kes-installer
关于性能 :
rsize和wsize设成1MB,大文件传输性能会有明显提升。KES完整安装包一般 几百MB到数GB(算上可选组件),合理的缓冲区大小对安装介质的复制和解压速度影响还是挺直观的。
四、别等出了事再慌 ------ KES安装前环境检查清单(Pre-Installation Checklist)
为了避免同样的问题反复折腾,这里整理了一份专门面向 KingbaseES 部署 的前置检查清单,覆盖环境变量、依赖库、Shell配置和NFS挂载选项这四个维度。
4.1 全自动化检查脚本
bash
#!/bin/bash
# ============================================================
# KingbaseES 安装前环境检查脚本 (pre_install_check.sh)
# 适用平台: CentOS 7+/RHEL 7+/Ubuntu 18.04+ / Kylin V10+
# 检查内容: 环境变量、依赖库、Shell 配置、NFS 挂载选项
# ============================================================
echo "============================================="
echo " KingbaseES 安装前环境检查 (Pre-Install)"
echo "============================================="
PASS_COUNT=0
FAIL_COUNT=0
WARN_COUNT=0
# ==================== 1. 内核版本 ====================
KERNEL_VER=$(uname -r)
echo ""
echo "--- [1/10] 内核版本 ---"
echo -n " 当前内核: $KERNEL_VER ... "
if [[ "$KERNEL_VER" == *3.10* ]] || [[ "$KERNEL_VER" > "3.10.0" ]]; then
echo "✓ 通过 (KES支持此内核)"
((PASS_COUNT++))
else
echo "✗ 不满足最低要求(>=3.10.0)"
((FAIL_COUNT++))
fi
# ==================== 2. 操作系统发行版 ====================
echo ""
echo "--- [2/10] 操作系统 ---"
if [ -f /etc/redhat-release ]; then
OS_INFO=$(cat /etc/redhat-release)
elif [ -f /etc/os-release ]; then
OS_INFO=$(grep PRETTY_NAME /etc/os-release | cut -d'"' -f2)
else
OS_INFO="未知操作系统"
fi
echo " $OS_INFO"
# ==================== 3. NFS挂载(重点!)====================
echo ""
echo "--- [3/10] NFS挂载状态(KES安装的关键项)---"
if mount | grep -q "nfs"; then
echo " [!] 检测到以下NFS挂载:"
mount | grep nfs | while read line; do
echo " $line"
# 是不是读写模式?(KES必须要是rw)
if echo "$line" | grep -qE ",rw[, ]"; then
echo " ✓ 读写模式正常 (KES装得上的前提)"
else
echo " ✗ 只读挂载! KES肯定装不上!"
((FAIL_COUNT++))
fi
# NFS版本
if echo "$line" | grep -q "vers=4"; then
echo " ✓ NFSv4协议 (推荐)"
else
echo " ⚠ 建议升到NFSv4,兼容性好一些"
((WARN_COUNT++))
fi
# hard挂载
if echo "$line" | grep -q "hard"; then
echo " ✓ 硬挂载模式 (推荐)"
fi
done
else
echo " ℹ 没检测到NFS挂载(本地存储,跳过此项)"
fi
# ==================== 4. Shell环境(核心!)====================
echo ""
echo "--- [4/10] Shell环境变量(KES的核心依赖)---"
# 4.1 SHELL类型
echo -n " 当前SHELL: $SHELL ... "
if [ -n "$SHELL" ]; then
echo "✓ 已识别"
else
echo "⚠ SHELL变量是空的"
((WARN_COUNT++))
fi
# 4.2 PATH完整性
echo -n " PATH长度: ${#PATH} 字符 ... "
if [ "${#PATH}" -gt 50 ]; then
echo "✓ 长度看着还行"
# 再看一眼有没有KES的路径
if echo "$PATH" | grep -q "kes"; then
echo " ✓ PATH里已经有KES相关路径了"
else
echo " ⚠ PATH里没看到KES路径(首次安装的话这倒正常)"
fi
else
echo "✗ PATH太短了,环境变量大概率没完整加载!"
echo " → 建议: source ~/.bashrc"
((FAIL_COUNT++))
fi
# 4.3 KES专用变量
echo -n " KES_HOME: "
if [ -n "$KES_HOME" ] && [ -d "$KES_HOME" ]; then
echo "✓ $KES_HOME (有效)"
((PASS_COUNT++))
elif [ -n "$KES_HOME" ]; then
echo "⚠ $KES_HOME (但目录不存在啊)"
((WARN_COUNT++))
else
echo "ℹ 没设置(首次安装属于正常情况)"
fi
echo -n " LD_LIBRARY_PATH: "
if [ -n "$LD_LIBRARY_PATH" ]; then
echo "✓ 已设置 (${#LD_LIBRARY_PATH} 字符)"
else
echo "⚠ 没设置(KES运行可能会受影响)"
((WARN_COUNT++))
fi
# 4.4 umask
echo -n " umask: $(umask) ... "
UMASK_VAL=$(umask)
if [ "$UMASK_VAL" = "0022" ] || [ "$UMASK_VAL" = "0002" ] || [ "$UMASK_VAL" = "0007" ]; then
echo "✓ 没问题(符合KES安全基线)"
else
echo "⚠ umask=$UMASK_VAL 有点太宽松了"
((WARN_COUNT++))
fi
# ==================== 5. 关键依赖包 ====================
echo ""
echo "--- [5/10] KES关键依赖包 ---"
DEPS=("gcc" "gcc-c++" "make" "readline-devel" "zlib-devel" "openssl-devel")
for dep in "${DEPS[@]}"; do
if rpm -q "$dep" &>/dev/null || dpkg -l "$dep" 2>/dev/null | grep -q "^ii"; then
echo " ✓ $dep 已经装了"
else
echo " ✗ $dep 没装 (KES编译或运行可能需要)"
((FAIL_COUNT++))
fi
done
# ==================== 6. ulimit系统资源限制 ====================
echo ""
echo "--- [6/10] ulimit资源限制 ---"
echo -n " 最大打开文件数(ulimit -n): $(ulimit -n) ... "
if [ "$(ulimit -n)" -ge 65536 ]; then
echo "✓ 满足KES生产环境的要求"
elif [ "$(ulimit -n)" -ge 4096 ]; then
echo "⚠ 偏低了点(建议 >= 65536,高并发场景扛不住)"
((WARN_COUNT++))
else
echo "✗ 严重不够! KES高并发下大概率爆'too many open files'"
((FAIL_COUNT++))
fi
echo -n " 最大进程数(ulimit -u): $(ulimit -u) ... "
if [ "$(ulimit -u)" -ge 4096 ]; then
echo "✓ OK"
else
echo "⚠ 建议至少 4096"
((WARN_COUNT++))
fi
# ==================== 7. 共享内存参数 ====================
echo ""
echo "--- [7/10] 共享内存(跟KES性能挂钩)---"
SHMALL=$(sysctl -n kernel.shmall 2>/dev/null || echo "N/A")
SHMMAX=$(sysctl -n kernel.shmmax 2>/dev/null || echo "N/A")
echo " kernel.shmall = $SHMALL"
echo " kernel.shmmax = $SHMMAX"
if [ "$SHMMAX" != "N/A" ] && [ "$SHMMAX" -lt 17179869184 ] 2>/dev/null; then
echo " ⚠ shmmax偏低(建议 >= 16GB,KES大内存配置要用到的)"
((WARN_COUNT++))
else
echo " ✓ 共享内存参数没问题"
fi
# ==================== 8. 网络 ====================
echo ""
echo "--- [8/10) 主机名和网络解析 ---"
echo " 主机名: $(hostname)"
echo " /etc/hosts 关键条目:"
grep -E "(127\.0\.0\.1|::1)" /etc/hosts 2>/dev/null | head -3 | sed 's/^/ /'
if hostname -I &>/dev/null; then
echo " IP地址: $(hostname -I | awk '{print $1}')"
else
echo " ⚠ 拿不到IP地址"
fi
# ==================== 9. SELinux ====================
echo ""
echo "--- [9/10] SELinux ---"
if command -v getenforce &>/dev/null; then
SELINUX_STATUS=$(getenforce 2>/dev/null)
echo -n " 当前状态: $SELINUX_STATUS ... "
case "$SELINUX_STATUS" in
Enforcing)
echo "⚠ 强制模式(KES监听端口可能被拦,得配SELinux策略)"
((WARN_COUNT++))
;;
Permissive)
echo "✓ 宽容模式(排查完之后可以考虑关掉或配策略)"
;;
Disabled)
echo "ℹ 已禁用"
;;
*)
echo "? 不知道啥状态"
;;
esac
else
echo " ℹ 这系统没SELinux(Ubuntu/Debian之类)"
fi
# ==================== 10. 磁盘空间 ====================
echo ""
echo "--- [10/10] 磁盘空间(KES安装起码要2GB空闲)---"
INSTALL_DIR="/home" # 改成你实际的KES安装目标目录
AVAIL_KB=$(df -k "$INSTALL_DIR" 2>/dev/null | tail -1 | awk '{print $4}')
if [ -n "$AVAIL_KB" ]; then
AVAIL_GB=$((AVAIL_KB / 1024 / 1024))
echo -n " $INSTALL_DIR 空闲: 约 ${AVAIL_GB}GB ... "
if [ "$AVAIL_GB" -ge 2 ]; then
echo "✓ 够KES装的"
((PASS_COUNT++))
else
echo "✗ 不够! KES完整安装最少要2GB"
((FAIL_COUNT++))
fi
else
echo " ⚠ 查不到磁盘信息"
fi
# ==================== 汇总 ====================
echo ""
echo "============================================="
echo " KES 安装前环境检查报告"
echo "============================================="
printf " %-12s %s\n" "通过项:" "$PASS_COUNT"
printf " %-12s %s\n" "警告项:" "$WARN_COUNT"
printf " %-12s %s\n" "异常项:" "$FAIL_COUNT"
echo "---------------------------------------------"
if [ $FAIL_COUNT -eq 0 ] && [ $WARN_COUNT -eq 0 ]; then
echo " 🎉 全部通过,可以开始装KES了!"
elif [ $FAIL_COUNT -eq 0 ]; then
echo " ⚠️ 有 $WARN_COUNT 个警告,关注一下也能继续装"
else
echo " ❌ 有 $FAIL_COUNT 个必须先修复的问题!"
echo " → 先把上面异常项处理掉,再跑KES安装程序"
fi
echo "============================================="
4.2 怎么跑这个脚本
bash
# 存好之后赋权执行
chmod +x pre_install_check.sh
./pre_install_check.sh
# 输出大概长这样:
# =============================================
# KingbaseES 安装前环境检查 (Pre-Install)
# =============================================
#
# --- [1/10] 内核版本 ---
# 当前内核: 3.10.0-1160.el7.x86_64 ... ✓ 通过
# ...
# ============================================
# KES 安装前环境检查报告
# ============================================
# 通过项: 8
# 警告项: 2
# 异常项: 0
# ---------------------------------------------
# ⚠️ 有 2 个警告,关注后可继续安装
# ============================================
五、再往深处聊聊:KES 在网络存储环境下的部署策略
5.1 存储方案怎么选?
在生产环境里部署KingbaseES,选什么样的存储直接决定了数据库能跑多快、多稳。下面三种主流方案各有各的适用场景:
| 对比项 | NFS | SAN (FC/iSCSI) | 本地NVMe SSD |
|---|---|---|---|
| 部署难度 | ★☆☆ 简单 | ★★★ 复杂 | ★★☆ 一般 |
| I/O吞吐量 | 100-300 MB/s | 1-10 GB/s | 2-7 GB/s |
| 延迟 | 1-5 ms | <1 ms | <0.1 ms |
| 适合KES什么场景 | 开发测试、安装介质共享、WAL归档 | 生产核心、KES共享存储集群 | KES高并发OLTP、热数据 |
| 成本 | 低 | 高 | 中高 |
| 多节点共享 | 天然支持 | 得配集群文件系统 | 得靠KES流复制方案 |
KES部署的一点建议 :生产环境真心推荐 SAN + 本地SSD混搭------KES的数据文件和WAL日志放本地高性能SSD,备份归档和安装介质丢NFS/SAN共享存储上去。这样既保证了核心IO性能,又兼顾了管理便利性。
5.2 NFS上跑KES的最佳实践
有些时候确实不得不在NFS上部署KES(比如某些行业合规要求,或者资源实在紧张),那就照下面的规矩来:
yaml
# KES的NFS部署配置参考 (kes_nfs_deployment.yaml)
nfs_server_config:
description: "KES安装介质和归档存储用的NFS服务端配置"
server_ip: "192.168.10.100"
export_path: "/database/kes_share"
exports_options: "rw,sync,no_wdelay,no_subtree_check,insecure_locks,no_root_squash"
# 性能调优(KES安装包大,这几个参数很关键)
nfsd_threads: 16 # NFS工作线程
rpc.mountd_args: "-F 16" # mountd线程
client_mount_options:
mount_point: "/mnt/kes-media"
options:
vers: "4.2" # 协议版本
rsize: 1048576 # 读缓冲1MB(KES安装包传得快)
wsize: 1048576 # 写缓冲1MB(KES日志/归档写得快)
hard: true # 硬挂载(网断了也不丢写请求)
intr: true # 允许中断挂起的操作
timeo: 600 # 超时60秒(慢速网络友好)
retrans: 2 # 重试2次
_netdev: true # 网络设备标记(等网络好了再挂)
kingbasees_config:
kes_conf_tuning:
shared_buffers: "256MB" # 共享内存调小(NFS延迟敏感)
effective_cache_size: "1GB" # 缓存预期降低
wal_sync_method: "open_datasync" # WAL写入方式调整
nfs_limitations:
enable_bitmapscan: false # 位图扫描随机IO太多,NFS上禁掉
random_page_cost: 2.5 # 随机IO代价调高(抑制全表扫描倾向)
data_directory_layout:
local_primary: "/opt/kes/data" # KES主数据目录(本地SSD)
nfs_archive: "/mnt/kes-media/archive" # KES WAL归档(放NFS)
nfs_backup: "/mnt/kes-media/backup" # KES物理备份(放NFS)
nfs_installer: "/mnt/kes-media/installer" # KES安装介质(放NFS)
5.3 KES高可用架构长什么样(NFS的角色)
192.168.1.11"] APP2["应用服务器 2
192.168.1.12"] end subgraph KESLayer ["KingbaseES 数据库集群"] direction LR KES1["主节点 Primary
KES读写服务
IP: 192.168.1.21"] KES2["备节点 Standby
KES只读和灾备
IP: 192.168.1.22"] end subgraph StorageLayer ["存储层"] direction LR NFS["NFS共享存储
KES安装介质 / WAL归档 / 物理备份"] LOCAL1[("本地NVMe SSD
KES主数据 + WAL日志")] LOCAL2[("本地NVMe SSD
KES备份数据 + Standby WAL")] end APP1 -->|SQL请求| KES1 APP2 -->|SQL请求| KES1 KES1 -->|"KES Physical Replication"| KES2 KES1 -.->|读安装介质| NFS KES2 -.->|读安装介质| NFS KES1 -.->|WAL归档写入| NFS KES1 ===|数据文件和WAL| LOCAL1 KES2 ===|接收复制流| LOCAL2 style NFS fill:#fff3e0,stroke:#ff9800,color:#e65100 style LOCAL1 fill:#e3f2fd,stroke:#1565c0,color:#0d47a1 style LOCAL2 fill:#e3f2fd,stroke:#1565c0,color:#0d47a1 style KES1 fill:#e8f5e9,stroke:#2e7d32,color:#1b5e20 style KES2 fill:#fce4ec,stroke:#c62828,color:#b71c1c
各组件放哪儿、为什么这么放:
| 组件 | 放哪 | 理由 |
|---|---|---|
| KES主节点数据目录 | 本地NVMe SSD | 高频读写,延迟必须压到最低 |
| KES WAL(预写式日志) | 本地NVMe SSD | 每次事务提交都得刷盘,慢不起 |
| KES安装介质 | NFS共享存储 | 就装的时候用一下,带宽要求不高 |
| KES WAL归档 | NFS共享存储 | 异步归档,稍微慢一点没关系 |
| KES物理备份 | NFS共享存储 | 定时任务跑的,带宽可控 |
六、KES 运维中 Shell 脚本调试的那点事儿
6.1 三板斧搞定KES安装脚本报错
日常运维里,KES安装器(setup.sh)或者它里面调用的KES工具(比如 initdb、sys_ctl)报错了怎么办?下面这几招挺好使:
第一招:调试模式跑KES安装器
bash
# 方式A:bash -x 逐行追踪KES安装器的执行过程
bash -x setup.sh 2>&1 | tee kes_debug.log
# 方式B:往KES脚本头里插调试开关(如果你有修改权限的话)
#!/bin/bash
set -x # 每条命令执行时打印出来(追踪KES安装全过程)
set -e # 出错立刻退出(快速暴露问题在哪)
set -u # 引用未定义变量就报错(抓KES环境变量缺失)
set -o pipefail # 管道里任一命令失败整个管道就算失败
KES调试输出的样子(带 + 号的是追踪信息):
bash
+ cd /home/test/pan/cluster_nfs
+ '[' -f config.ini ']'
+ source ./env_init.sh # ← KES环境初始化脚本
++ export KES_HOME=/opt/kes/prog # ← 设置KES主目录
++ KES_HOME=/opt/kes/prog
++ export LD_LIBRARY_PATH=/opt/kes/prog/lib # ← 设置KES链接库路径
++ LD_LIBRARY_PATH=/opt/kes/prog/lib
+ ./install_bin --mode=install # ← 启动KES安装器
./install_bin: error while loading shared libraries: libstdc++.so.6:
cannot open shared object file: No such file or directory
# ↑ 问题暴露了:依赖库缺失
第二招:strace 追踪系统调用
bash
# 追踪KES安装器执行过程中的关键系统调用
strace -f -e trace=open,openat,execve,chmod sh setup.sh 2>&1 | grep -E "(ENOENT|EACCES|EPERM)"
典型的KES安装场景输出,怎么看:
perl
# ENOENT - 文件不存在(KES的PATH问题 ------ 找不到KES工具了)
execve("./sh", ["./sh", "setup.sh"], 0x7ffc...) = -1 ENOENT (No such file or directory)
# EACCES - 权限不够(NFS挂载问题或者KES文件权限不对)
open("setup.sh", O_RDONLY) = -1 EACCES (Permission denied)
# EPERM - 操作不被允许(SELinux拦了或者NFS root_squash在作祟)
chmod("setup.sh", 0755) = -1 EPERM (Operation not permitted)
# ↑ 就是本文开头那个案例的错误!
第三招:环境对比法
bash
# 在KES正常运行的那台机器上导出完整环境
env > kes_env_normal.txt
declare -p > kes_vars_normal.txt
alias > kes_alias_normal.txt
# 在KES安装失败的问题机器上也导一份
env > kes_env_problem.txt
declare -p > kes_vars_problem.txt
alias > kes_alias_problem.txt
# 两边一对比 ------ 缺失的KES环境变量一目了然
diff kes_env_normal.txt kes_env_problem.txt
diff kes_vars_normal.txt kes_vars_problem.txt
6.2 KES运维常见环境问题速查表
| 碰到什么现象 | 大概率是什么原因 | 怎么排查 | KES怎么解决 |
|---|---|---|---|
command not found(ksql/sys_ctl之类的) |
PATH里没有KES的路径 | `echo $PATH | grep kes` |
Permission denied |
KES文件权限不够 | ls -la $KES_HOME/bin/ |
chmod +x script.sh |
Operation not permitted |
NFS root_squash或者SELinux在搞事 | `mount | grep nfs; getenforce` |
Read-only filesystem |
NFS挂成了只读 | `mount | grep nfs` |
library not found |
LD_LIBRARY_PATH没设 | `ldconfig -p | grep libstdc` |
segmentation fault |
平台架构对不上 | file sys_ctl; uname -m |
下载匹配平台的KES版本 |
KES_HOME not defined |
环境变量根本没加载 | echo $KES_HOME |
source ~/.bashrc 或者手动export |
lock file postmaster.pid |
KES上次退出不干净留下的 | cat $KES_DATA/postmaster.pid |
清掉pid文件或者重启KES |
6.3 KES的日志体系和多实例隔离
KES有哪些日志可以看:
| 日志种类 | 在哪 | 干嘛用的 | 怎么分析 |
|---|---|---|---|
| KES安装日志 | install/kes_install.log |
记录安装全过程 | grep -i error/warn 过滤 |
| KES启动日志 | $KES_DATA/log/server.log |
数据库引擎运行时的输出 | 重点看ERROR和FATAL级别 |
| KES系统日志 | /var/log/messages |
操作系统层面的记录(SELinux之类的) | 按时间线关联着看 |
| Shell调试日志 | 自己用tee存的 | 环境变量和命令执行记录 | bash -x 的输出重定向 |
一台机器上跑多个KES实例怎么隔离环境:
bash
# 给不同KES实例准备独立的Shell环境配置文件
# ~/.bashrc.kes_prod (生产实例用的)
export KES_HOME=/opt/kes/prod
export KES_DATA=/data/kes/prod_data
export LD_LIBRARY_PATH=$KES_HOME/lib:$LD_LIBRARY_PATH
export PGPORT=54321
export PGDATABASE=prod_db
# ~/.bashrc.kes_test (测试实例用的)
export KES_HOME=/opt/kes/test
export KES_DATA=/data/kes/test_data
export LD_LIBRARY_PATH=$KES_HOME/lib:$LD_LIBRARY_PATH
export PGPORT=54322
export PGDATABASE=test_db
# 切实例的时候就source对应的环境文件
source ~/.bashrc.kes_prod # 切到生产实例
source ~/.bashrc.kes_test # 切到测试实例
七、总结
这篇东西从一起 KingbaseES 在NFS环境下的典型安装报错 说起,把问题的根因一层层扒开,给了从应急到根治的解决方案,还顺带整理了预防性的检查手段。核心内容回顾一下:

最后列个行动清单
- 马上查 :所有要装KES的节点,NFS挂载有没有带上
rw和hard - 环境标准化 :每个KES用户的
~/.bash_profile确保有调用source ~/.bashrc - 文档沉淀 :把内部的 KES部署SOP 写出来,NFS配置那一块别漏
- 自动化建设 :前面那份 KES Pre-Install Check 脚本 塞进部署流水线
- 监控告警:NFS服务的可用性和KES数据目录的挂载状态弄个监控指标
- 定期演练:非生产环境定期走一遍KES在NFS下的安装流程,提前踩坑
现在容器化和云原生越来越普及,不少企业开始用Docker镜像或者Kubernetes Operator来部署KingbaseES了。新范式下存储层交给了Kubernetes CSI驱动来抽象,但底层的道理------不管是POSIX权限模型、NFS挂载参数还是Shell环境隔离------其实都是相通的。把这些基础打牢了,不管技术栈怎么变,KES部署中的各种问题都能应对得比较从容。
当然,KingbaseES 自身也在不断迭代,新版对网络存储环境的兼容性和容错能力一直在增强。建议大家关注官方的版本说明,及时了解KES在存储层面又多了哪些新特性、修了哪些已知问题。
