ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

CentOS 7 下 Greenplum 自动化安装脚本实战:从系统调优到集群初始化

CentOS 7 下 Greenplum 自动化安装脚本实战:从系统调优到集群初始化

简介:这份资源是面向大数据运维与数据库开发人员的 Greenplum 安装部署包,专为 CentOS 7 环境打造,帮助用户快速搭建可扩展的 MPP 大数据分析平台,适用于海量数据处理与复杂查询场景。压缩包共 32 个文件,约 66.11MB,以 yml、sh、j2、yaml 等自动化配置与脚本文件为主,辅以 ini 主机配置、makefile 编译指令、rpm 安装包、sql 脚本及 license、txt 说明文档,覆盖从环境初始化、集群部署到服务启动的完整链路。资源内含主机配置、许可协议、编译安装指令、启动脚本及源码目录等模块,读者可据此完成 Greenplum 在 CentOS 7 上的系统化安装,并借助脚本简化启动流程,同时通过源码目录满足定制开发与性能优化需求。目前已有 253 人学习下载,适合需要快速落地大数据仓库平台的中高级开发者参考。

1. 为什么我还在用 greenplum_installer-centos7 装 Greenplum

上周帮一个做数据仓库的朋友救火,他们一套跑了三年的 Greenplum 集群要扩容,结果新机器上源码编译 Greenplum 6 卡在gporca依赖上整整两天没过去。我翻出自己压箱底的greenplum_installer-centos7脚本包,半小时把新节点拉起来了。这不是什么新鲜工具,但在 CentOS 7 这个已经进入维护期的系统上,它依然是把 Greenplum 从零装到能跑 SQL 的最短路径。

这个资源本质上是一套面向 CentOS 7 的 Greenplum 自动化安装脚本集合,覆盖了系统参数调优、依赖安装、Greenplum 二进制部署、集群初始化、segment 节点注册这一整条链路。它解决的核心问题是:Greenplum 官方文档给的安装步骤散落在十几个章节里,手工执行极易漏掉sysctl内核参数、limits.conf文件描述符限制、ssh免密互信这些前置条件,而任何一项漏掉都会在gpinitsystem阶段以各种玄学报错收场。

适合谁用?如果你手头是 CentOS 7.x 的物理机或虚拟机,要搭一套用于开发测试或中小规模生产验证的 Greenplum 集群,又不想在编译和依赖上耗时间,这套脚本能让你把精力放在表设计和查询优化上。但如果你用的是 CentOS 8、Rocky Linux 或者想上 Greenplum 7,这套脚本的适配性需要你自己改,后面会讲怎么改。

2. 拆开脚本包:目录结构与核心参数怎么读

拿到一个安装脚本包,我习惯先看目录结构和主脚本的变量定义,而不是上来就sh install.sh。这套greenplum_installer-centos7的目录组织比较典型,理解它的分层逻辑能帮你快速定位改哪里。

2.1 目录分层与各文件职责

解压后大致是这么几层:

greenplum_installer-centos7/ ├── install.sh # 主入口,串联各阶段 ├── conf/ │ ├── cluster.conf # 集群拓扑:master/segment 主机名与 IP │ └── gpdb.conf # Greenplum 版本、安装路径、数据目录 ├── scripts/ │ ├── 01_os_prepare.sh # 系统参数、依赖包、用户创建 │ ├── 02_ssh_trust.sh # 节点间免密互信 │ ├── 03_install_gpdb.sh # 二进制部署与环境变量 │ └── 04_init_cluster.sh # gpinitsystem 初始化 └── rpm/ # 离线依赖包(部分版本自带)

install.sh本身不做具体操作,它按顺序调用scripts/下的四个脚本,每个脚本执行完会检查返回码,失败就停住并打印日志路径。这种设计的好处是你可以在任意阶段单独重跑,比如系统参数已经调好了,就直接跑03_install_gpdb.sh。

conf/cluster.conf是最需要你动手改的文件,它定义了集群里每台机器的角色。一个典型的双 segment 配置长这样:

