如何在生产环境安全地开启慢日志?

解读

面试官问“生产环境”“安全地”开启慢日志,核心考察三点:

  1. 对 PHP-FPM 慢日志机制与 MySQL 慢查询日志机制的区别与配置细节是否熟悉;
  2. 是否具备“最小可用、最小暴露、最小影响”的线上变更意识;
  3. 能否把日志采集、存储、脱敏、轮转、监控闭环讲清楚,避免“开了日志却没人看”或“日志爆盘”的运维事故。
    国内大厂/金融/政务云等场景对 GDPR、等保 2.0、国密合规要求极高,答案必须体现“可审计、可回滚、可告警”。

知识点

  1. PHP-FPM slowlog:
    request_slowlog_timeout、slowlog 文件路径、php_admin_value[disable_functions] 防止 Web 用户读日志。
  2. MySQL slow_query_log:
    long_query_time、log_slow_extra、log_timestamps、max_slowlog_size(8.0+)、slow_log 表转存。
  3. 内核级安全:
    日志目录挂载独立 inode、noexec/nodev/nosuid、auditd 监控 chmod/chown、SELinux/AppArmor 策略。
  4. 敏感信息脱敏:
    正则滤身份证号、手机号、银行卡号;国密 SM4 加密后再落盘。
  5. 日志轮转:
    logrotate copytruncate + compress,按 100 MB 切割、保留 14 天,避免 IO 抖动。
  6. 观测与告警:
    日志接入 ELK/ClickHouse,Grafana 配置“单实例 5 min 内慢查询 >100 条”即飞书/企微/钉钉告警;
    Prometheus + Exporter 采集 phpfpm_slow_requests_total。
  7. 变更流程:
    国内互联网标准“灰度→监控→全量”三步走;变更单需三级审批,保留 30 天回滚脚本。

答案

线上开启慢日志的“七步安全法”:

  1. 评估窗口:选低峰时段(通常 02:00–05:00),先在预发布环境压测,确认 IO 增幅 <3%。
  2. 目录隔离:
    mkdir -p /var/log/php-slow /var/log/mysql-slow
    chown www-data:adm /var/log/php-slow
    chmod 0750 /var/log/php-slow
    挂载独立 5 GB lv,加 attr +a 防止误删。
  3. PHP-FPM 配置:
    [www]
    request_slowlog_timeout = 1s
    slowlog = /var/log/php-slow/www-$pool.log
    php_admin_value[disable_functions] = exec,passthru,shell_exec,system
    重载:systemctl reload php-fpm,禁止直接 restart,防止长连接 502。
  4. MySQL 配置:
    SET GLOBAL slow_query_log = 1;
    SET GLOBAL long_query_time = 0.5;
    SET GLOBAL log_slow_extra = 1;
    将 slow_log 表改为 CSV 引擎并 truncate,避免 mysql 库膨胀。
  5. 脱敏与加密:
    rsyslog 模板中用 mmexternal 调用国密 SM4 动态库,对 18 位身份证、11 位手机全字段加密;
    日志文件属组 adm,禁止 www-data 读取,防止 WebShell 下载。
  6. 轮转与清理:
    /etc/logrotate.d/php-slow:
    /var/log/php-slow/*.log {
    daily
    rotate 14
    compress
    delaycompress
    missingok
    notifempty
    copytruncate
    postrotate
    systemctl reload php-fpm > /dev/null 2>&1 || true
    endscript
    }
    加 cron 每日 06:00 执行,轮转后立刻 fsync 刷盘。
  7. 监控与回滚:
    日志接入公司统一 Kafka → Flink → ClickHouse;
    Grafana 面板配置“单实例 1 min 慢请求率突增 3σ”即告警;
    保留 Ansible 回滚剧本:关闭慢日志只需 SET GLOBAL slow_query_log = 0; 并 reload php-fpm,30 s 内可回滚。
    变更记录录入 Jira,审计保存 180 天,满足等保要求。

拓展思考

  1. 若业务使用容器 sidecar 模式,慢日志 stdout 直接打到宿主机,如何避免 Docker json-file driver 造成 inode 耗尽?
    答:使用 local 日志驱动 + max-size=50m,max-file=5,并挂载 hostPath 到独立 SSD 盘,sidecar 里用 Vector 实时吐到 Kafka,不落盘。
  2. 当慢日志里出现“password=***”字段,如何证明已做脱敏?
    答:在等保测评时提供 rsyslog 的 mmexternal 调用脚本、SM4 加密密钥托管在 KMS 的审计截图、以及第三方渗透测试报告,证明无法逆向。
  3. 如果开启慢日志后 QPS 下跌 5%,如何定位是 IO 还是锁竞争?
    答:用 perf top -p pgrep php-fpm 观察 __write_nocancel 占比;同时 iostat -x 1 看 %util;若 IO 高则升高 log_slow_extra=0 减少行数;若 mutex 竞争高则调低 request_slowlog_timeout 精度,或改用异步日志(PHP 8.3 的 zend_observer 接口)。