Red Hat系统Chef配方部署时Apache httpd服务inactive启动失败问题
问题背景
单台客户服务器承载500个网站,通过Chef实现配置部署自动化,存在偶发故障:每次启动Apache服务前都会执行配置语法校验且校验通过,但Apache仍无法正常启动,故障并非每次执行Chef配方都会触发。
现有Chef配方执行工作流
- 停止httpd服务
- 下载配置文件
- 复制全量500份站点配置
- 执行
apachectl configtest检查配置、排查error_log - 语法校验通过则启动服务
故障表现
启动环节服务状态显示为inactive,对应执行日志如下:
Executing /bin/systemctl is-active httpd ---- Begin output of /bin/systemctl is-active httpd ---- DEBUG: STDOUT: inactive DEBUG: STDERR: ---- End output of /bin/systemctl is-active httpd ---- DEBUG: Ran /bin/systemctl is-active httpd returned 3 DEBUG: Executing /bin/systemctl is-enabled httpd DEBUG: ---- Begin output of /bin/systemctl is-enabled httpd ---- DEBUG: STDOUT: enabled DEBUG: STDERR: DEBUG: ---- End output of /bin/systemctl is-enabled httpd ---- DEBUG: Ran /bin/systemctl is-enabled httpd returned 0 DEBUG: Executing /bin/systemctl start httpd DEBUG: ---- Begin output of /bin/systemctl start httpd ---- DEBUG: STDOUT: DEBUG: STDERR: Job for httpd.service failed because the control process exited with error code. See "systemctl status httpd.service" and "journalctl -xe" for details. DEBUG: ---- End output of /bin/systemctl start httpd ---- DEBUG: Ran /bin/systemctl start httpd returned 1
当前使用的Chef服务资源配置代码如下:
service 'httpd' do supports :status => true action :start ignore_failure true end
根因分析
apachectl configtest仅做配置静态语法校验,不会覆盖启动阶段的动态资源检查,这是校验通过但启动失败的核心原因,结合500站点的部署规模,偶发故障的常见触发点包括:
- 配置复制完成后立即执行校验、启动动作,部分配置依赖的SSL证书、站点目录、权限规则还未完全落盘,或正被其他进程占用,静态校验无法发现这类问题,启动时进程加载资源失败直接退出
- 旧httpd进程未完全退出:停止服务动作返回成功时,可能仍有残留工作进程在回收资源,监听端口处于TIME_WAIT状态,新进程启动时绑定端口失败
- 并发操作冲突:Chef执行启动动作的时间点,刚好撞上系统定时触发的日志轮转、SSL证书自动续期、其他运维脚本的httpd reload操作,产生资源竞争导致启动控制进程异常退出
- 现有Chef配置缺陷:
ignore_failure true会直接吞掉启动失败的错误,不会触发重试逻辑,也不会自动收集故障现场信息,导致偶发问题难以定位。
修复方案
1. 补全启停流程的资源清理逻辑
在停止httpd动作之后、复制配置之前增加预处理步骤:
- 停止服务后等待2-3秒,扫描残留httpd进程,存在残留则强制终止
- 检查httpd监听端口的占用状态,等待端口完全释放后再执行后续操作
- 全量配置复制完成后,执行
sync命令强制将文件缓存写入磁盘,等待1秒后再执行配置校验
2. 为服务启动增加重试机制
替换原有service资源配置,增加失败重试、启动后状态校验逻辑,参考配置:
service 'httpd' do supports status: true, restart: true, reload: true action :nothing retries 3 retry_delay 2 ignore_failure false end
待所有前置校验通过后再触发启动动作,单次启动失败时等待2秒自动重试,最多重试3次,可覆盖绝大多数偶发的资源竞争、端口未释放场景。
3. 强化前置校验规则
不要仅依赖apachectl configtest做静态检查,补充启动前的运行时校验项:
- 校验所有站点配置中引用的SSL证书、密钥、站点根目录路径真实存在,且httpd运行用户有对应读取权限
- 校验httpd需要监听的端口未被其他进程占用
- 校验日志目录、运行时pid目录的写入权限正常
4. 增加故障现场自动收集逻辑
移除ignore_failure true配置,若3次启动重试全部失败,自动执行诊断命令收集现场信息:
systemctl status httpd.servicejournalctl -u httpd.service --since "1 minute ago"- 导出httpd error_log最新200行内容
方便后续定位未覆盖的偶发触发点。
内容的提问来源于stack exchange,提问作者n3x
相关产品推荐
相关产品推荐