# cluster.conf 示例 MASTER_HOST=mdw MASTER_IP=192.168.1.10 STANDBY_HOST=smdw STANDBY_IP=192.168.1.11 SEGMENT_HOSTS=(sdw1 sdw2) SEGMENT_IPS=(192.168.1.12 192.168.1.13) SEGMENT_COUNT=2

这里有个容易翻车的点:SEGMENT_HOSTS和SEGMENT_IPS的顺序必须严格对应,脚本内部用数组下标做映射。如果你把 IP 顺序写反了,初始化时 segment 会注册到错误的主机上,gpstate显示全是不认识的 hostname。

conf/gpdb.conf管的是软件层面的路径和版本:

GPDB_VERSION=6.24.0 GPDB_HOME=/usr/local/greenplum-db DATA_DIR=/data/gpdata MASTER_DATA_DIR=/data/gpmaster GP_USER=gpadmin

GPDB_VERSION决定了脚本去rpm/目录找哪个版本的二进制包。如果你手头的包版本和这里不一致,脚本会在03_install_gpdb.sh阶段报「package not found」。改版本号之前,先ls rpm/确认实际文件名。

2.2 系统参数脚本里那几个不能动的值

01_os_prepare.sh做三件事:创建gpadmin用户、安装依赖、写内核参数。其中内核参数部分我建议你逐行看一遍,因为有些值是根据机器内存算出来的,不是固定值。

# 01_os_prepare.sh 节选 # 共享内存段,Greenplum 的 postgres 进程间通信依赖它 sysctl -w kernel.shmmax=$(echo "$(free -b | awk '/Mem/{print $2}') * 0.6" | bc | cut -d. -f1) sysctl -w kernel.shmall=$(echo "$(free -b | awk '/Mem/{print $2}') / 4096" | bc) # 信号量与消息队列 sysctl -w kernel.sem="250 32000 100 128" sysctl -w kernel.msgmnb=65536 sysctl -w kernel.msgmax=65536 # 文件描述符 echo "gpadmin soft nofile 65536" >> /etc/security/limits.conf echo "gpadmin hard nofile 65536" >> /etc/security/limits.conf

kernel.shmmax取物理内存的 60%,这是 Greenplum 官方推荐的经验值。如果你机器上还跑着别的吃共享内存的服务,这个比例要往下调,否则gpinitsystem会在创建共享内存段时报No space left on device——注意这个报错和磁盘空间无关,是共享内存段不够。

kernel.sem的四个值分别是:每个信号集的最大信号数、系统级最大信号数、每个 semop 调用的最大操作数、系统级最大信号集数。Greenplum 的并行查询会大量使用信号量,32000这个系统级上限在 segment 数量多的时候可能不够,我遇到过 8 个 segment 的集群跑到复杂查询时报semop失败,把第二个值调到64000才稳住。

提示:改完limits.conf后,gpadmin用户必须重新登录才生效。脚本里用su - gpadmin切换用户,但如果你是在当前 shell 里手动验证,记得先exit再重新su。

2.3 免密互信脚本的隐藏依赖

02_ssh_trust.sh的逻辑是:在 master 上生成密钥对,然后通过ssh-copy-id分发到所有 segment 和 standby。但这里有个隐藏依赖——脚本假设所有节点的sshd配置里PubkeyAuthentication是开启的,且AuthorizedKeysFile指向默认路径。

我踩过一次坑:某台机器之前被安全加固过,sshd_config里AuthorizedKeysFile被改到了/etc/ssh/keys/%u,脚本分发过去的公钥根本没被读取,ssh还是提示输密码。排查方法是在目标机上tail -f /var/log/secure,然后从 master 发起ssh连接,看日志里有没有Authentication refused: bad ownership or modes之类的提示。

脚本执行完互信后,会跑一个验证循环:

for host in "${SEGMENT_HOSTS[@]}" "$STANDBY_HOST"; do ssh -o BatchMode=yes -o ConnectTimeout=5 gpadmin@$host "hostname" || { echo "SSH trust failed to $host" exit 1 } done

BatchMode=yes的作用是禁止交互式密码输入,如果互信没配好,这里会直接失败而不是卡在密码提示上。ConnectTimeout=5避免网络不通时长时间挂起。这个验证逻辑值得保留,比人工一台台试靠谱。

