Docker Compose多实例连PostgreSQL遇DNS解析临时失败求助
问题:Docker Compose环境中PostgreSQL服务DNS解析偶发失败及相关问题
环境信息
- Docker Compose运行
app服务40个实例(--scale app=40),宿主机配置56核CPU、256GB内存 - 所有
app实例连接同一编排内的db服务(PostgreSQL单实例,启动前已确认就绪可接受连接) - 版本信息:
- Docker 20.10.18
- Docker Compose v2.5.0
- Python 3.9.7
- psycopg2 2.9.3
- 磁盘情况:根目录
/dev/mapper/vps-vg-root总容量665G,已用355G,剩余277G(使用率57%)
偶发错误现象
DNS解析失败错误
app实例偶尔抛出psycopg2连接错误:
psycopg2.OperationalError: could not translate host name "db" to address: Temporary failure in name resolution
完整堆栈跟踪:
Traceback (most recent call last): File "/usr/local/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 3361, in _wrap_pool_connect return fn() File "/usr/local/lib/python3.9/site-packages/sqlalchemy/pool/base.py", line 310, in connect return _ConnectionFairy._checkout(self) File "/usr/local/lib/python3.9/site-packages/sqlalchemy/pool/base.py", line 868, in _checkout fairy = _ConnectionRecord.checkout(pool) File "/usr/local/lib/python3.9/site-packages/sqlalchemy/pool/base.py", line 476, in checkout rec = pool._do_get() File "/usr/local/lib/python3.9/site-packages/sqlalchemy/pool/impl.py", line 146, in _do_get self._dec_overflow() File "/usr/local/lib/python3.9/site-packages/sqlalchemy/util/langhelpers.py", line 70, in __exit__ compat.raise_( File "/usr/local/lib/python3.9/site-packages/sqlalchemy/util/compat.py", line 208, in raise_ raise exception File "/usr/local/lib/python3.9/site-packages/sqlalchemy/pool/impl.py", line 143, in _do_get return self._create_connection() File "/usr/local/lib/python3.9/site-packages/sqlalchemy/pool/base.py", line 256, in _create_connection return _ConnectionRecord(self) File "/usr/local/lib/python3.9/site-packages/sqlalchemy/pool/base.py", line 371, in __init__ self.__connect() File "/usr/local/lib/python3.9/site-packages/sqlalchemy/pool/base.py", line 666, in __connect pool.logger.debug("Error on connect(): %s", e) File "/usr/local/lib/python3.9/site-packages/sqlalchemy/util/langhelpers.py", line 70, in __exit__ compat.raise_( File "/usr/local/lib/python3.9/site-packages/sqlalchemy/util/compat.py", line 208, in raise_ raise exception File "/usr/local/lib/python3.9/site-packages/sqlalchemy/pool/base.py", line 661, in __connect self.dbapi_connection = connection = pool._invoke_creator(self) File "/usr/local/lib/python3.9/site-packages/sqlalchemy/pool/base.py", line 241, in <lambda> return lambda crec: creator() File "/app/scripts/database_connectors.py", line 112, in connector res = psycopg2.connect(**DB_PARAMETERS) File "/usr/local/lib/python3.9/site-packages/psycopg2/__init__.py", line 122, in connect conn = _connect(dsn, connection_factory=connection_factory, **kwasync) psycopg2.OperationalError: could not translate host name "db" to address: Temporary failure in name resolution
出现该错误的容器内执行psql命令同样报错:
psql -d postgres://postgres@db:5432/mydatabase psql: error: could not translate host name "db" to address: Temporary failure in name resolution
关联的共享内存错误(不同时出现)
偶尔出现PostgreSQL共享内存调整失败错误:
psycopg2.errors.DiskFull: could not resize shared memory segment "/PostgreSQL.3516559362" to 146703328 bytes: No space left on device
或SQLAlchemy包装后的错误:
sqlalchemy.exc.OperationalError: (psycopg2.errors.DiskFull) could not resize shared memory segment "/PostgreSQL.3516559362" to 146703328 bytes: No space left on device
错误原因分析
DNS解析失败的核心原因
- Docker内置DNS服务并发过载:40个
app实例同时发起DNS查询,Docker默认的docker-dns服务在高并发下出现短暂响应超时,导致部分实例解析db失败。 - 容器DNS缓存缺失/配置不合理:容器默认DNS缓存时长短、重试次数少,频繁重复查询进一步加剧DNS服务器压力。
- 宿主机网络栈资源紧张:大量容器运行导致UDP端口耗尽或DNS请求包丢失,引发解析失败。
共享内存错误的关联逻辑
虽然磁盘剩余空间充足,但PostgreSQL共享内存段存储在/dev/shm(内存文件系统)中。当宿主机内存被40个app实例+PostgreSQL大量占用时,/dev/shm空间不足,导致PostgreSQL无法调整共享内存大小,触发类似磁盘满的错误。该问题会间接影响数据库服务稳定性,可能加剧DNS解析或连接异常。
排查与解决方法
DNS解析问题排查与修复
- 监控Docker DNS服务状态:
- 查看
docker-dns进程资源占用及日志:ps aux | grep docker-dns journalctl -u docker | grep dns - 并发测试DNS解析:在多个
app容器内同时执行nslookup db,观察是否出现失败。
- 查看
- 调整容器DNS配置:
- 在
docker-compose.yml中为app服务配置外部公共DNS,绕过Docker内置DNS:services: app: dns: - 8.8.8.8 - 1.1.1.1 - 修改容器内
/etc/resolv.conf,延长DNS超时时间和重试次数:options timeout=5 attempts=3 rotate
- 在
- 优化Docker网络配置:
- 升级Docker至较新稳定版(如23.x系列),修复旧版本DNS并发缺陷。
- 修改Docker daemon配置
/etc/docker/daemon.json,优化DNS参数:{ "dns-opts": ["timeout=5", "attempts=5"], "dns": ["8.8.8.8", "1.1.1.1"] } - 重启Docker服务生效:
systemctl restart docker
共享内存问题排查与修复
- 检查
/dev/shm空间:在宿主机执行df -h /dev/shm,确认内存文件系统剩余容量。 - 调整PostgreSQL共享内存参数:
- 修改
postgresql.conf中的shared_buffers、work_mem参数,避免过度申请内存。 - 临时扩大
/dev/shm挂载大小:mount -o remount,size=16G /dev/shm - 永久生效需修改
/etc/fstab中/dev/shm的挂载参数。
- 修改
- 监控宿主机内存使用:用
top、htop工具实时监控内存占用,避免内存耗尽导致/dev/shm不足。
通用连接优化
- 为SQLAlchemy添加连接重试逻辑,应对偶发的DNS解析失败:
from sqlalchemy import create_engine from sqlalchemy.exc import OperationalError import time def create_retrying_engine(): engine = create_engine("postgresql+psycopg2://postgres@db:5432/mydatabase") max_retries = 3 for attempt in range(max_retries): try: with engine.connect(): return engine except OperationalError as e: if "Temporary failure in name resolution" in str(e) and attempt < max_retries -1: time.sleep(1) continue raise - 限制
app实例的连接池大小,减少DNS查询频率和PostgreSQL连接压力。
内容的提问来源于stack exchange,提问作者swiss_knight
相关产品推荐
相关产品推荐

