Jenkins+gitlab+docker+k8s之CICD流水线

1、安装JDK

1、下载安装包

https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.tar.gz

本次安装直接从本地上传的jdk8:jdk-8u211-linux-x64.tar.gz

2、安装

tar -xvf jdk-8u211-linux-x64.tar.gz -C /usr/local/

vim /etc/profile

export JAVA_HOME=/usr/local/java/jdk1.8.0_211

export PATH= J A V A H O M E / b i n : JAVA_HOME/bin: JAVAHOME/bin:PATH

export CLASSPATH=.: J A V A H O M E / l i b / d t . j a r : JAVA_HOME/lib/dt.jar: JAVAHOME/lib/dt.jar:JAVA_HOME/lib/tools.jar

source /etc/profile

2、安装Maven

1、下载安装包

wget https://dlcdn.apache.org/maven/maven-3/3.9.6/binaries/apache-maven-3.9.6-bin.tar.gz --no-check-certificate

2、创建目录

mkdir /usr/local/maven 存放maven

mkdir /usr/local/maven/repo 用于存放maven下载的依赖包

tar -xvf apache-maven-3.9.6-bin.tar.gz -C /usr/local/maven/

3、修改配置文件 设置本地仓库以及阿里云仓库以及指定jdk版本

vim /usr/local/maven/apache-maven-3.9.6/conf/settings.xml

<localRepository>/usr/local/maven/repo</localRepository>

<mirror>
        <id>alimaven</id>
        <mirrorOf>central</mirrorOf>
        <name>aliyun maven</name>
        <url>http://maven.aliyun.com/nexus/content/repositories/central/</url>
</mirror>

<profile>
      <id>jdk-1.8</id>
      <activation>
            <activeByDefault>true</activeByDefault>
        <jdk>1.8</jdk>
      </activation>

      <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
            <maven.compiler.target>1.8</maven.compiler.target>
            <maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
      </properties>
</profile>

vim /etc/profile

export MAVEN_HOME=/usr/local/maven/apache-maven-3.9.6

export PATH= M A V E N H O M E / b i n : MAVEN_HOME/bin: MAVENHOME/bin:PATH

source /etc/profile

查看maven版本,成功输出信息则maven环境变量配置成功

mvn --version

3、安装Gitlab

1、安装

1、在线安装

新建 /etc/yum.repos.d/gitlab_gitlab-ce.repo,内容为:

[gitlab-ce]
name=Gitlab CE Repository
baseurl=https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el$releasever/
gpgcheck=0
enabled=1
yum clean all
yum makecache
yum install gitlab-ce
gitlab-ctl reconfigure  #Configure and start GitLab

2、离线安装

wget https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/gitlab-ce-10.0.0-ce.0.el7.x86_64.rpm --no-check-certificate

rpm -ivh gitlab-ce-10.0.0-ce.0.el7.x86_64.rpm

2、配置域名和端口: vim /var/opt/gitlab/nginx/conf/gitlab-http.conf

# 外网访问的端口,如果服务器已经有服务器占用了80,那么这里可以改成其它
listen *:8888;
server_name gitlab.test.domain.com;

set $http_host_with_default "gitlab.test.domain.com:8888";

补充说明:因为编译gitlab的配置 /etc/gitlab/gitlab.rb 时会重新生成这个自定义nginx 配置,所以只要 gitlab 的配置配得好,上面的nginx其实不需要自定义的。

gitlab-ctl reconfigure

gitlab-ctl restart

gitlab-ctl status

4、修改密码

gitlab-rails console production
user = User.where(id:1).first
user.password='123456'
user.save!

安装完成,浏览器访问http://gitlab.test.domain.com:8888即可访问(需配置hosts映射)

5、GitLab备份和恢复

1、备份

可以将此命令写入crontab,以实现定时备份

/usr/bin/gitlab-rake gitlab:backup:create

备份的数据会存储在/var/opt/gitlab/backups,用户通过自定义参数 gitlab_rails[‘backup_path’],改变默认值。

2、恢复

# 停止unicorn和sidekiq,保证数据库没有新的连接,不会有写数据情况
sudo gitlab-ctl stop unicorn
sudo gitlab-ctl stop sidekiq

# 进入备份目录进行恢复,1476900742为备份文件的时间戳
cd /var/opt/gitlab/backups
gitlab-rake gitlab:backup:restore BACKUP=1476900742
cd -

# 启动unicorn和sidekiq
sudo gitlab-ctl start unicorn
sudo gitlab-ctl start sidekiq

6、GitLab配置文件修改

1、gitlab发送邮件配置