3. 从零跑通安装:四个阶段的操作与验证

理解了配置文件的含义,接下来就是实际执行。我一般把安装过程拆成四个可独立验证的阶段,每个阶段做完都确认一下状态,不要一口气跑完install.sh再看结果——那样出错了你都不知道是哪一步的问题。

3.1 阶段一:系统准备与依赖安装

先在所有节点上确认 CentOS 版本和架构:

cat /etc/redhat-release uname -m

脚本支持的是 CentOS 7.x,uname -m应该是x86_64。如果你在 ARM 上跑,rpm/目录里的包架构不对,需要自己替换。

然后编辑conf/cluster.conf和conf/gpdb.conf,把主机名、IP、路径改成你环境的实际值。主机名建议用短名(如mdw、sdw1),并在所有节点的/etc/hosts里做好映射。Greenplum 内部大量使用主机名通信,用 IP 虽然也能跑,但gpstate和日志里全是 IP,排查问题时很不直观。

执行系统准备脚本:

# 在 master 节点执行,脚本会通过 ssh 分发到各 segment bash scripts/01_os_prepare.sh

这个脚本会做几件耗时的事:yum install一堆依赖包(如果rpm/目录有离线包则用rpm -ivh)、创建gpadmin用户、写sysctl参数并sysctl -p生效。如果卡在yum install,大概率是网络源不可用,检查/etc/yum.repos.d/下的 repo 文件,或者确认rpm/目录里的离线包是否完整。

脚本跑完后,验证内核参数是否生效:

sysctl kernel.shmmax kernel.shmall kernel.sem su - gpadmin -c "ulimit -n"

ulimit -n应该输出65536。如果还是1024,说明limits.conf没生效,检查/etc/security/limits.d/下有没有其他文件覆盖了配置——CentOS 7 默认有个20-nproc.conf,里面的nproc设置有时会干扰。

3.2 阶段二:SSH 互信与节点连通性

bash scripts/02_ssh_trust.sh

这个脚本执行很快,但验证很重要。跑完后手动从 master 试连每个 segment:

for host in sdw1 sdw2 smdw; do echo "--- $host ---" ssh -o BatchMode=yes gpadmin@$host "hostname && date" done

如果某台机器返回Permission denied,去那台机器上看/var/log/secure。常见原因有三个:gpadmin用户的家目录权限不对(应该是700)、.ssh目录权限不对(也应该是700)、authorized_keys文件权限不对(应该是600)。SSH 对权限极其敏感,多一个w权限都会拒绝。

注意:如果你在cluster.conf里配了 standby 节点,互信脚本也会往 standby 分发密钥。但 standby 在初始化阶段不参与,它的互信是为了后续gpactivatestandby准备的,别漏掉。

3.3 阶段三:Greenplum 二进制部署

bash scripts/03_install_gpdb.sh

这个脚本把rpm/目录下的 Greenplum 二进制包解压或安装到GPDB_HOME,然后设置gpadmin用户的环境变量。环境变量写在~gpadmin/.bashrc里:

source /usr/local/greenplum-db/greenplum_path.sh export MASTER_DATA_DIRECTORY=/data/gpmaster/gpseg-1 export PGPORT=5432

MASTER_DATA_DIRECTORY这个变量很关键,gpstart、gpstop、psql都依赖它。如果你手动改了数据目录,这里必须同步改,否则gpstart会报找不到数据目录。

验证安装:

su - gpadmin which gpstart gpstart --version

gpstart --version应该输出 Greenplum 的版本号。如果提示command not found,说明greenplum_path.sh没被 source,检查.bashrc里有没有这行,或者手动source一下。

3.4 阶段四:集群初始化与状态检查

这是最容易出问题的一步。04_init_cluster.sh内部调用gpinitsystem,传入一个根据cluster.conf生成的配置文件。核心参数包括:

参数含义常见值
-c集群配置文件路径脚本自动生成
-hsegment 主机列表文件脚本自动生成
-sstandby 主机名来自cluster.conf
-S是否启用 standbyy或n
-a自动确认脚本里默认加
-l日志目录/home/gpadmin/logs

