环境搭建:本地CI环境模拟、Docker CI节点、常用日志采集工具配置

做CI失败日志分析,第一道坎往往不是分析本身,而是环境。我记得刚接手一个老项目时,开发环境、测试环境、CI环境三套配置各不一样,构建日志里的路径、依赖版本、权限全对不上,根本没法复现问题。后来我学乖了:必须先把环境搞成“一次构建,到处调试”的状态。所以这一章,我们先把实验环境搭起来。

3.1 本地CI环境模拟

说白了,就是在你笔记本上跑一套简易版的CI服务。我个人习惯用Jenkins + Docker compose来模拟。为什么选Jenkins?生态成熟,插件多,Pipeline脚本能直接拷到生产CI里用。下面是我常用的docker-compose.yml:

version: '3.8'
services:
  jenkins:
    image: jenkins/jenkins:lts
    container_name: jenkins-master
    ports:
      - "8080:8080"
      - "50000:50000"
    volumes:
      - jenkins_home:/var/jenkins_home
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - JAVA_OPTS=-Djenkins.install.runSetupWizard=false
volumes:
  jenkins_home:
挂载宿主机的docker.sock,让Jenkins能直接调用Docker。这样在Pipeline里就能动态创建/销毁CI节点,模拟多环境。

避坑指南:我曾经直接把Jenkins解压装在Ubuntu上,结果系统Java版本和Jenkins不匹配,折腾了半天。换成容器化部署后,再没出过这种低级问题。你想想看,容器多省心。

3.2 Docker CI节点

本地Jenkins跑起来后,得给它配几个“机器人”来干活。Docker CI节点,就是用容器做构建执行环境。我建议用官方的jenkins/agent镜像,但最好自己封装一层,加些常用工具:

FROM jenkins/agent:latest-jdk11
USER root
RUN apt-get update && apt-get install -y \
    python3-pip \
    jq \
    netcat \
    && rm -rf /var/lib/apt/lists/*
RUN pip3 install --no-cache-dir requests pyyaml
USER jenkins

然后让Jenkins master通过SSH或JNLP协议自动拉起这个agent镜像。每个构建任务独立容器,日志从容器里直接输出,干净利落。

注意:docker.sock权限问题!把宿主机root的socket挂给Jenkins容器后,Jenkins容器内的jenkins用户默认没有读写权限。我踩过这个坑,最后用chmod 666 /var/run/docker.sock或在compose里指定用户ID才搞定。生产环境千万别这么干,本地模拟可以凑合用。

3.3 常用日志采集工具配置

环境搭好了,构建跑起来了,日志从哪来?不能每次都ssh进容器看控制台吧。咱们得把日志“吸”到统一地方。这里我推荐Filebeat——轻量、配置简单,适合初学者。下面是针对Docker容器的Filebeat配置:

filebeat.inputs:
- type: container
  paths:
    - '/var/lib/docker/containers/*/*.log'
  processors:
    - add_docker_metadata:
        host: "unix:///var/run/docker.sock"

output.elasticsearch:
  hosts: ["localhost:9200"]
  index: "ci-logs-%{+yyyy.MM.dd}"

这段配置让Filebeat自动监听所有Docker容器的日志,加上容器元数据(镜像名称、环境变量等),然后发送到本地Elasticsearch。后续章节的日志分析全靠这个数据源。

为什么选Filebeat? 1)内存占用约20MB,不影响CI性能;2)原生支持Docker日志驱动;3)和ELK全家桶无缝集成。生产环境也用它。

当然,还有Fluentd、Logstash等选择。我简单对比一下:

工具优势劣势适用场景
Filebeat极轻量、配置简洁、原生Docker支持数据处理能力弱纯采集转发,尤其适合容器日志
Fluentd丰富的插件生态、内置缓冲Ruby性能开销稍大需要复杂解析/过滤的场景
Logstash强大的Grok解析、易调试资源占用高(Java)数据预处理要求高的全量采集

我个人建议:刚开始用Filebeat就行,后续如果发现解析能力不够,可以在Filebeat和Elasticsearch之间串一个Logstash。

CI失败日志分析环境搭建流程图 本地CI服务 (Jenkins) 调度Pipeline Docker CI节点 临时构建容器 构建日志输出 stdout / 文件 Filebeat日志采集 监听容器日志 Elasticsearch 存储索引日志 日志分析平台 Kibana / 脚本分析 注意:Filebeat需挂载 docker.sock和容器日志 目录到宿主机 构建日志格式建议 统一为JSON,方便 后续结构化分析

整张图的逻辑很清晰:Jenkins调度Docker容器跑构建,容器日志被Filebeat自动采集,发到Elasticsearch,最后用Kibana或脚本做归因分析。这个栈我用了两年,本地调试和线上唯一区别就是Elasticsearch集群规模。

好了,环境搭起来后,下一阶段就是真正去抓日志、拆日志、查根因了。不过那是后面几章的内容。这章你先把docker-compose起起来,Filebeat配上,能用curl调一下Elasticsearch的索引API看到日志进来,就算通关。

一次性检查清单:
  • ✅ Jenkins页面上Pipeline能正常跑完
  • ✅ 每次构建启动一个新Docker容器(容器名包含构建编号)
  • ✅ Filebeat日志中没有错误,ES里有生成ci-logs-*索引
  • ✅ Kibana(如果安装了)能搜索到最近构建日志