gitlab_rails['smtp_enable'] = true  
gitlab_rails['smtp_address'] = “smtp.exmail.qq.com”  
gitlab_rails['smtp_port'] = 25  
gitlab_rails['smtp_user_name'] = “huangdc@domain.com“  
gitlab_rails['smtp_password'] = "smtp password"  
gitlab_rails['smtp_authentication']= “plain"  
gitlab_rails['smtp_enable_starttls_auto']= true  
gitlab_rails['gitlab_email_from']= 'huangdc@domain.com'  
gitlab_rails['gitlab_email_reply_to']= ‘noreply@domain.com'

2、服务器修改过ssh端口的坑(需要修改配置ssh端口)

#修改过ssh端口,gitlab中项目的的ssh地址,会在前面加上协议头和端口号“ssh://git@gitlab.domain.com:55725/huangdc/test.git”
gitlab_rails['gitlab_shell_ssh_port'] = 55725

3、配置生效

#使配置生效
gitlab-ctl reconfigure
#重新启动GitLab 
gitlab-ctl restart

7、GitLab常用命令

gitlab-ctl start    # 启动所有 gitlab 组件;
gitlab-ctl stop        # 停止所有 gitlab 组件;
gitlab-ctl restart        # 重启所有 gitlab 组件;
gitlab-ctl status        # 查看服务状态;
vim /etc/gitlab/gitlab.rb        # 修改gitlab配置文件;
gitlab-ctl reconfigure        # 重新编译gitlab的配置;
gitlab-rake gitlab:check SANITIZE=true --trace    # 检查gitlab;
gitlab-ctl tail        # 查看日志;
gitlab-ctl tail nginx/gitlab_access.log

注意:执行 reconfigure 命令会把gitlab的nginx组件的配置还原,导致自定义修改的端口以及域名等都没有了

8、初始化git信息,此处配置的邮箱都是后续gitlab用户的邮箱

git config --global user.name "qiaonannan"
git config --global user.email "1205947071@qq.com"

生成秘钥,直接一路回车即可
ssh-keygen -t rsa -C "1205947071@qq.com"

查看公钥
cat ~/.ssh/id_rsa.pub

9、GitLab页面配置

按照指导简单配置完成

本地使用idea新建一个简单的Spring Boot项目

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>


    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.4</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>


    <groupId>org.example</groupId>
    <artifactId>test</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <java.version>8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

    </dependencies>


    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
package com.xkc.controller;


import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;


@RestController
public class UserController {

    @GetMapping("/test")
    public String m1(){

        return  "测试";
    }


}

package com.xkc.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author qiaonan
 * @version v1.0
 * @package com.xkc.controller
 * @project test
 * @date 2024年1月9号     11:00
 **/
@RestController
@RequestMapping("/user")
public class UserLogin {

    @GetMapping("/test1")
    public String test1(){
        return "自动化测试一";
    }
}
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.xkc;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class TestDemoApplication {
    public TestDemoApplication() {
    }

    public static void main(String[] args) {
        SpringApplication.run(TestDemoApplication.class, args);
    }
}

application.yml

server:
  port: 8088

配置本地maven仓库,后续所有依赖包都会下载报错到本地这个目录

配置完成后本地调试代码

推送代码到GitLab上

弹窗出来后输入用户名密码即可完成git仓库配置

本地修改完代码先commit

然后push到远程git仓库

4、安装Jenkins

1、安装
wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat/jenkins.repo 
rpm --import https://pkg.jenkins.io/redhat/jenkins.io.key
yum -y install fontconfig java-11-openjdk jenkins
2、启动
systemctl restart jenkins && systemctl enable jenkins
3、下载插件源修改为国内站点
进入 Manage Jenkins -》 Manage Plugin -> Advanced 最下面有 Update Site,
设置为:https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json 
或者 http://mirror.xmission.com/jenkins/updates/update-center.json
进入jenkins安装目录下的/updates/default.json ,将其中的updates.jenkins-ci.org/download 
替换为mirrors.tuna.tsinghua.edu.cn/jenkins ,
有些 jenkins 版本当中,是将updates.jenkins.io/download 替换为mirrors.tuna.tsinghua.edu.cn/jenkins
然后,把 www.google.com 修改为 www.baidu.com

sed -i 's/updates.jenkins.io\/download/mirrors.tuna.tsinghua.edu.cn\/jenkins/g' /var/lib/jenkins/updates/default.json 
sed -i 's/www.google.com/www.baidu.com/g' /var/lib/jenkins/updates/default.json

