centos8 jenkins 搭建和使用

一、安装jenkins

  1. 直接war包搭建下载地址:https://get.jenkins.io/war-stable/
    下载稳定长期版本

二、jenkins 启动依赖java, 安装java sdk ,好像支持java 11和17版本,21版本不支持会报错

  1. 下载sdk地址,https://www.oracle.com/java/technologies/downloads/#java17
  2. 解压并且添加环境变量
tar -xzf jdk-17_linux-x64_bin.tar.gz -C /usr/local/
在/etc/profile 添加
export JAVA_HOME=/usr/local/jdk-17.0.8
export PATH=$PATH:$JAVA_HOME/bin

source /etc/profile
java -version

三、启动jenkins

1.启动命令
java -jar jenkins.war --httpPort=9090

启动完成后,会生成首次登录的秘钥,一般会在
cat /root/.jenkins/secrets/initialAdminPassword

我使用的github ,在github 配置 ssh 公钥 ,位置setting ssh,在jenkins 配置全局私钥
服务器生成密钥

ssh-keygen -t rsa

注意在页面拉取代码的时候Are you sure you want to continue connecting (yes/no/[fingerprint])? yes,需要点击确认

2.添加到system 守护进程去运行
[Unit]
Description=Jenkins Daemon
After=network.target

[Service]
User=jenkins
Group=jenkins
Type=simple
ExecStart=/usr/local/jdk-17.0.8/bin/java -jar /root/jenkins.war --httpPort=9099
Restart=always

[Install]
WantedBy=multi-user.target

设置启动和开启启动

sudo systemctl daemon-reload
启动 Jenkins: sudo systemctl start jenkins
停止 Jenkins: sudo systemctl stop jenkins
开机启动 Jenkins: sudo systemctl enable jenkins
查看 Jenkins 服务状态: sudo systemctl status jenkins
日志 sudo journalctl -u jenkins

四、继续安装docker

yum remove docker  docker-common docker-selinux docker-engine

yum install -y yum-utils device-mapper-persistent-data lvm2

选择镜像
阿里云镜像
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
源镜像
yum-config-manager --add-repo http://download.docker.com/linux/centos/docker-ce.repo
调试容器出错原因
docker run -it --rm -p 8062:8062 \
-v $(pwd)/config.yaml:/app/conf/config.yaml \
-v $(pwd)/logs:/app/logs \
gitxuzan/weather_api:v0.0.1 /bin/sh
查看服务端:
yum list docker-ce --showduplicates | sort -r
选择版本安装

查看客户端,下载对应版本
yum list docker-ce-cli --showduplicates | sort -r

yum install -y docker-ce-3:20.10.9-3.el8 docker-ce-cli-1:20.10.9-3.el8
最后开启启动查看
systemctl start docker
systemctl enable docker docker version

五、设置跳板机登录

.ssh/config文件配置
执行 ssh target 可以跳板机登录

# 定义跳板机 (a) 的配置
Host bastion
    # 跳板机的IP地址或主机名
    HostName 16.xxx.xxx.xx
    # 用于登录跳板机的用户名
    User xuzan
    # Jenkins 服务器上的SSH私钥路径,用于身份验证
    IdentityFile /var/lib/jenkins/.ssh/bastonhost_16.xxx.xxx.pem

# 定义目标服务器 (b) 的配置
Host target
    # 目标服务器的IP地址或主机名
    HostName 52.xxx.xxx.xxx
    # 用于登录目标服务器的用户名
    User ec2-user
    # Jenkins 服务器上的SSH私钥路径,用于身份验证
    IdentityFile /home/xuzan/.ssh/news_app.pem
    # 使用ProxyCommand来指定通过跳板机连接到目标服务器
    # 这里使用ssh命令通过跳板机连接到目标服务器
    ProxyCommand ssh -q -W %h:%p bastion

六、jenkins 流水线,监听到push,然后根据commit 信息打包

