Rocky Linux 8.5部署Jenkins CI/CD系统实战指南
1. 项目概述
在当今DevOps实践中,Jenkins作为老牌自动化服务器依然占据重要地位。最近我在Rocky Linux 8.5上完整部署了一套支持容器化构建的Jenkins CI/CD系统,过程中发现不少官方文档未提及的细节问题。本文将分享从系统准备到流水线优化的全流程实战经验,特别针对混合架构环境下的常见痛点提供解决方案。
2. 环境准备与基础安装
2.1 Rocky Linux系统调优
在安装Jenkins前,需要对操作系统进行针对性优化:
# 禁用不必要的服务 sudo systemctl disable --now firewalld sudo dnf remove -y firewalld # 配置SWAP(当物理内存<8GB时建议) sudo dd if=/dev/zero of=/swapfile bs=1M count=4096 sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab # 修改文件描述符限制 echo '* soft nofile 65535' | sudo tee -a /etc/security/limits.conf echo '* hard nofile 65535' | sudo tee -a /etc/security/limits.conf注意:生产环境请根据实际安全需求配置防火墙规则,此处禁用仅用于简化测试环境配置
2.2 Jenkins核心安装
使用官方仓库安装最新LTS版本:
sudo dnf install -y wget sudo wget -O /etc/yum.repos.d/jenkins.repo \ https://pkg.jenkins.io/redhat-stable/jenkins.repo sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key sudo dnf install -y jenkins java-11-openjdk-devel sudo systemctl enable --now jenkins安装后需检查关键目录权限:
sudo chown -R jenkins:jenkins /var/lib/jenkins sudo chmod 755 /var/log/jenkins3. 容器化构建环境配置
3.1 Docker集成方案
为支持容器化构建,需要配置Docker-in-Docker方案:
sudo dnf config-manager --add-repo=https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install -y docker-ce docker-ce-cli containerd.io sudo usermod -aG docker jenkins sudo systemctl restart docker jenkins在Jenkins全局配置中设置Docker路径:
Manage Jenkins -> Configure System -> 云 -> Docker Docker Host URI: unix:///var/run/docker.sock3.2 Podman作为备选方案
对于无root环境,可选用Podman:
sudo dnf install -y podman sudo mkdir -p /home/jenkins/.local/share/containers sudo chown -R jenkins:jenkins /home/jenkins在Jenkinsfile中使用时需注意:
pipeline { agent any stages { stage('Build') { steps { sh ''' podman build -t myapp . podman tag myapp localhost:5000/myapp podman push localhost:5000/myapp ''' } } } }4. 多平台流水线实战
4.1 混合架构构建方案
针对ARM/x86混合环境,使用buildx实现跨平台构建:
stage('Multi-arch Build') { steps { script { docker.withRegistry('https://registry.example.com', 'docker-creds') { docker.image('docker.io/docker/buildx:latest').inside('--privileged') { sh ''' docker buildx create --use docker buildx build --platform linux/amd64,linux/arm64 \ -t ${IMAGE_NAME}:${BUILD_NUMBER} \ -t ${IMAGE_NAME}:latest \ --push . ''' } } } } }4.2 动态节点分配策略
在Jenkinsfile中实现智能节点选择:
def getBuilder(label) { def cloud = Jenkins.instance.clouds.find { it.name == 'docker-cloud' } def template = cloud.templates.find { it.labelString == label } return template } pipeline { parameters { choice(name: 'ARCH', choices: ['amd64', 'arm64'], description: 'Target architecture') } agent none stages { stage('Build') { agent { docker { image "docker:${params.ARCH == 'arm64' ? 'arm64v8' : ''}/dind" label "${params.ARCH}-builder" args '--privileged -v /var/run/docker.sock:/var/run/docker.sock' } } steps { sh 'docker build -t app .' } } } }5. 性能优化与安全加固
5.1 JVM参数调优
修改/etc/sysconfig/jenkins中的JAVA_OPTS:
JAVA_OPTS="-Djava.awt.headless=true \ -Xms2g -Xmx4g \ -XX:MaxMetaspaceSize=512m \ -XX:+UseG1GC \ -XX:+ParallelRefProcEnabled \ -XX:+DisableExplicitGC \ -Djenkins.install.runSetupWizard=false"5.2 凭据安全存储
使用HashiCorp Vault集成方案:
@Library('vault-library') _ pipeline { environment { DB_PASSWORD = vault( path: 'secret/data/jenkins', key: 'db_password' ) } stages { stage('Deploy') { steps { sh 'echo $DB_PASSWORD | docker login -u _json_key --password-stdin registry.example.com' } } } }6. 典型问题排查指南
6.1 插件依赖冲突
常见错误现象:
java.lang.NoSuchMethodError: org.jenkinsci.plugins.workflow.steps.StepContext.get解决方案:
- 进入
Manage Jenkins -> Script Console - 执行以下Groovy脚本检查冲突:
Jenkins.instance.pluginManager.plugins .findAll { it.isActive && it.hasUpdate() } .each { println "${it.shortName}: ${it.version} -> ${it.getUpdateInfo().version}" }- 通过
--plugins.txt文件批量降级插件版本
6.2 容器内DNS解析失败
在docker-agent模板中添加额外参数:
{ "HostConfig": { "Dns": ["8.8.8.8", "114.114.114.114"], "DnsOptions": ["timeout:2", "attempts:2"], "NetworkMode": "host" } }7. 监控与日志方案
7.1 Prometheus监控集成
配置/etc/prometheus/jenkins.yml:
scrape_configs: - job_name: 'jenkins' metrics_path: '/prometheus' static_configs: - targets: ['jenkins.example.com:8080']在Jenkins中安装Prometheus插件后,调整采集间隔:
Manage Jenkins -> Configure System -> Prometheus Collection Interval: 15s Enable perBuildMetrics: true7.2 日志集中管理
使用Fluentd转发日志到ELK:
<plugin> <groupId>org.jenkins-ci.plugins</groupId> <artifactId>fluentd-plugin</artifactId> <version>0.10.0</version> <configuration> <host>fluentd.example.com</host> <port>24224</port> <tag>jenkins.${JOB_NAME}.${BUILD_NUMBER}</tag> <bufferSize>1000</bufferSize> </configuration> </plugin>8. 扩展功能实现
8.1 自动伸缩构建节点
使用Kubernetes插件动态创建pod:
apiVersion: "v1" kind: "Pod" metadata: labels: jenkins: "agent" spec: containers: - name: "jnlp" image: "jenkins/inbound-agent:4.3-4" resources: limits: cpu: "2" memory: "4Gi" requests: cpu: "500m" memory: "1Gi" - name: "dind" image: "docker:dind" securityContext: privileged: true volumeMounts: - name: "docker-graph-storage" mountPath: "/var/lib/docker"8.2 制品仓库集成
配置Nexus3作为私有仓库:
withCredentials([usernamePassword( credentialsId: 'nexus-creds', usernameVariable: 'NEXUS_USER', passwordVariable: 'NEXUS_PASS' )]) { sh ''' curl -u $NEXUS_USER:$NEXUS_PASS \ -X POST 'http://nexus.example.com/service/rest/v1/components?repository=maven-releases' \ -H "Content-Type: multipart/form-data" \ -F maven2.groupId=com.example \ -F maven2.artifactId=myapp \ -F maven2.version=1.0.0 \ -F maven2.asset1=@target/myapp.jar \ -F maven2.asset1.extension=jar ''' }