systemctl restart jenkins
4、自定义jenkins端口号
vim /usr/lib/systemd/system/jenkins.service
Environment="JENKINS_PORT=8090"
vim /etc/sysconfig/jenkins
JENKINS_PORT="8090"
systemctl restart jenkins

在这里插入图片描述
配置Jenkins

yum 安装的jenkins,jenkins用户默认是不可以切换的,jenkins运行和执行脚本都是用jekins用户执行的,所以要保证jenkins用户可以执行配置里的脚本。比如调用java,mvn,git和免密,都要保证jenkins用户可以。

vim /etc/passwd

全局工具配置

jdk配置

maven

服务器之间免密:

免密登录,需切换到jenkins用户,进入jenkins用户根目录。

执行 ssh-keygen -t rsa //生成秘钥

执行 ssh-copy-id -i ~/.ssh/id_rsa.pub 用户名@服务器IP //与后面的服务器进行免密,第一次需要输入密码

安装插件

Publish over SSH:通过SSH发布

配置系统

http的git地址一定加上端口

注意修改jar包的名称,可以直接将该脚本放在服务器,使用 sh /home/脚本名称 该处直接运行脚本

#!/bin/bash
workPath=/usr/local/project/test/
jarPath=/var/lib/jenkins/workspace/Auto-deploy/test/target/
jarName=test-1.0-SNAPSHOT.jar
dockerPath=/var/lib/jenkins/workspace/Auto-deploy/test/src/main/resources/
#echo "当前执行脚本的用户是: $(whoami)"
mkdir -vp $workPath
echo "==========创建工作空间=========="
chmod 755 $workPath
pid=`ps -ef | grep test-1.0-SNAPSHOT.jar | grep -v grep | awk '{print $2}'`
if [ -n "$pid" ]
then
   kill -9 $pid
   echo "==========杀死存在进程=========="
fi
echo $workPath$jarName
echo $jarPath$jarName
if [ -e $workPath$jarName ]; then
   echo "==========启动文件存在, 执行删除启动文件=========="
   rm -rf $workPath$jarName
else
   echo "==========启动文件不存在=========="
fi
if [ -e $jarPath$jarName ]; then
   cp $jarPath$jarName $workPath
   cp $dockerPath/Dockerfile $workPath
   echo "==========目标文件存在, 执行拷贝启动文件=========="
else
   echo "==========目标文件不存在=========="
fi
cd $workPath
docker build -t demo:v1.0 .
#export BUILD_ID=donotKillMe
echo "==========执行启动demo服务=========="
docker run -d -p 9090:8488 -it demo:v1.0
#nohup java -jar test-1.0-SNAPSHOT.jar  > test-logs.log 2>&1 &
pid=`lsof -i:9090 | awk 'NR==2 {print $2}'`
if [ "$pid" != "" ];then
   echo "==========启动成功demo服务=========="
else
   echo "==========demo服务启动失败=========="
fi

开始构建

访问成功

更新代码后,重新构建

1、Dstore项目构建

pipeline {
    agent any
    tools {
        maven "M3"
    }
	options { timestamps() }
    environment {
    	gitSrc = "$params.gitSource"
    	gitBranch =  "$params.gitBranch"
    	mavenProfile = "$params.mavenProfile"
		targetDir = "$params.targetDir"
		targetHost = "$params.targetHost"
		jarPath = "/var/lib/jenkins/workspace/dstore2.0_build_deploy/dstore-server/dstore-hop/target/hbis-dstore-hop.jar"
    }
    stages {
        
        stage('clean') { 
            steps {
				sh 'cd /var/lib/jenkins/workspace/dstore2.0_build_deploy && rm -rf *'
            }
		}
        
        stage('checkout') { 
            steps {
				echo gitSrc
				echo gitBranch
				echo ">>>拉取代码<<<"
				git branch: gitBranch, credentialsId: 'dstore_git', url: gitSrc
            }
		}
		stage('build') {
			steps {
			    echo "${mavenProfile}"
			    echo ">>>maven构建<<<"
				sh "cd dstore-server && mvn clean package -P ${mavenProfile} -pl dstore-hop"
            }
		}
	   stage('backup jar'){
		 steps{
			echo ">>>备份jar<<<"
			script{
				withCredentials([usernamePassword(credentialsId: 'host_default', passwordVariable: 'password', usernameVariable: 'userName')]){
				   sh 'sshpass -p ${password} ssh -o StrictHostKeyChecking=no ${userName}@${targetHost} "mkdir /opt/dstore_bak/ & cp ${targetDir}/hbis-dstore-hop.jar /opt/dstore_bak/hbis-dstore-hop.jar_bak_"$(date +"%Y-%m-%d_%H:%M:%S")""'
				}
			}
		 }
	   }
	   stage('stop jar'){
			steps {	
				echo ">>>停止jar<<<"
				script{
					withCredentials([usernamePassword(credentialsId: 'host_default', passwordVariable: 'password', usernameVariable: 'userName')]){
					   sh 'sshpass -p ${password} ssh ${userName}@${targetHost} "sh ${targetDir}/bin/shutdown.sh"'
					}
				}
			}
		}
	   stage('copy jar'){
			steps{
				echo ">>>拷贝jar<<<"
				script{
					withCredentials([usernamePassword(credentialsId: 'host_default', passwordVariable: 'password', usernameVariable: 'userName')]){
					   sh 'sshpass -p ${password} scp ${jarPath} ${userName}@${targetHost}:${targetDir}'
					}
				}
			}
		}
	   stage('run jar'){
			steps{
			    echo ">>>启动jar<<<"
				script{
					withCredentials([usernamePassword(credentialsId: 'host_default', passwordVariable: 'password', usernameVariable: 'userName')]){
					   withEnv(['JENKINS_NODE_COOKIE=dontkillme']) {
						sh 'sshpass -p ${password} ssh ${userName}@${targetHost} "sh ${targetDir}/bin/startup.sh"'
					   }
					}
				}
			}
		}
    }
}

