1. 核心架构
plaintext
代码提交 → Webhook → Jenkins Master → Agent节点 → 制品库/集群
↓
Pipeline执行(Stage)
2. 部署安装
2.1 Docker Compose(推荐)
yaml
version: '3.8'
services:
jenkins:
image: jenkins/jenkins:lts-jdk17
container_name: jenkins
restart: unless-stopped
privileged: true
user: root
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:
driver: local
bash
docker-compose up -d
docker exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword
2.2 Kubernetes Helm
bash
helm install jenkins jenkins/jenkins -n jenkins <<'EOF'
controller:
image: jenkins/jenkins
tag: 2.426.3-lts-jdk17
persistence:
enabled: true
storageClass: "nfs-client"
size: 50Gi
resources:
requests: { cpu: 500m, memory: 1Gi }
limits: { cpu: 2000m, memory: 4Gi }
ingress:
enabled: true
hostName: jenkins.example.com
agent:
enabled: true
image: jenkins/inbound-agent:latest
EOF
2.3 必装插件
表格
| 插件 | 用途 |
|---|---|
| workflow-aggregator, pipeline-stage-view | Pipeline核心 |
| git, docker, docker-workflow, kubernetes | 代码/容器/K8s |
| role-based-authorization-strategy | 权限控制 |
| warnings-ng, email-ext, slack | 检查/通知 |
3. 核心配置
3.1 凭证类型
表格
| 类型 | 用途 |
|---|---|
| Username/Password | Git认证、LDAP |
| Secret Text | API Token |
| SSH + Private Key | Git SSH |
| Docker Cert | 镜像仓库 |
3.2 Jenkinsfile - 声明式Pipeline
groovy
@Library('shared-library') _
pipeline {
agent {
kubernetes {
yaml '''
apiVersion: v1
kind: Pod
spec:
containers:
- name: maven
image: maven:3.9-eclipse-temurin-17
command: ["sleep", "infinity"]
resources:
requests: { memory: "1Gi", cpu: "500m" }
- name: kubectl
image: bitnami/kubectl:1.29
command: ["sleep", "infinity"]
- name: docker
image: docker:24-dind
securityContext: { privileged: true }
'''
}
}
options {
timestamps()
timeout(time: 1, unit: 'HOURS')
buildDiscarder(logRotator(numToKeepStr: '30'))
}
parameters {
choice(name: 'ENVIRONMENT', choices: ['dev', 'staging', 'production'])
booleanParam(name: 'SKIP_TESTS', defaultValue: false)
}
environment {
REGISTRY = 'harbor.example.com'
REGISTRY_CREDENTIALS = 'harbor-credentials'
}
stages {
stage('Checkout') {
steps {
script { env.IMAGE_TAG = "${env.BUILD_NUMBER}" }
checkout scm
}
}
stage('Build & Test') {
parallel {
stage('Unit Test') {
when { expression { !params.SKIP_TESTS } }
steps { container('maven') { sh 'mvn clean test' } }
}
stage('Build JAR') {
steps { container('maven') { sh 'mvn clean package -DskipTests' } }
}
}
}
stage('Docker Build & Push') {
steps {
script {
def img = docker.build("${env.REGISTRY}/myapp:${env.IMAGE_TAG}")
docker.withRegistry("https://${env.REGISTRY}", env.REGISTRY_CREDENTIALS) {
img.push()
img.push('latest')
}
}
}
}
stage('Deploy') {
steps {
container('kubectl') {
sh '''
sed "s|IMAGE_TAG|${IMAGE_TAG}|g" k8s/deployment.yaml | kubectl apply -f -
kubectl rollout status deployment/myapp -n ${ENVIRONMENT} --timeout=300s
'''
}
}
}
stage('Health Check') {
steps {
script {
def status = sh(
script: "kubectl exec -n ${ENVIRONMENT} deployment/myapp -- curl -sf localhost:8080/health",
returnStatus: true
)
if (status != 0) error "Health check failed"
}
}
}
}
post {
always { junit '**/target/surefire-reports/*.xml' }
success { echo "✅ Deployed to ${params.ENVIRONMENT}" }
failure { echo "❌ Build failed" }
cleanup { cleanWs() }
}
}
3.3 脚本式Pipeline
groovy
node('docker-agent') {
try {
stage('Build') {
docker.image('maven:3.9').inside { sh "mvn clean package" }
}
stage('Docker Push') {
def img = docker.build("${HARBOR}/myapp:${BUILD_NUMBER}")
docker.withRegistry("https://${HARBOR}", 'harbor-cred') { img.push() }
}
} catch (e) {
currentBuild.result = 'FAILURE'
throw e
}
}
3.4 Shared Libraries
groovy
// vars/deploy.groovy
def call(Map config) {
sh """
kubectl set image deployment/myapp myapp=${config.image} -n ${config.namespace}
kubectl rollout status deployment/myapp -n ${config.namespace} --timeout=300s
"""
}
// Jenkinsfile使用
@Library('my-library@main') _
pipeline {
stages {
stage('Deploy') {
steps { deploy(namespace: 'prod', image: 'harbor.io/myapp:latest') }
}
}
}
3.5 Webhook配置
bash
# GitLab: http://jenkins/project/job-name, Trigger: Push events
# GitHub: http://jenkins/github-webhook/, Trigger: Push, PR
4. 常用操作
4.1 CLI
bash
curl -O http://jenkins/jnlpJars/jenkins-cli.jar
java -jar jenkins-cli.jar -s http://jenkins:8080/ list-jobs
java -jar jenkins-cli.jar -s http://jenkins:8080/ build my-job -s
4.2 REST API
bash
curl -s -u admin:token http://jenkins:8080/job/my-job/lastBuild/api/json
curl -X POST http://jenkins:8080/job/my-job/build -u admin:token \
-d 'json={"parameter": [{"name": "ENV", "value": "prod"}]}'
4.3 备份恢复
bash
# 备份
tar -czf jenkins_$(date +%Y%m%d).tar.gz --exclude='workspace' /var/jenkins_home
# 恢复
tar -xzf jenkins_backup.tar.gz -C /var/jenkins_home && curl -X POST http://jenkins:8080/restart
4.4 Agent配置(Kubernetes云)
plaintext
Name: kubernetes | Kubernetes URL: https://kubernetes.default.svc
Kubernetes Namespace: jenkins | Jenkins URL: http://jenkins:8080
Pod Template: Image: jenkins/inbound-agent:latest, Idle minutes: 10
5. 问题排查
5.1 构建卡住
plaintext
排查:系统管理 → 节点管理 → 检查状态/日志 | 验证:telnet jenkins 50000
解决:Agent离线需重启服务;无Executor需增加数量;资源不足增加限制
5.2 插件冲突
plaintext
排查:系统日志 → 过滤ERROR
解决:禁用可疑插件、降级稳定版本、清除缓存 rm -rf plugins/*.bak
5.3 权限问题
plaintext
配置:系统管理 → Manage and Assign Roles
创建角色:globalRoles(overall/read, job/build)、projectRoles(pattern: "dev-.*")
分配:Assign Roles → 用户 → 角色
6. 最佳实践
6.1 安全加固
groovy
// Master禁止构建:系统管理 → 节点管理 → Master → executors: 0
// 凭证安全:定期轮换、使用API Token、限制使用范围
matrixAuthorizationStrategy {
permissions {
permission('hudson.model.Hudson.Administer:admin')
permission('hudson.model.Item.Build:authenticated')
}
}
6.2 资源优化
groovy
agent {
kubernetes {
yaml '''
spec:
containers:
- name: builder
resources:
requests: { memory: "512Mi", cpu: "250m" }
limits: { memory: "1Gi", cpu: "1000m" }
'''
}
}
// 清理策略:Build record age to keep: 30 days
6.3 Pipeline模板化
groovy
// vars/ciPipeline.groovy
def call(Map config, Closure body) {
pipeline {
agent { label config.agentLabel ?: 'any' }
stages { stage('Test') { steps { script { body() } } } }
post { always { cleanWs() } }
}
}
// 使用:ciPipeline(versionPrefix: 'v1.0') { sh 'mvn test' }
6.4 制品管理
groovy
// Nexus上传
sh "curl -u ${NEXUS_USER}:${NEXUS_PASS} -X PUT 'http://nexus:8081/repository/releases/${path}' -T ${path}"
// Harbor推送
docker.withRegistry("https://harbor.example.com", 'harbor-cred') {
docker.build("harbor.io/${SERVICE}:${VERSION}").push()
}
6.5 蓝绿/金丝雀部署
groovy
// 蓝绿部署
stage('Blue-Green Deploy') {
steps {
script {
def activeNS = sh(
script: 'kubectl get ns -l deploy=active -o jsonpath="{.items[0].metadata.name}"',
returnStdout: true
).trim()
def newNS = activeNS == 'prod-blue' ? 'prod-green' : 'prod-blue'
sh """
kubectl apply -n ${newNS} -f k8s/
kubectl set image deployment/myapp myapp=${IMAGE_TAG} -n ${newNS}
kubectl rollout status deployment/myapp -n ${newNS}
kubectl label namespace ${newNS} deploy=active --overwrite
kubectl label namespace ${activeNS} deploy=standby --overwrite
"""
}
}
}
// 金丝雀部署
stage('Canary Deploy') {
steps {
script {
sh """
kubectl set image deployment/myapp-canary myapp=${IMAGE_TAG} -n production
kubectl autoscale deployment myapp-canary -n production --min=1 --max=3
sleep 60
"""
}
}
}
快速命令
bash
docker exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword # 获取初始密码
curl -X POST http://jenkins:8080/restart # 重启Jenkins
docker exec jenkins sed -i 's/<useSecurity>true/<useSecurity>false/' /var/jenkins_home/config.xml # 禁用安全(紧急)
docker exec jenkins rm -rf /var/jenkins_home/workspace/* # 清理缓存