← 返回首页
🔧

Jenkins:自动化服务器

📂 devops ⏱ 4 min 614 words

Jenkins:自动化服务器

Jenkins简介

Jenkins是一个开源的自动化服务器,用于构建、测试和部署软件。它支持丰富的插件生态系统,可以集成各种DevOps工具。

安装Jenkins

Docker安装

# 运行Jenkins
docker run -d \
  --name jenkins \
  -p 8080:8080 \
  -p 50000:50000 \
  -v jenkins_home:/var/jenkins_home \
  jenkins/jenkins:lts

# 获取初始密码
docker exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword

Docker Compose安装

# docker-compose.yml
version: '3.8'
services:
  jenkins:
    image: jenkins/jenkins:lts
    container_name: jenkins
    ports:
      - "8080:8080"
      - "50000:50000"
    volumes:
      - jenkins_home:/var/jenkins_home
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - JAVA_OPTS=-Xmx2g
    restart: unless-stopped

volumes:
  jenkins_home:

Pipeline基础

声明式Pipeline

// Jenkinsfile
pipeline {
    agent any

    parameters {
        choice(
            name: 'ENVIRONMENT',
            choices: ['dev', 'staging', 'production'],
            description: '部署环境'
        )
        string(
            name: 'VERSION',
            defaultValue: 'latest',
            description: '应用版本'
        )
    }

    stages {
        stage('Checkout') {
            steps {
                checkout scm
            }
        }

        stage('Build') {
            steps {
                sh 'docker build -t myapp:${VERSION} .'
            }
        }

        stage('Test') {
            steps {
                sh 'docker run --rm myapp:${VERSION} npm test'
            }
        }

        stage('Push') {
            steps {
                withCredentials([usernamePassword(
                    credentialsId: 'registry-credentials',
                    usernameVariable: 'USER',
                    passwordVariable: 'PASS'
                )]) {
                    sh 'echo $PASS | docker login -u $USER --password-stdin registry.example.com'
                    sh 'docker tag myapp:${VERSION} registry.example.com/myapp:${VERSION}'
                    sh 'docker push registry.example.com/myapp:${VERSION}'
                }
            }
        }

        stage('Deploy') {
            steps {
                script {
                    if (params.ENVIRONMENT == 'production') {
                        input message: '确认部署到生产环境?'
                    }
                }
                sh """
                    kubectl set image deployment/myapp \
                        myapp=registry.example.com/myapp:${VERSION} \
                        -n ${params.ENVIRONMENT}
                """
            }
        }
    }

    post {
        success {
            slackSend(
                channel: '#devops',
                message: "构建成功: ${env.JOB_NAME} #${env.BUILD_NUMBER}"
            )
        }
        failure {
            slackSend(
                channel: '#devops',
                message: "构建失败: ${env.JOB_NAME} #${env.BUILD_NUMBER}"
            )
        }
    }
}

脚本式Pipeline

node {
    stage('Checkout') {
        checkout scm
    }

    stage('Build') {
        sh 'docker build -t myapp:latest .'
    }

    stage('Test') {
        try {
            sh 'docker run --rm myapp:latest npm test'
        } catch (e) {
            currentBuild.result = 'FAILURE'
            throw e
        }
    }

    stage('Deploy') {
        if (currentBuild.result == null) {
            sh 'kubectl apply -f k8s/'
        }
    }
}

多分支Pipeline

// 自动为每个分支创建Pipeline
pipeline {
    agent {
        kubernetes {
            yaml '''
                spec:
                  containers:
                  - name: jnlp
                    image: jenkins/inbound-agent:latest
                  - name: docker
                    image: docker:latest
                    command: ['cat']
                    tty: true
            '''
        }
    }

    stages {
        stage('Build') {
            steps {
                container('docker') {
                    sh 'docker build -t myapp:${GIT_BRANCH} .'
                }
            }
        }
    }
}

共享库

// vars/standardPipeline.groovy
def call(Map config) {
    pipeline {
        agent any
        stages {
            stage('Build') {
                steps {
                    sh "docker build -t ${config.image}:${config.tag} ."
                }
            }
            stage('Test') {
                steps {
                    sh "docker run --rm ${config.image}:${config.tag} npm test"
                }
            }
            stage('Deploy') {
                steps {
                    sh "kubectl set image deployment/${config.app} ${config.app}=${config.image}:${config.tag}"
                }
            }
        }
    }
}

// Jenkinsfile中使用
@Library('my-shared-library') _

standardPipeline(
    image: 'registry.example.com/myapp',
    tag: '1.0.0',
    app: 'myapp'
)

凭证管理

// 使用Jenkins凭证
withCredentials([
    usernamePassword(
        credentialsId: 'docker-registry',
        usernameVariable: 'DOCKER_USER',
        passwordVariable: 'DOCKER_PASS'
    ),
    string(
        credentialsId: 'kubeconfig',
        variable: 'KUBECONFIG'
    )
]) {
    sh 'docker login -u $DOCKER_USER -p $DOCKER_PASS'
    sh 'kubectl --kubeconfig=$KUBECONFIG get pods'
}

定时构建

// Jenkinsfile
pipeline {
    agent any

    triggers {
        // 每天凌晨2点构建
        cron('H 2 * * *')
        // 每15分钟检查代码变更
        pollSCM('H/15 * * * *')
    }

    stages {
        stage('Build') {
            steps {
                sh './build.sh'
            }
        }
    }
}

实践:企业级Pipeline

pipeline {
    agent {
        kubernetes {
            yaml '''
                spec:
                  serviceAccountName: jenkins
                  containers:
                  - name: docker
                    image: docker:latest
                    command: ['cat']
                    tty: true
                  - name: kubectl
                    image: bitnami/kubectl:latest
                    command: ['cat']
                    tty: true
            '''
        }
    }

    environment {
        REGISTRY = 'registry.example.com'
        IMAGE = "${REGISTRY}/myapp"
        COMMIT = sh(script: 'git rev-parse --short HEAD', returnStdout: true).trim()
    }

    stages {
        stage('Lint & Test') {
            steps {
                sh 'npm ci'
                sh 'npm run lint'
                sh 'npm test'
            }
        }

        stage('Build Image') {
            steps {
                container('docker') {
                    sh "docker build -t ${IMAGE}:${COMMIT} ."
                    withCredentials([usernamePassword(
                        credentialsId: 'registry-creds',
                        usernameVariable: 'USER',
                        passwordVariable: 'PASS'
                    )]) {
                        sh "echo $PASS | docker login -u $USER --password-stdin $REGISTRY"
                        sh "docker push ${IMAGE}:${COMMIT}"
                    }
                }
            }
        }

        stage('Deploy') {
            parallel {
                stage('Staging') {
                    steps {
                        container('kubectl') {
                            sh "kubectl set image deployment/myapp myapp=${IMAGE}:${COMMIT} -n staging"
                            sh "kubectl rollout status deployment/myapp -n staging --timeout=300s"
                        }
                    }
                }
            }
        }

        stage('Production') {
            when { branch 'main' }
            steps {
                input message: '确认部署到生产环境?'
                container('kubectl') {
                    sh "kubectl set image deployment/myapp myapp=${IMAGE}:${COMMIT} -n production"
                    sh "kubectl rollout status deployment/myapp -n production --timeout=600s"
                }
            }
        }
    }
}

总结

Jenkins是功能强大的CI/CD工具。掌握Pipeline语法、插件集成和企业级实践,可以构建高效的自动化交付流水线。