执行:

bash scripts/04_init_cluster.sh

如果一切正常,最后会看到Greenplum Database instance successfully created。然后验证:

gpstate -s

gpstate -s会输出每个 segment 的状态,正常应该是Up。如果有 segment 显示Down,去对应的 segment 主机上看~/gpdata/.../pg_log/下的日志,通常是数据目录权限问题或者端口被占用。

初始化完成后,用psql连一下:

psql -d postgres -c "select version();" psql -d postgres -c "select * from gp_segment_configuration;"

第二条 SQL 会列出所有 segment 的角色、状态和端口。检查role列:master 是p(primary),standby 是m(mirror),segment 的 primary 是p,mirror 是m。如果 mirror 没起来,说明初始化时没配镜像,需要后续用gpaddmirrors补。

4. 避坑与排查:那些让我重装三次的报错

这套脚本虽然把大部分脏活干了,但 CentOS 7 环境本身的差异性和 Greenplum 的严格性,还是会让你在某些节点上翻车。下面是我实际遇到过的五个坑,按「现象 → 原因 → 解决」整理。

4.1 gpinitsystem 报共享内存段创建失败

现象:gpinitsystem执行到一半,日志里出现could not create shared memory segment: No space left on device,但df -h显示磁盘空间充足。

原因:kernel.shmmax或kernel.shmall设置过小,或者系统里已有其他进程占用了大量共享内存段。Greenplum 每个 segment 实例都需要独立的共享内存段,segment 数量多的时候总需求量超过内核限制。

解决:先ipcs -lm看当前共享内存限制,再ipcs -m看已使用的段。如果已用段很多,清理掉不用的(ipcrm -m <shmid>)。然后调大kernel.shmmax和kernel.shmall,sysctl -p生效后重跑gpinitsystem。注意kernel.shmall的单位是页(4KB),不是字节。

4.2 segment 节点 ssh 互信时好时坏

现象:02_ssh_trust.sh执行成功,但过一段时间后某些节点又需要密码,或者gpstate报cannot connect to segment。

原因:gpadmin用户的家目录或.ssh目录权限被其他操作改动了。CentOS 7 上有些安全扫描脚本会批量修改家目录权限,把700改成755,SSH 就会拒绝使用密钥。

解决:在所有节点上执行chmod 700 /home/gpadmin /home/gpadmin/.ssh && chmod 600 /home/gpadmin/.ssh/authorized_keys。然后从 master 重新验证互信。如果问题反复出现,检查有没有定时任务或配置管理工具在改权限。

4.3 gpstart 启动后 segment 大量 Down

现象:gpstart显示成功,但gpstate里一半 segment 是Down,日志里报could not bind to port。

原因:端口冲突。Greenplum 默认从5432开始给 master,segment 从6000开始递增。如果机器上有其他服务占用了这些端口,segment 就起不来。

解决:netstat -tlnp | grep -E '5432|600[0-9]'找到占用端口的进程,要么停掉它,要么改 Greenplum 的端口配置。改端口在gpdb.conf里加MASTER_PORT和SEGMENT_PORT_BASE,然后重新初始化。已经初始化的集群改端口比较麻烦,建议初始化前就规划好。

4.4 psql 连接报 too many clients

现象:应用连上来跑了一段时间后,psql报FATAL: sorry, too many clients already。

原因:Greenplum 的max_connections默认值(通常 100 左右)不够用,而且这个参数是 master 和每个 segment 各自维护的。master 的max_connections要大于等于所有 segment 的连接数之和,否则 master 先撑不住。

解决:在postgresql.conf里调大max_connections,master 和 segment 都要调。改完gpstop -u重载配置。但注意,max_connections调太大会增加共享内存需求,可能又触发 4.1 的坑,需要同步调大kernel.shmmax。

4.5 数据目录磁盘满导致 segment 崩溃

现象:某个 segment 突然Down,日志里报could not write to file或No space left on device。

原因:Greenplum 的数据目录写满了。CentOS 7 的/分区通常不大,如果DATA_DIR设在/下,跑几天就满了。