pipeline {
    agent any
    options {
        disableConcurrentBuilds()  // 确保流水线不会并行执行
        timeout(time: 5, unit: 'MINUTES')  // 设置整个流水线的超时为 5 分钟
    }

    environment {
        CRAWLER_API = "weather_api"
        DIR_RUN = "cd /home/ec2-user/data/docker/services/weather && ./secrets.sh"
        CREDENTIALSID = "f2b9ffa0-89d4-41bd-b3b4-9d5fd3cfac06"
        VERSION_FILE = 'deployed_version.txt'
    }

    stages {

        stage('Retrieve Latest Successful Version') {
            steps {
                script {
                    if (fileExists(env.VERSION_FILE)) {
                        def versions = readFile(file: env.VERSION_FILE).trim().split("\n")
                        env.LATEST_VERSION = versions[-1] // Last line is the latest version
                        env.PREVIOUS_VERSION = versions.size() > 1 ? versions[-2] : "v0.0.1" // Second last line is the previous version
                    } else {
                        env.LATEST_VERSION = "v0.0.1"
                        env.PREVIOUS_VERSION = "v0.0.1"
                    }
                }
            }
        }


        stage('Checkout Code from GitHub') {
            steps {
                checkout([
                    $class: 'GitSCM',
                    branches: [[name: '*/main']],
                    extensions: [],
                    userRemoteConfigs: [[url: "[email protected]:xxxxx/${CRAWLER_API}.git", credentialsId: "${CREDENTIALSID}"]]
                ])
            }
        }

        stage('Decide Operation Based on Commit Message') {
            steps {
                script {
                    def lastCommitMessage = sh(script: "git log -1 --pretty=%B", returnStdout: true).trim()
                    env.CommitMessage = lastCommitMessage
                    if (lastCommitMessage.startsWith("#pro")) {
                        env.OPERATION = "deploy"
                        env.VERSION = "v0.0.${env.BUILD_NUMBER}"
                    } else if (lastCommitMessage.startsWith("#pre")) {
                        env.OPERATION = "rollback"
                        env.VERSION = env.PREVIOUS_VERSION
                    } else {
                        currentBuild.result = 'ABORTED'
                        error("Invalid commit message. Either start with #pro for deploy or #pre for rollback!")
                    }
                }
            }
        }

        stage('Build Docker Image and Push') {
            when {
                expression { env.OPERATION == "deploy" }
            }
            steps {
                script {
                    sh 'docker build --platform linux/amd64 -t xxxx/${CRAWLER_API}:${VERSION} -f Dockerfile_amd64_arm64 .'
                    sh 'docker push xxxx/${CRAWLER_API}:${VERSION}'
                }
            }
        }

        stage('登录服务器Deploy/Rollback on Production Server') {
            steps {
                script {
                    sh 'ssh -t target "${DIR_RUN} ${VERSION}"'
                }
            }
        }

        stage('验证接口Verify Deployment') {
            steps {
                script {
                    sleep 5
                    sh """
                        status_code=\$(curl -o /dev/null -s -w "%{http_code}" https://xxxxx/weather/v1/app/test)
                        if [ "\$status_code" != "200" ]; then
                            echo "API check failed! Received status code: \$status_code"
                            exit 1
                        fi
                    """
                }
            }
        }
    }

    post {
        success {
            echo 'Build was successful!'
            script {
                if (env.OPERATION == "deploy") {
                // 如果文件存在且最后一个字符不是换行符,则追加一个换行符
                if (fileExists(env.VERSION_FILE) && sh(script: "tail -c 1 ${env.VERSION_FILE} | wc -l", returnStdout: true).trim() != "1") {
                    sh "echo '' >> ${env.VERSION_FILE}"
                }
                // 追加版本号
                    sh "echo '${VERSION}' >> ${env.VERSION_FILE}"
                }
                currentBuild.description = "构建成功!"
                def projectName = sh(script: "basename `git rev-parse --show-toplevel`", returnStdout: true).trim()
                def messageToSend = "${projectName}: ${VERSION} ${env.CommitMessage}"
                sh "ssh target '/home/ec2-user/data/docker/services/tg.sh \"构建成功 ${messageToSend}\"'"
            }
        }

        failure {
            echo 'Build failed!'
            script {
                currentBuild.description = "构建失败!"
                def projectName = sh(script: "basename `git rev-parse --show-toplevel`", returnStdout: true).trim()
                def messageToSend = "${projectName}: ${VERSION} ${env.CommitMessage}"
                sh "ssh target '/home/ec2-user/data/docker/services/tg.sh \"构建失败 ${messageToSend}\"'"
            }
        }

        aborted {
            echo '构建取消拉aborted!'
            script {
                currentBuild.description = "构建取消拉!"
            }
        }
    }
}

获取构建方式,例如是push 的还是手动构建的,还是定时构建的
 environment {
    CAUSE = "${currentBuild.getBuildCauses()[0].shortDescription}"
}

其他

github clone不下来

https://ping.chinaz.com/github.com

选择可用的ip ,在/etc/hosts 修改
20.205.243.166 github.com
20.205.243.166 raw.githubusercontent.com

你可能感兴趣的:(jenkins,运维)