2、大数据中心项目自动化构建:gitlab+Jenkins+maven+docker+道客云k8s

后端项目:以DTrans为例

上传Dockerfile文件到main服务和node服务目录下

/**
 *********************************************************************
 * hbisdt pipeline for cicd
 * by qiaonannan
 * 2024-05-23
 *********************************************************************
 * jenkins构建时需传入的参数
 * install: 列表,逗号分隔,是否执行全局install,可使用jenkins插件Extended Choice Parameter中的Single Select类型
 * service: 列表,逗号分隔,本次部署的微服务模块名称,类型同上
 * branch: 发布分支
 * deploy_env: dev,test,prod  只能接受这三个值,分别会部署到k8s不同命名空间
 *                          dev  -> "${APP}-dev"
 *                          test -> "${APP}-test"
 *                          prod -> "${APP}"
 * 依赖组件
 * jenkins、jdk8、jdk11、git、mvn、nodejs(14.18.0)、docker、kubectl、vpn(可选)
 *
 */

def setVars() {
    // 这里定义每个微服务的模块(微服务)名称和GIT项目根下的相对路径
    // 微服务名称和数量,一定要和Jenkins构建参数传入的$service名称保持一致,禁止包含中划线"-"
    // 每个微服务路径内应包含Dockerfile,即该目录也是docker build的项目目录,会在该目录执行编译过程
    env.main_server = "dtrans-main-server"
    env.task_node = "dtrans-task-node"
    return true
}

def createVersion() {
    // 定义一个版本号作为当次构建的版本
    return new Date().format('yyyyMMddHHmmss') + "_${env.BUILD_ID}"
}

