命名空间隔离
使用命名空间在单台主机上创建隔离的环境
命名空间允许你在单台主机上创建完全隔离的环境,非常适合将生产、开发和测试环境分开,避免容器名称冲突或端口冲突。
什么是命名空间?
命名空间是应用于配置文件中所有容器名称的前缀。这种隔离机制确保:
- 容器名称不冲突:每个命名空间有自己的容器前缀
- 端口范围分离:每个配置文件从自己的范围分配端口
- 备份容器隔离:每个命名空间有自己的 pgBackRest 容器
- 配置文件独立:每个环境使用单独的配置文件
使用场景:生产和开发环境
一个常见场景是在同一台服务器上运行生产和开发环境:
# 创建生产环境
pg config init \
--namespace prod \
--pg-start-port 35432 \
--pg-ssh-port 42201 \
--add app-db \
-o ~/.pgcli-prod/pg.yaml
# 创建开发环境
pg config init \
--namespace dev \
--pg-start-port 38000 \
--pg-ssh-port 43000 \
--add app-db \
-o ~/.pgcli-dev/pg.yaml
这会创建两个完全隔离的环境:
管理多个环境
使用 -c 标志指定要使用的配置文件:
# 启动生产数据库
pg -c ~/.pgcli-prod/pg.yaml start -i app-db
# 启动开发数据库
pg -c ~/.pgcli-dev/pg.yaml start -i app-db
# 列出生产环境实例
pg -c ~/.pgcli-prod/pg.yaml list
# 列出开发环境实例
pg -c ~/.pgcli-dev/pg.yaml list
工作原理
容器命名
命名空间为 prod,实例为 app-db:
- 实例容器:
pgcli-pg-prod-app-db
- 备份容器:
pgcli-backup-prod
- 网络:
pgcli-net-prod(如果使用独立网络)
没有命名空间(或 --namespace ""):
- 实例容器:
pgcli-pg-default-app-db
- 备份容器:
pgcli-backup-default
端口分配
配置文件中的每个实例获得顺序端口:
- 第一个实例:
pg_start_port(例如 35432)
- 第二个实例:
pg_start_port + 1(例如 35433)
- 依此类推…
SSH 端口同理。
配置持久化
命名空间和端口范围保存在配置文件中:
namespace: prod
pg_start_port: 35432
pg_ssh_port: 42201
最佳实践
1. 始终使用显式命名空间
在一台主机上运行多个配置时,永远不要依赖默认命名空间:
# 错误:两个配置都会使用 "default" 命名空间并冲突
pg config init --add app -o ~/.pgcli-prod/pg.yaml
pg config init --add app -o ~/.pgcli-dev/pg.yaml # 冲突!
# 正确:显式命名空间
pg config init --namespace prod --add app -o ~/.pgcli-prod/pg.yaml
pg config init --namespace dev --add app -o ~/.pgcli-dev/pg.yaml
2. 使用不重叠的端口范围
确保配置之间的端口范围不重叠:
# 生产:35432-35999, 42201-42999
pg config init --namespace prod \
--pg-start-port 35432 \
--pg-ssh-port 42201 \
--add app -o ~/.pgcli-prod/pg.yaml
# 开发:38000-38999, 43000-43999
pg config init --namespace dev \
--pg-start-port 38000 \
--pg-ssh-port 43000 \
--add app -o ~/.pgcli-dev/pg.yaml
# 测试:40000-40999, 44000-44999
pg config init --namespace test \
--pg-start-port 40000 \
--pg-ssh-port 44000 \
--add app -o ~/.pgcli-test/pg.yaml
为每个环境中的多个实例预留足够的端口空间。
3. 命名空间在创建时固化
命名空间在创建时嵌入容器名称。之后更改会破坏关联:
# 使用命名空间 "prod" 创建
pg -c ~/.pgcli-prod/pg.yaml start -i app-db
# 容器:pgcli-pg-prod-app-db
# 编辑配置将命名空间改为 "production"
# 这样不行 - 容器名称不匹配!
# 正确做法:销毁并重建
pg -c ~/.pgcli-prod/pg.yaml destroy -i app-db --clean-data
pg -c ~/.pgcli-prod/pg.yaml create -i app-db
pg -c ~/.pgcli-prod/pg.yaml start -i app-db
4. 使用 Shell 别名简化操作
创建别名避免重复输入 -c:
# 添加到 ~/.bashrc 或 ~/.zshrc
alias pg-prod='pg -c ~/.pgcli-prod/pg.yaml'
alias pg-dev='pg -c ~/.pgcli-dev/pg.yaml'
alias pg-test='pg -c ~/.pgcli-test/pg.yaml'
# 然后使用:
pg-prod start -i app-db
pg-dev list
pg-test destroy -i test-db --force
高级用法:带副本的多环境
你甚至可以设置隔离的复制环境:
# 生产:主实例 + 副本
pg -c ~/.pgcli-prod/pg.yaml create -i primary --base-dir /data/prod
pg -c ~/.pgcli-prod/pg.yaml replica create replica -i primary
# 开发:独立的主实例 + 副本
pg -c ~/.pgcli-dev/pg.yaml create -i primary --base-dir /data/dev
pg -c ~/.pgcli-dev/pg.yaml replica create replica -i primary
每个环境维护自己的复制槽、备份 stanza 和数据目录。
故障排除
容器名称冲突
Error: container "pgcli-pg-default-app-db" already exists
原因:两个配置使用了相同的命名空间。
解决:使用不同的命名空间,或先销毁冲突的实例。
端口已被占用
Error: listen tcp 0.0.0.0:35432: bind: address already in use
原因:配置之间的端口范围重叠。
解决:使用不重叠的端口范围,并预留足够间距。
更改命名空间后找不到实例
Error: instance "app-db" exists in config but container not found
原因:创建实例后更改了配置文件中的命名空间。
解决:销毁并重建实例,或恢复命名空间更改。
总结
命名空间为单台主机上的多环境提供完全隔离:
- 独立配置:每个环境有自己的
pg.yaml
- 不同命名空间:防止容器名称冲突
- 不重叠端口:避免端口冲突
- 独立操作:每个环境使用
-c 单独管理
非常适合在同一台服务器上运行生产、开发、测试和预发布环境,互不干扰。