Jenkins-pipeline自动化构建Java应用

本实验操作需要:Jenkins,git代码仓库(如gitlab,gitee等都可以),maven,docker,docker镜像仓库(habor,nexus或者阿里云ACR等)以及k8s环境。

前期准备工作

本例需要Jenkins插件如下:

Git
Git Parameter
Git Pipeline for Blue Ocean
GitLab
Credentials
Credentials Binding
Blue Ocean
Blue Ocean Pipeline Editor
Blue Ocean Core JS
Pipeline SCM API for Blue Ocean
Dashboard for Blue Ocean
Build With Parameters
Dynamic Extended Choice Parameter Plug-In
Dynamic Parameter Plug-in
Extended Choice Parameter
List Git Branches Parameter
Pipeline
Pipeline: Declarative
Kubernetes
Kubernetes CLI

Kubernetes Credentials
Image Tag Parameter
Active Choices

安装完毕记得重启一下jenkins。

因为是实验环境,我这里直接拷贝一份杜宽老师的代码

杜宽/spring-boot-project放在我的代码仓库中。

  • 添加docker镜像仓库的凭证:

  • 在jenkins上添加git的ssh-key,每个代码仓库都会有指导创建,这里不赘述了,不了解的百度一下。 

如果添加后拉取代码有提示错误信息 :

Failed to connect to repository : Command "git ls-remote -h git@GIT_URL:/home/git/www.git HEAD" returned status code 128:
stdout:
stderr: Permission denied, please try again.
Permission denied, please try again.
Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

 在Manage Jenkins --> Configure Global Security 下有一个配置,这里的选项选择为No verification,即可解决。

  • 在jenkins上添加k8s集群kebectl控制认证配置,一般路径在~/.kube/config。

创建Jenkinsfile

在代码仓库根下创建Jenkinsfile文件。

pipeline {
  agent any
  stages {
    stage('Pulling Code') {
      parallel {
        stage('Pulling Code by Jenkins') {
          when {
            expression {
              env.gitlabBranch == null
            }

          }
          steps {
            git(changelog: true, poll: true, url: 'git@gitcode.net:qq_39626154/spring-boot-project.git', branch: "${BRANCH}", credentialsId: 'git-ssh-key')
            script {
              COMMIT_ID = sh(returnStdout: true, script: "git log -n 1 --pretty=format:'%h'").trim()
              TAG = BUILD_TAG + '-' + COMMIT_ID
              println "Current branch is ${BRANCH}, Commit ID is ${COMMIT_ID}, Image TAG is ${TAG}"
              
            }

          }
        }

        stage('Pulling Code by trigger') {
          when {
            expression {
              env.gitlabBranch != null
            }

          }
          steps {
            git(url: 'git@gitcode.net:qq_39626154/spring-boot-project.git', branch: env.gitlabBranch, changelog: true, poll: true, credentialsId: 'git-ssh-key')
            script {
              COMMIT_ID = sh(returnStdout: true, script: "git log -n 1 --pretty=format:'%h'").trim()
              TAG = BUILD_TAG + '-' + COMMIT_ID
              println "Current branch is ${env.gitlabBranch}, Commit ID is ${COMMIT_ID}, Image TAG is ${TAG}"
            }

          }
        }

      }
    }

    stage('Building') {
      steps {
            sh """ 
              /usr/local/maven/bin/mvn clean install -DskipTests
              ls target/*
            """
      }
    }

    stage('Docker build for creating image') {
      environment {
        HARBOR_USER     = credentials('HARBOR_ACCOUNT')
    }
      steps {
          sh """
          echo ${HARBOR_USER_USR} ${HARBOR_USER_PSW} ${COMMIT_ID} ${TAG}
          docker build -t ${HARBOR_ADDRESS}/${REGISTRY_DIR}/${IMAGE_NAME}:${COMMIT_ID} .
          docker login -u ${HARBOR_USER_USR} -p ${HARBOR_USER_PSW} ${HARBOR_ADDRESS}
          docker push ${HARBOR_ADDRESS}/${REGISTRY_DIR}/${IMAGE_NAME}:${COMMIT_ID}
          """
      }
    }

    stage('Deploying to K8s') {
      environment {
        MY_KUBECONFIG = credentials('study-k8s-kubeconfig')
    }
      steps {
           sh """
           /usr/local/bin/kubectl --kubeconfig $MY_KUBECONFIG set image deploy -l app=${IMAGE_NAME} ${IMAGE_NAME}=${HARBOR_ADDRESS}/${REGISTRY_DIR}/${IMAGE_NAME}:${COMMIT_ID} -n $NAMESPACE
           """
      }
    }

  }
  environment {
    COMMIT_ID = ""
    HARBOR_ADDRESS = "registry.cn-hangzhou.aliyuncs.com"
    REGISTRY_DIR = "maodocker"
    IMAGE_NAME = "spring-boot-project"
    NAMESPACE = "kubernetes"
    TAG = ""
  }
  parameters {
    gitParameter(branch: '', branchFilter: 'origin/(.*)', defaultValue: '', description: 'Branch for build and deploy', name: 'BRANCH', quickFilterEnabled: false, selectedValue: 'NONE', sortMode: 'NONE', tagFilter: '*', type: 'PT_BRANCH')
  }
}

 创建Dockerfile