pipeline {
    // 定义该pipeline 在哪些jenkins上节点上执行
    // 若jenkins集群为单节点或无要求,可配置为: agent any
    agent { label 'weshyper-jenkins' }

    environment {
        APP = "weshyper"                            //应用名称,主要用于创建k8s命名空间、deployment、镜像时命名前缀
                                                    //deployoment默认名称:$APP-微服务名称(若名称中包含下划线会自动替换为中划线)
        KUBE_CONFIG = "/root/.kube/daoke"           //K8S更新镜像,kubectl使用的kube config
        J_WORKSPACE = "/root/.jenkins/workspace"    //jenkins默认的工作空间,根据自己环境修改,没修改过保持默认即可
        HARBOR_IP = "192.168.100.189"               //Harbor服务器地址,一般不用修改
        HARBOR_REPO = "hbisdt-weshyper"             //镜像上传到Harbor中的仓库名称,产品融合统一使用hbisdt-weshyper
        RESOURCE = "deployment"                     //k8s中资源部署类型,一般不用修改
        CONTAINER = "container-1"                   //k8s中默认容器名称,一般不用修改
        WAIT_TIMEOUT = "180s"                       //流水线等待微服务启动完成时间,建议提前在k8s配置健康检查等探针
        IMG_TAG = createVersion()                   //镜像标签,默认动态生成,格式为:当前时间_(jenkins build id)
        LOAD_MS_PATH = setVars()                    //加载微服务<名称-路径>MAP
        NAMESPACE = """${sh(
                        returnStdout: true,
                        script: """
                            set -x; set -e; set -v
                            if [ ${deploy_env} == "dev" ]; then
                                echo "${APP}-dev"
                            elif [ ${deploy_env} == "test" ]; then
                                echo "${APP}-test"
                            else
                                echo ${APP}
                            fi
                            """
                        ).trim()}"""

    }

    stages {
        stage('打印全局变量') {
            steps {
                echo "----------------------print environment----------------------"
                sh "printenv"
            }
        }

        stage('GIT代码拉取') {
            steps {
                checkout scm
                updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success')

            }
        }

        stage('Sonar扫描') {
            steps {
                sh "echo sonar scan, to be completed..."

            }
        }

        stage('Maven编译') {
            steps {
                echo "----------------------java building----------------------"
                sh '''
                    P_NAME=`pwd |awk -F '/' '{print $NF}'`
                    cd ${J_WORKSPACE}/${P_NAME} || exit
                    if [ "$install" = "是" ];then
                        mvn clean install -Dmaven.test.skip=true
                    fi

                    echo `pwd`
                    echo "============ maven build:$service ============"

                    IFS=','
                    arr=($service)
                    for i in "${arr[@]}"
                    do
                        echo "maven build: $i"
                        ms_path="${J_WORKSPACE}/${P_NAME}/${!i}"
                        cd ${ms_path}
                        mvn clean package -Dmaven.test.skip=true
                    done
                    '''
                updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success')
            }
        }

        stage('Docker编译') {
            steps {
                echo "----------------------docker building----------------------"
                withCredentials([usernamePassword(passwordVariable:'password',usernameVariable:'username',credentialsId:'kjzx_harbor_credentials')]) {
                sh '''
                    P_NAME=`pwd |awk -F '/' '{print $NF}'`
                    cd ${J_WORKSPACE}/${P_NAME} || exit
                    IFS=','
                    arr=($service)
                    for i in "${arr[@]}"
                    do
                        echo "docker build $i"
                        ms=`echo ${i} |sed 's/_/-/g'`
                        ms_path="${J_WORKSPACE}/${P_NAME}/dtrans-${ms}"
                        IMAGE_URL="${HARBOR_IP}/${HARBOR_REPO}/${APP}-${ms}:${IMG_TAG}"
                        echo "${IMAGE_URL}"
                        cd ${ms_path}
                        docker build --build-arg JAR_FILE="*.jar"  -t ${IMAGE_URL} .
                        docker login http://${HARBOR_IP} -u ${username} -p ${password}
                        docker push ${IMAGE_URL}
                    done

                    '''
                }
                updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success')
            }
        }



        stage('K8S部署') {
            steps {
                echo "-----------------update images in k8s------------------"
                sh '''
                    echo "start update $service images with kubectl tools"
                    IFS=','
                    arr=($service)
                    for i in "${arr[@]}"
                    do
                        ms=`echo ${i} |sed 's/_/-/g'`
                        IMG="${HARBOR_IP}/${HARBOR_REPO}/"${APP}-${ms}":${IMG_TAG}"
                        echo "update $ms : $IMG"
                        kubectl --kubeconfig ${KUBE_CONFIG}  set image $RESOURCE/"${APP}-${ms}" $CONTAINER=$IMG -n $NAMESPACE
                    done
                    '''
                updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success')
                }
            }

        stage('等待服务启动') {
            steps {
                echo "----------------------wait service startup----------------------"
                sh '''
                    IFS=','
                    arr=($service)
                    for i in "${arr[@]}"
                    do
                        ms=`echo ${i} |sed 's/_/-/g'`
                        echo "wait ${APP}-${ms} ...     timeout: ${WAIT_TIMEOUT}"
                        kubectl --kubeconfig ${KUBE_CONFIG}   rollout status  $RESOURCE  "${APP}-${ms}" -n $NAMESPACE   --timeout=${WAIT_TIMEOUT}
                    done
                    '''
                updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success')
            }
        }
    }

    post {
        success {
            echo "deploy success!"
        }
        failure {
            echo "deploy failure!"
        }
        always {
            echo "deploy done! or call send_sms.py or send_wechat.py"
        }
    }
}


###
升级后参数改动,NAMESPACE=$deploy_env,后续新增环境直接在Jenkins页面添加即可

main-server:

# 使用本地的 Java 8 镜像作为基础镜像
FROM container-registry.oracle.com/java/jdk:1.8.0_371

# 镜像制作作者
MAINTAINER this is dtrans-main images <qiaonannannan>

# 将应用包拷贝并解压到/opt目录下
ARG JAR_FILE
COPY target/${JAR_FILE} app.jar

