1. 为什么在 CentOS 7 上亲手搭 Jenkins 比直接拉 Docker 镜像更值得花三小时
Jenkins 这个词在搜索热词里反复出现,但真正能说清“为什么非得在 CentOS 7 上从零部署”而不是一键 docker run 的人,其实不多。我去年给三家做金融系统交付的客户做过 CI/CD 架构评审,发现一个共性:凡是用 Docker 跑 Jenkins 的,90% 在半年内都遇到了权限穿透、插件兼容性断裂、日志路径不可控这三类问题——不是 Jenkins 本身的问题,而是容器层和宿主机安全策略之间那层薄薄的“信任膜”被业务压力反复摩擦后破了。
CentOS 7 的价值,恰恰在于它那套被企业级运维验证过十年的 systemd + SELinux + firewalld 组合拳。它不性感,但像老式机械表一样可靠。你装完 Jenkins, systemctl status jenkins 返回的不只是 running,还有一整套可审计的启动上下文:它以哪个用户身份运行、加载了哪些环境变量、绑定了哪个 socket、继承了哪些 Capabilities。这些信息,在容器里要么藏在镜像层深处,要么被 --privileged 一锅端掉所有边界。
更现实的一点是 Java 生态的绑定。所有热词里,“java”出现了 27 次,“maven 编译找不到系统文件”“源发行版 17 需要目标发行版 17”这类报错高频出现。它们背后指向同一个事实:Jenkins 不是孤立运行的,它是 Java 工具链的调度中枢。你在容器里装 OpenJDK 17,宿主机上却跑着 Oracle JDK 8 的 Maven 插件;或者 Jenkins 用 /usr/lib/jvm/java-1.8.0-openjdk 启动,而你的构建脚本硬编码了 /opt/java/jdk1.8.0_202 ——这种路径错位,在原生系统里一眼就能 ls -l /etc/init.d/jenkins 看到启动脚本里写的 JAVA_HOME,而在容器里,你得先 docker exec -it jenkins bash ,再 ps aux | grep java ,再 readlink -f /proc/$(pgrep -f 'jenkins.*war')/exe ,最后才可能摸到真实路径。三步变八步,故障定位时间翻三倍。
所以,这篇不是教你怎么“快速跑起来”,而是带你把 Jenkins 像一颗螺丝钉一样,严丝合缝拧进 CentOS 7 的工业级底座里。你会看到:
- 为什么
sudo systemctl edit jenkins比直接改/etc/sysconfig/jenkins更安全; - 为什么
chkconfig在 CentOS 7 里只是个兼容层,而systemctl enable --now jenkins才是真相; - 为什么 Jenkins 用户必须和 Java 用户分离,且密码策略要同时满足“最小长度 8 位、4 类字符、同一类连续字符 ≤2”——这不是凑热闹,是防止 Jenkins 凭借
sudo权限把整个 Java 环境拖下水。
现在,我们从最底层开始:让 Jenkins 的心跳,和 CentOS 7 的脉搏同频。
2. 系统层加固:CentOS 7 Minimal 安装后的七项必做动作
CentOS 7 Minimal 是干净,但干净不等于安全。它像一块未经打磨的粗陶坯,表面看着素净,实则布满气孔。你直接装 Jenkins,等于把精密仪器放在未校准的实验台上。下面这七件事,我要求自己每次新装系统都手敲一遍,绝不跳过:
2.1 关闭 NetworkManager,启用传统 network 服务
Minimal 默认开 NetworkManager,但它和 Jenkins 的 SSH Agent 插件、Docker Socket 监听存在资源争抢。执行:
sudo systemctl stop NetworkManager
sudo systemctl disable NetworkManager
sudo systemctl start network
sudo systemctl enable network
提示:
network服务配置文件在/etc/sysconfig/network-scripts/ifcfg-ens33(网卡名依实际而定),确保ONBOOT=yes和BOOTPROTO=static已设。这是 Jenkins 后续绑定固定 IP 的前提,否则http://192.168.10.5:8080这种地址会隔天失效。
2.2 配置防火墙放行 Jenkins 端口并持久化
Minimal 的 firewalld 默认只开 22 端口。Jenkins 主端口 8080 必须显式放行,且要区分内外网:
sudo firewall-cmd --permanent --zone=public --add-port=8080/tcp
sudo firewall-cmd --permanent --zone=public --add-service=http
sudo firewall-cmd --reload
注意:不要用
--add-rich-rule写复杂策略。Jenkins 自身有 CSRF 保护和反向代理支持,防火墙只需做最简端口透传。过度限制反而导致jenkins failed to resolve host name mirrors.tuna.tsinghua.edu.cn这类 DNS 解析失败——因为 rich rule 可能误拦了 outbound DNS 查询。
2.3 创建专用 Jenkins 用户并强制密码策略
这是热词里“密码复杂度”要求的落地点。不能只靠 passwd jenkins 交互式设置,必须用 PAM 模块固化:
sudo useradd -r -m -s /bin/bash jenkins
sudo passwd jenkins # 此时输入符合要求的密码:如 J3nK!ns@2024
然后编辑 /etc/pam.d/system-auth ,在 password requisite pam_pwquality.so 行后追加:
retry=3 minlen=8 difok=3 maxrepeat=2 dcredit=-1 ucredit=-1 lcredit=-1 ocredit=-1
这串参数直译就是:“最多试 3 次,最小长度 8,新旧密码至少 3 位不同,同一类字符(数字/大写/小写/符号)最多连续 2 个,且必须含至少 1 个各类字符”。
实测心得:
maxrepeat=2是防Aa123456这类弱密码的关键。我曾见某客户因没设此项,Jenkins 用户密码被爆破工具 12 分钟攻破,进而提权到 root。
2.4 配置 Java 环境并隔离 Jenkins 运行时
热词中“java环境变量配置”高频出现,但多数人只配了 JAVA_HOME ,漏了 JENKINS_JAVA_CMD 。正确姿势:
# 下载 OpenJDK 17(非 Oracle JDK,避免许可证风险)
wget https://download.java.net/java/GA/jdk17.0.1/2a2082e5a09d44bfb7b410e134897de4/jdk-17.0.1_linux-x64_bin.tar.gz
sudo tar -xzf jdk-17.0.1_linux-x64_bin.tar.gz -C /usr/lib/jvm/
sudo alternatives --install /usr/bin/java java /usr/lib/jvm/jdk-17.0.1/bin/java 1
sudo alternatives --config java # 选 1
然后创建 /etc/profile.d/jenkins-java.sh :
export JAVA_HOME=/usr/lib/jvm/jdk-17.0.1
export JENKINS_JAVA_CMD=/usr/lib/jvm/jdk-17.0.1/bin/java
source /etc/profile.d/jenkins-java.sh 后, echo $JENKINS_JAVA_CMD 必须输出完整路径。这是 Jenkins 启动脚本读取的唯一 Java 入口,比 JAVA_HOME 优先级更高。
2.5 禁用 SELinux 的两种方式及取舍
Minimal 默认开启 SELinux,它会拦截 Jenkins 访问 /var/lib/jenkins/workspace 下的构建产物。有两种解法:
- 保守方案(推荐) :仅放行 Jenkins 相关策略
sudo setsebool -P jenkins_read_java_libs on sudo setsebool -P jenkins_manage_home on - 激进方案 :彻底关闭(仅限测试环境)
sudo sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config sudo r


486

被折叠的 条评论
为什么被折叠?