解决:把DATA_DIR和MASTER_DATA_DIRECTORY设到独立的大容量分区上。如果已经装好了,可以用gpddboost或者手动迁移数据目录,但更省事的做法是重装——初始化前规划好分区,比事后迁移省心得多。我现在的习惯是:/data单独挂一块盘,gpdata和gpmaster都放下面。

5. 进阶:改脚本适配新版本与离线环境

这套脚本默认绑定了某个 Greenplum 6.x 版本和在线 yum 源,但实际环境往往需要你改两处:版本适配和离线安装。下面是我改过多次之后总结的具体做法。

5.1 替换 Greenplum 二进制包版本

假设你要从 6.24 升到 6.26,步骤是:

# 1. 下载新版本的 Greenplum 二进制包,放到 rpm/ 目录 ls rpm/ # greenplum-db-6.26.0-rhel7-x86_64.rpm # 2. 改 conf/gpdb.conf 里的版本号 sed -i 's/GPDB_VERSION=6.24.0/GPDB_VERSION=6.26.0/' conf/gpdb.conf # 3. 检查 03_install_gpdb.sh 里的包名匹配逻辑 grep -n "GPDB_VERSION" scripts/03_install_gpdb.sh

03_install_gpdb.sh里通常用rpm -ivh rpm/greenplum-db-${GPDB_VERSION}-rhel7-x86_64.rpm这种方式安装。如果你的包命名规则不同(比如带了 build 号),需要改脚本里的文件名拼接逻辑。改完后先bash -n scripts/03_install_gpdb.sh做语法检查,再实际执行。

5.2 离线环境下的依赖处理

在线环境下01_os_prepare.sh用yum install装依赖,离线环境需要提前把依赖包下载好。我一般在一台有网的 CentOS 7 上执行:

# 下载 Greenplum 依赖包到本地目录 yum install --downloadonly --downloaddir=./rpm/deps \ apr apr-util bash bzip2 ca-certificates coreutils \ curl krb5-libs libcurl libevent libxml2 libyaml \ openldap openssl pam perl python rsync sed tar zip

然后把rpm/deps目录拷到目标机的rpm/下,改01_os_prepare.sh里的安装逻辑:

# 原逻辑(在线) # yum install -y apr apr-util ... # 改为离线安装 if [ -d "rpm/deps" ]; then rpm -ivh rpm/deps/*.rpm --nodeps --force else yum install -y apr apr-util ... fi

--nodeps --force是为了跳过依赖检查,因为离线包可能不完整。但这样装完之后,一定要跑一遍ldd $GPDB_HOME/bin/postgres检查动态库是否齐全。如果提示not found,缺哪个库就单独补哪个。

5.3 验证集群健康度的几个命令

装完之后,我习惯跑一套「体检」命令,确认集群不是表面能连、实际有隐患:

# 1. 检查所有 segment 状态 gpstate -s # 2. 检查数据分布是否倾斜 psql -d postgres -c " SELECT gp_segment_id, count(*) FROM gp_dist_random('pg_class') GROUP BY 1 ORDER BY 2 DESC;" # 3. 检查磁盘使用 gpssh -f all_hosts -e "df -h /data" # 4. 检查日志里有没有 ERROR gpssh -f all_hosts -e "tail -50 ~/gpdata/*/pg_log/*.csv | grep -i error"

第二条 SQL 用gp_dist_random强制在每个 segment 上执行,返回的count如果差异超过 20%,说明数据分布不均,需要检查分布键设计。第四条命令批量看日志,比一台台登录快得多。

提示:gpssh -f all_hosts需要一个包含所有主机名的文件,格式是每行一个主机名。这个文件在初始化时脚本会生成,通常在conf/目录下。

从那以后我每次装完 Greenplum,不管脚本跑得多顺利,都会强制走一遍gpstate -s加数据分布检查,确认没有隐藏的 segment 异常再交给应用侧。这套greenplum_installer-centos7脚本帮我省掉了大量重复劳动,但省掉的是操作,不是判断——该看的日志、该验的状态,一个都不能少。希望帮到你。

本文还有配套的精品资源,点击获取

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进