# 设置环境变量
ENV LANG C.UTF-8
ENV TZ=Asia/Shanghai
ENV NACOS_SERVERADDR=""
ENV NACOS_NAMESPACE=""
ENV NACOS_GROUP="DEFAULT_GROUP"
ENV NACOS_PROFILES_ACTIVE="dev"
ENV NACOS_USERNAME=""
ENV NACOS_PASSWORD=""


# 定义容器启动时执行的命令
CMD java -Dnacos.serveraddr=$NACOS_SERVERADDR \
         -Dnacos.namespace=$NACOS_NAMESPACE \
         -Dnacos.group=$NACOS_GROUP \
         -Dnacos.username=$NACOS_USERNAME \
         -Dpassword=$NACOS_PASSWORD \
         -jar app.jar \
         --spring.profiles.active=$NACOS_PROFILES_ACTIVE

task-node:

# 使用本地的 Java 8 镜像作为基础镜像
FROM container-registry.oracle.com/java/jdk:1.8.0_371

# 镜像制作作者
MAINTAINER this is dtrans-main images <qiaonannannan>

# 将应用包拷贝并解压到/opt目录下
COPY kettleplugin /opt/kettleplugin
ARG JAR_FILE
COPY target/${JAR_FILE} app.jar



# 设置环境变量
ENV LANG C.UTF-8
ENV TZ=Asia/Shanghai
ENV NACOS_SERVERADDR=""
ENV NACOS_NAMESPACE=""
ENV NACOS_GROUP="DEFAULT_GROUP"
ENV NACOS_PROFILES_ACTIVE="dev"
ENV NACOS_USERNAME=""
ENV NACOS_PASSWORD=""


# 定义容器启动时执行的命令
CMD java -Dnacos.serveraddr=$NACOS_SERVERADDR \
         -Dnacos.namespace=$NACOS_NAMESPACE \
         -Dnacos.group=$NACOS_GROUP \
         -Dnacos.username=$NACOS_USERNAME \
         -Dpassword=$NACOS_PASSWORD \
         -jar app.jar \
         --spring.profiles.active=$NACOS_PROFILES_ACTIVE

Jenkins新建工程

构建流水线之前需将Jenkinsfile、Dockerfile文件放入Git仓库目录方可执行

部署完成后前往道客云查看https://dce.weshyper.com/kpanda/clusters/hbisdt-work/namespaces/weshyper-dev/deployments

kind: Deployment
apiVersion: apps/v1
metadata:
  name: weshyper-main-server
  namespace: weshyper-dev
spec:
  replicas: 1
  selector:
    matchLabels:
      app: weshyper-main-server
  template:
    metadata:
      labels:
        app: weshyper-main-server
    spec:
      containers:
        - name: container-1
          image: >-
            192.168.100.189/hbisdt-weshyper/weshyper-main-server:20240613113028_37
          env:
            - name: NACOS_SERVERADDR
              value: 192.168.100.219:9901
            - name: NACOS_NAMESPACE
              value: c05a485e-b854-4783-b69c-fb08729fae7f
            - name: NACOS_USERNAME
              value: nacos
            - name: NACOS_PASSWORD
              value: nacos
          resources: {}
          livenessProbe:
            httpGet:
              path: http://localhost:19000/api/server/getServerInstance
              port: 19000
              scheme: HTTP
            initialDelaySeconds: 10
            timeoutSeconds: 1
            periodSeconds: 30
            successThreshold: 1
            failureThreshold: 3
          lifecycle: {}
          terminationMessagePath: /dev/termination-log
          terminationMessagePolicy: File
          imagePullPolicy: Always
          securityContext:
            privileged: false
      restartPolicy: Always
      terminationGracePeriodSeconds: 30
      dnsPolicy: ClusterFirst
      securityContext: {}
      schedulerName: default-scheduler
      tolerations:
        - key: node.kubernetes.io/not-ready
          operator: Exists
          effect: NoExecute
          tolerationSeconds: 300
        - key: node.kubernetes.io/unreachable
          operator: Exists
          effect: NoExecute
          tolerationSeconds: 300
      dnsConfig: {}
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 25%
      maxSurge: 25%
  revisionHistoryLimit: 10
  progressDeadlineSeconds: 600

kind: Deployment
apiVersion: apps/v1
metadata:
  name: weshyper-task-node
  namespace: weshyper-dev