在执行流水线过程时,需要将代码的编译产物做成镜像。Dockerfile主要写的是如何生成公司业务的镜像,而本示例是Java项目,只需要把JAR包放在有JRE环境的镜像中,然后启动该JAR包即可:

# 基础镜像可以按需修改,可以更改为公司自有的镜像
FROM registry.cn-beijing.aliyuncs.com/dotbalo/jre:8u211-data
#JAR包名称改成实际的名称,本示例为spring-cloud-eureka-0.0.1-SNAPSHOT.jar
COPY target/spring-cloud-eureka-0.0.1-SNAPSHOT.jar ./
# 启动JAR包
CMD java -jar spring-cloud-eureka-0.0.1-SNAPSHOT.jar

 定义 Kubernetes 资源

在GitLab创建的Group为kubernetes,可以认为其是一个项目,同一个项目可以部署至Kubernetes集群中的同一个Namespace中,本示例为kubernetes命名空间。由于使用的是私有仓库因此需要先配置拉取私有仓库镜像的密钥:

# kubectl create ns kubernetes
namespace/kubernetes created
# kubectl create secret docker-registry harborkey-docker-server=CHANGE HERE FOR YOUR HARBOR ADDRESS --docker-username=admin-docker-password=Harbor12345 --docker-email=mail@kubeasy.com -n kubernetes
secret/harborkey created

yaml文件app.yaml,资源限制部分请按照业务需求调整。

---
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: null
  labels:
    app: spring-boot-project
  name: spring-boot-project
  namespace: kubernetes
spec:
  ports:
  - name: web
    port: 8761
    protocol: TCP
    targetPort: 8761
  selector:
    app: spring-boot-project
  sessionAffinity: None
  type: ClusterIP
status:
  loadBalancer: {}
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  creationTimestamp: null
  name: spring-boot-project
  namespace: kubernetes
spec:
  ingressClassName: nginx
  rules:
  - host: spring-boot-project.test.com
    http:
      paths:
      - backend:
          service:
            name: spring-boot-project
            port: 
              number: 8761
        path: /
        pathType: ImplementationSpecific
      
---
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: spring-boot-project
  name: spring-boot-project
  namespace: kubernetes
spec:
  replicas: 1
  selector:
    matchLabels:
      app: spring-boot-project
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: spring-boot-project
    spec:
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - spring-boot-project
              topologyKey: kubernetes.io/hostname
            weight: 100
      containers:
      - env:
        - name: TZ
          value: Asia/Shanghai
        - name: LANG
          value: C.UTF-8
        image: registry.cn-hangzhou.aliyuncs.com/maodocker/springboot-project:v0.0.1
        imagePullPolicy: IfNotPresent
        lifecycle: {}
        livenessProbe:
          failureThreshold: 2
          initialDelaySeconds: 30
          periodSeconds: 10
          successThreshold: 1
          tcpSocket:
            port: 8761
          timeoutSeconds: 2
        name: spring-boot-project
        ports:
        - containerPort: 8761
          name: web
          protocol: TCP
        readinessProbe:
          failureThreshold: 2
          initialDelaySeconds: 30
          periodSeconds: 10
          successThreshold: 1
          tcpSocket:
            port: 8761
          timeoutSeconds: 2
        resources:
          limits:
            cpu: 994m
            memory: 1170Mi
          requests:
            cpu: 10m
            memory: 55Mi
      dnsPolicy: ClusterFirst
      imagePullSecrets:
      - name: harborkey
      restartPolicy: Always
      securityContext: {}
      serviceAccountName: default

先再集群上部署该应用:

# kubectl apply -f app.yaml

创建Jenkins任务

 

 

 点击Build Now,第一次构建之后会出现Build with Parameters就可以选择分支构建。

 点击构建查看控制台输出:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值