环境:centos7.6 、Docker version 19.03.5、Jenkins 2.249.3(jackson = 2.11.2、docker plugin = 1.2.1)
主要思想: 使用 docker plugin 配置一个动态的docker jenkins jnlp slave,该镜像中包含 mvn、git、docker、kubectl 等命令。创建多分支流水线,Jenkinsfile 使用前面配置好的 jenkins slave。在该 jenkins slave 中执行 maven 构建、docker build、jave 、kubectl apply 等操作。

1、配置动态 docker jenkins jnlp slave,参考 https://blog.csdn.net/Man_In_The_Night/article/details/111614431
在这里插入图片描述在这里插入图片描述在这里插入图片描述
在这里插入图片描述2、创建 k8s 和 docker hub credential。参考 https://blog.csdn.net/Man_In_The_Night/article/details/111614431
在这里插入图片描述
3、创建一个 springboot java web 项目,见 github 项目 https://github.com/pretendhigh/javawebdemo
Jenkinsfile 如下:

node("mapleaves") {
  def APP_NAME = "javaWebDemo"
  def APP_PORT = "8081"
  def NODE_PORT_DEV = "30040"
  def NODE_PORT_PRO = "32040"
  def REPLICAS = "1"
  def cicd_admin = "mapleaves"
  def myRepo = checkout scm
  def gitCommit = myRepo.GIT_COMMIT
  def gitBranch = myRepo.GIT_BRANCH
  def imageTag = sh(script: "git rev-parse --short HEAD", returnStdout: true).trim()
  def imageEndpoint = "mapleaves/javawebdemo-${gitBranch}"
  def IMAGE = "${imageEndpoint}:${imageTag}"  
  if (gitBranch != 'dev' && gitBranch != 'master'){
    echo "${gitBranch} 分支不参与执行,开始退出,如有疑问,请联系运维人员 ${cicd_admin}"
    return     
  }    
  stage('SonarQube 代码检测') {
    echo "============================== 1.代码检测阶段 =============================="
    echo "branch name is ${gitBranch}"
    if (gitBranch == 'dev' ){
        echo "branch name is ${gitBranch}"
        // 此处可以调用 sonarqube,这里不展开,可以参考 jenkinsfile-demo
    } else {
      echo "${gitBranch} 分支不做代码检测,如有疑问,请联系运维人员 ${cicd_admin}"
    }
  }
  stage('代码编译打包') {
    echo "============================== 2.代码编译打包阶段 =============================="
    try {
      sh "ls"
      sh "ls target"
      sh "mvn clean package -s settings.xml -Dmaven.test.skip=true"
      sh "ls"
      sh "ls target"      
    } catch (exc) {
      println "构建失败 - ${currentBuild.fullDisplayName}"
      throw(exc)
    }
  }
  stage('构建 Docker 镜像') {
    echo "============================== 3.构建 Docker 镜像阶段  =============================="
    withCredentials([[$class: 'UsernamePasswordMultiBinding',
      credentialsId: 'mydockerhub',
      usernameVariable: 'dockerHubUser',
      passwordVariable: 'dockerHubPassword']]) {         
      // 此处可以使用 harbor,这里不展开,可以参考 jenkinsfile-demo
      sh """
      sed -i 's/<APP_PORT>/${APP_PORT}/g' Dockerfile
      docker login -u ${dockerHubUser} -p ${dockerHubPassword}
      docker build -t ${IMAGE} .
      docker push ${IMAGE}
      """        
    }
  }
  stage('部署 recommend-system 到 infra-k8s') {
    echo "============================== 4.部署 recommend-system ${gitBranch} 分支到 infra-k8s =============================="
    if (gitBranch == 'master') {      
      input "确认要部署到生产环境吗?"
      NAMESPACE = "pro"
      NODE_PORT = "${NODE_PORT_PRO}"
    }
    if (gitBranch == 'dev') {
      NAMESPACE = "dev"
      NODE_PORT = "${NODE_PORT_DEV}"
    }    
    withKubeConfig([credentialsId: 'infra-k8s',contextName: 'kubernetes',]) {    
      sh """
        sed -i 's/<APP_NAME>/${APP_NAME}/g' k8s.yaml
        sed -i 's/<APP_PORT>/${APP_PORT}/g' k8s.yaml
        sed -i 's/<NODE_PORT>/${NODE_PORT}/g' k8s.yaml
        sed -i 's/<REPLICAS>/${REPLICAS}/g' k8s.yaml
        sed -i 's?<IMAGE>?${IMAGE}?g' k8s.yaml
        sed -i 's/<NAMESPACE>/${NAMESPACE}/g' k8s.yaml
         """       
      sh "kubectl apply -f k8s.yaml --record"          
    }   
  }
}

Dockerfile 如下:

FROM openjdk:8-jdk-alpine

ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8
ENV TZ=Asia/Shanghai

RUN mkdir /app

WORKDIR /app

COPY target/javawebdemo-1.0-SNAPSHOT.jar  /app/javawebdemo.jar

EXPOSE <APP_PORT>

ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "--server.port=<APP_PORT>", "javawebdemo.jar"]

k8s.yaml 如下:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: <APP_NAME>
  namespace: <NAMESPACE>
  labels:
    app: <APP_NAME> 
spec:
  replicas: <REPLICAS>
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: <APP_NAME>
    spec:
      restartPolicy: Always
      hostAliases:
      - ip: "10.2.7.1"
        hostnames:
        - "kafka01"
      - ip: "10.2.7.9"
        hostnames:
        - "kafka02"
      containers:
      - image: <IMAGE>
        name: <APP_NAME>
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: <APP_PORT>
          name: api
        resources:
          limits:
            cpu: 800m
            memory: 1200Mi
          requests:
            cpu: 50m
            memory: 600Mi          

---

kind: Service
apiVersion: v1
metadata:
  name: <APP_NAME>
  namespace: <NAMESPACE>
spec:
  selector:
    app: <APP_NAME>
  type:  NodePort
  ports:
  - name: api-port
    port: 8080
    targetPort:  api
    nodePort: <NODE_PORT>

4、创建一个多分支流水线
在这里插入图片描述设置 github 代码仓库 https://github.com/pretendhigh/javawebdemo (gitlab 仓库同理),如果是私有仓库,需要设置 github crendential,可以参考
https://docs.github.com/cn/free-pro-team@latest/github/authenticating-to-github/creating-a-personal-access-token
https://stackoverflow.com/questions/61105368/how-to-use-github-personal-access-token-in-jenkins
在这里插入图片描述选择每 5 分钟扫描一次代码仓库
在这里插入图片描述5、当有 github 仓库有代码更新或者点击“立即构建” 就可以执行流水线了。
推荐使用私有 gitlab 和 harbor 代替 github 和 docker hub,不然由于网络原因,容易 timeout。

在这里插入图片描述

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