spec:
  replicas: 1
  selector:
    matchLabels:
      app: weshyper-task-node
  template:
    metadata:
      labels:
        app: weshyper-task-node
    spec:
      containers:
        - name: container-1
          image: 192.168.100.189/hbisdt-weshyper/weshyper-task-node:20240613113028_37
          env:
            - name: NACOS_SERVERADDR
              value: http://192.168.100.219:9901
            - name: NACOS_NAMESPACE
              value: c05a485e-b854-4783-b69c-fb08729fae7f
            - name: NACOS_USERNAME
              value: nacos
            - name: NACOS_PASSWORD
              value: nacos
          livenessProbe:
            httpGet:
              path: http://localhost:8898/api/test/testApp
              port: 8898
              scheme: HTTP
            initialDelaySeconds: 10
            timeoutSeconds: 1
            periodSeconds: 60
            successThreshold: 1
            failureThreshold: 3
          terminationMessagePath: /dev/termination-log
          terminationMessagePolicy: File
          imagePullPolicy: Always
          securityContext:
            privileged: false
      restartPolicy: Always
      terminationGracePeriodSeconds: 30
      dnsPolicy: ClusterFirst
      schedulerName: default-scheduler
      tolerations:
        - key: node.kubernetes.io/not-ready
          operator: Exists
          effect: NoExecute
          tolerationSeconds: 300
        - key: node.kubernetes.io/unreachable
          operator: Exists
          effect: NoExecute
          tolerationSeconds: 300
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 25%
      maxSurge: 25%
  revisionHistoryLimit: 10
  progressDeadlineSeconds: 600

3、Jenkins配置SonarQube扫描项目代码是否合规

sonar.projectKey=WeShyper_AI_DMind_AI_sonar
sonar.projectName=WeShyper_AI_DMind_AI_sonar
sonar.sources=$WORKSPACE
sonar.java.binaries=$WORKSPACE
sonar.projectVersion=V1.0
#sonar.language=java
sonar.sourceEncoding=UTF-8
#sonar.java.source=1.8
#sonar.java.target=1.8
sonar.inclusions= machine_learning/adaboost_regression/**
#sonar.exclusions=structured_data_analysis/model_10_electrical_faults/Dockerfile

sonar-scanner -Dsonar.projectKey=my:project -Dsonar.projectName=My Project -Dsonar.projectVersion=1.0 -Dsonar.sources=.

source /etc/profile
sleep  60
a=`curl  -u weshyper:weshyper1234  http://18.10.255.4:9000/api/qualitygates/project_status?projectKey=WeShyper_AI_DMind_AI_sonar`
b=`echo  $a | awk -F '":"'  '{print $2}'|awk -F '","'  '{print $1}'`
echo $b
[[ $b = "OK" ]]  &&  echo "pass" || (echo "sonar没通过" &&  abcde)

4、前端Vue项目构建

鉴于不通项目上的采用的node.js版本不通,在linux操作系统中安装多个node.js很麻烦,故前端采用docker进行npm编译,

FROM    node:20.14.0-alpine3.20
RUN     sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories && \
	    apk add git openssh && \
	    npm install -g nrm && \
	    nrm add hbis http://18.10.255.2:8081/repository/npm-group/ && \
	    nrm use hbis

/**
 *********************************************************************
 * hbisdt pipeline for cicd
 * by qiaonannan
 * 2024-06-04
 *********************************************************************
 * jenkins构建时需传入的参数
 * branch: 发布分支
 * deploy_env: dev,test,prod  只能接受这三个值,分别会部署到k8s不同命名空间
 *                          dev  -> "${APP}-dev"
 *                          test -> "${APP}-test"
 *                          prod -> "${APP}" 
 *
 *
 * 项目改造
 * 1、git项目根下创建目录:docker_build
 * 2、dist制品默认输出到项目根下
 * 3、docker_build包含容器打包依赖的所有资源:包括:Dockerfile、nginx.conf、dist等
 * 4、dist目录会等npm编译完成后,自动从项目根下copy进docker_build
 *
 */

def setVars() {
    // 这里定义每个微服务的模块名称和项目的相对路径,前端只定义微服务名称即可
    // k8s部署deployment完整名称为: ${APP}-${front_name}
    env.front_name = "cloud-web"
    return true
}

def createVersion() {
    // 定义一个版本号作为当次构建的版本,输出结果 20191210175842_69
    return new Date().format('yyyyMMddHHmmss') + "_${env.BUILD_ID}"
}

pipeline {
    agent { label 'weshyper-jenkins' }

    environment {
        APP = "weshyper"                     //应用名称,主要用于创建命名空间、deployment、镜像时命名前缀
        NPM_DOCKER_IMG="hbis-xa/node:20.14.0-alpine3.20" // 使用npm编译的docker镜像版本
        SCRIPT_PATH = "/scripts"          //jenkinsfil中脚本路径,jenkins服务器上的路径,一般不用修改
        HARBOR_IP = "192.168.100.189"     //Harbor服务器地址,一般不用修改
        HARBOR_REPO = "hbisdt-weshyper"          //镜像上传到Harbor中的仓库名称,产品融合统一使用hbisdt-weshyper
        RESOURCE = "deployment"           //k8s中资源部署类型,一般不用修改
        CONTAINER = "container-1"         //k8s中默认容器名称,一般不用修改
        WAIT_TIMEOUT = "180s"             //流水线等待微服务启动完成时间,建议提前在k8s配置健康检查
        IMG_TAG = createVersion()
        LOAD_MS_PATH = setVars()
        NAMESPACE = """${sh(
                        returnStdout: true, 
                        script: """
                            set -x; set -e; set -v
                            if [ ${deploy_env} == "dev" ]; then 
                                echo "${APP}-dev"
                            elif [ ${deploy_env} == "test" ]; then
                                echo "${APP}-test"
                            else 
                                echo ${APP}
                            fi
                            """
                        ).trim()}"""
        
    }

    stages {
        stage('打印全局变量') {
            steps {
                echo "----------------------print environment----------------------"
                sh "printenv"
            }
        }     

        stage('GIT代码拉取') {
            steps {
                checkout scm
                updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success')

            }   
        }

        stage('Sonar扫描') {
            steps {
                sh "echo sonar scan, pass"

            }
        }
            
        stage('前端NPM打包') {
            steps {
                echo "----------------------npm building----------------------"
                sh '''
                    P_NAME=`pwd |awk -F '/' '{print $NF}'`
                    cd /root/.jenkins/workspace/${P_NAME}
                    docker run --rm -v ${PWD}:/opt "${NPM_DOCKER_IMG}"  sh -c 'cd /opt && npm install && npm run build'
                    '''
                updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success')
            }
        }

        stage('Docker编译镜像') {
            steps {
                echo "----------------------docker building----------------------"
                withCredentials([usernamePassword(passwordVariable:'password',usernameVariable:'username',credentialsId:'kjzx_harbor_credentials')]) {
                sh '''
                    P_NAME=`pwd |awk -F '/' '{print $NF}'`
                    cd /root/.jenkins/workspace/${P_NAME}/docker_build || exit
                    cp -r /root/.jenkins/workspace/${P_NAME}/dist   ./
                    cp /root/.jenkins/workspace/${P_NAME}/Dockerfile ./
                    echo "docker build ${P_NAME}"
                    IMAGE_URL="${HARBOR_IP}/${HARBOR_REPO}/${APP}-${front_name}:${IMG_TAG}"
                    echo "${IMAGE_URL}"

                    docker build   -t ${IMAGE_URL} . 
                    docker login http://${HARBOR_IP} -u ${username} -p ${password}
                    docker push ${IMAGE_URL}
                    '''
                }
                updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success')
            }
        }


         
        stage('K8S部署') {
            steps {
                echo "-----------------update images in k8s------------------"
                sh '''
                    echo "start update vue images with kubectl tools"
                    IMG="${HARBOR_IP}/${HARBOR_REPO}/"${APP}-${front_name}":${IMG_TAG}"
                    echo "update ${APP}-${front_name} : $IMG"
                    kubectl --kubeconfig /root/.kube/daoke  set image $RESOURCE/"${APP}-${front_name}" $CONTAINER=$IMG -n $NAMESPACE
                    '''
                updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success')
                }    
            }

        stage('等待服务启动') {
            steps {
                echo "----------------------wait service startup----------------------"
                sh '''
                    echo "wait ${APP}-vue ...     timeout: ${WAIT_TIMEOUT}"
                    kubectl --kubeconfig /root/.kube/daoke   rollout status  $RESOURCE  "${APP}-${front_name}" -n $NAMESPACE   --timeout=${WAIT_TIMEOUT} 
                    '''
                updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success')
            }
        }
    }

    post {
        success {
            echo "deploy success!"
        }
        failure {
            echo "deploy failure!"
        }
        always {
            echo "deploy done!"
        }
    }
}
# 基于nginx:1.20镜像
FROM nginx:1.20
# 将dist文件中的内容复制到 /etc/nginx/html/ 这个目录下面
RUN mkdir -p /etc/nginx/html/
COPY dist /etc/nginx/html/dist
ENV LANG C.UTF-8
ENV TZ=Asia/Shanghai

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值