写在最前

因为有一些比较前沿的springboot项目采用的是gradle没有使用maven, 故而本篇章介绍一下如何自定义podTemplate接入gradle到kubesphere

1. 构建流程

KubeSphere 官方的 builder-base 代码库可以在 https://github.com/kubesphere/devops-agent/tree/master/gradle 找到,里面包含了 DevOps 相关的构建工具与配置。如果你需要下载其他版本的 OpenJDK,可以参考 JDK 官方提供的 https://jdk.java.net/java-se-ri/17-MR1,该页面列出了各个版本的详细下载信息,方便你根据需求选择合适的版本进行使用。

1.1 openjdk11

FROM kubespheredev/builder-base:v3.1.0

# gradle6
ENV GRADLE_VERSION 6.9.1
ENV GRADLE_HOME /usr/local/gradle-${GRADLE_VERSION}
ENV PATH ${GRADLE_HOME}/bin:$PATH

# 下载并安装 Gradle
RUN curl -fSL https://services.gradle.org/distributions/gradle-${GRADLE_VERSION}-bin.zip -o gradle.zip && \
    echo "$(curl -sLf https://services.gradle.org/distributions/gradle-${GRADLE_VERSION}-bin.zip.sha256) gradle.zip" | sha256sum --check && \
    unzip -q gradle.zip -d /usr/local && \
    rm -f gradle.zip

# 通过 RUN 检查 Gradle 版本
RUN gradle --version

# 下载并安装 OpenJDK 11(使用指定的 URL)
RUN curl -fSL https://download.java.net/openjdk/jdk11.0.0.2/ri/openjdk-11.0.0.2_linux-x64.tar.gz -o /tmp/openjdk-11.tar.gz && \
    tar -xzf /tmp/openjdk-11.tar.gz -C /usr/local && \
    rm -f /tmp/openjdk-11.tar.gz

# 设置 JAVA_HOME 和 PATH
ENV JAVA_HOME /usr/local/jdk-11.0.0.2
ENV PATH $JAVA_HOME/bin:$PATH

# 通过 RUN 检查 Java 版本
RUN java -version

1.2 openjdk17

FROM kubespheredev/builder-base:v3.1.0

# gradle6
ENV GRADLE_VERSION 6.9.1
ENV GRADLE_HOME /usr/local/gradle-${GRADLE_VERSION}
ENV PATH ${GRADLE_HOME}/bin:$PATH

# 下载并安装 Gradle
RUN curl -fSL https://services.gradle.org/distributions/gradle-${GRADLE_VERSION}-bin.zip -o gradle.zip && \
    echo "$(curl -sLf https://services.gradle.org/distributions/gradle-${GRADLE_VERSION}-bin.zip.sha256) gradle.zip" | sha256sum --check && \
    unzip -q gradle.zip -d /usr/local && \
    rm -f gradle.zip

# 通过 RUN 检查 Gradle 版本
RUN gradle --version

# 下载并安装 OpenJDK 17(使用指定的 URL)
RUN curl -fSL https://download.java.net/openjdk/jdk17.0.0.1/ri/openjdk-17.0.0.1+2_linux-x64_bin.tar.gz -o /tmp/openjdk-17.tar.gz && \
    tar -xzf /tmp/openjdk-17.tar.gz -C /usr/local && \
    rm -f /tmp/openjdk-17.tar.gz

# 设置 JAVA_HOME 和 PATH
ENV JAVA_HOME /usr/local/jdk-17.0.0.1
ENV PATH $JAVA_HOME/bin:$PATH

# 通过 RUN 检查 Java 版本
RUN java -version

2. 连接测试

2.1 jenkins-casc-config

我就用gradle6.9.1-openjdk11来演示

- name: "gradle6.9.1-openjdk11"
  namespace: "kubesphere-devops-worker"
  label: "gradle6.9.1-openjdk11"
  nodeUsageMode: "EXCLUSIVE"
  idleMinutes: 0
  containers:
  - name: "gradle"
    image: "registry.cn-hangzhou.aliyuncs.com/tanqidi/build-gradle:gradle6.9.1-openjdk11"
    command: "cat"
    args: ""
    ttyEnabled: true
    privileged: false
    resourceRequestCpu: "100m"
    resourceLimitCpu: "4000m"
    resourceRequestMemory: "100Mi"
    resourceLimitMemory: "8192Mi"
  - name: "jnlp"
    image: "registry.cn-beijing.aliyuncs.com/kubesphereio/inbound-agent:4.10-2"
    args: "^${computer.jnlpmac} ^${computer.name}"
    resourceRequestCpu: "50m"
    resourceLimitCpu: "500m"
    resourceRequestMemory: "400Mi"
    resourceLimitMemory: "1536Mi"
  workspaceVolume:
    emptyDirWorkspaceVolume:
      memory: false
  volumes:
  - hostPathVolume:
      hostPath: "/var/run/docker.sock"
      mountPath: "/var/run/docker.sock"
  - hostPathVolume:
      hostPath: "/data/gradle"
      mountPath: "/root/.gradle/"                    
  yaml: |
    spec:
      affinity:
        nodeAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 1
            preference:
              matchExpressions:
              - key: node-role.kubernetes.io/worker
                operator: In
                values:
                - ci
      tolerations:
      - key: "node.kubernetes.io/ci"
        operator: "Exists"
        effect: "NoSchedule"
      - key: "node.kubernetes.io/ci"
        operator: "Exists"
        effect: "PreferNoSchedule"
      containers:
      - name: "gradle"
        resources:
          requests:
            ephemeral-storage: "1Gi"
          limits:
            ephemeral-storage: "10Gi"
      securityContext:
        fsGroup: 1000 

2.2 jenkinsfile

我写了一个简单的gradle的springboot小demo项目,你可以fork到你的gitee仓库里面去,https://gitee.com/tanqidi/gradle

图片-spnc.png

pipeline {
  agent {
    node {
      label 'gradle6.9.1-openjdk11'
    }

  }
  stages {
    stage('拉取项目') {
      agent none
      when {
        environment name: 'BUILD_ENV', value: 'UAT_CICD'
      }
      steps {
        container('gradle') {
          git(credentialsId: 'gitee-secret', branch: 'master', url: 'https://gitee.com/tanqidi/gradle.git', changelog: true, poll: false)
        }

      }
    }

    stage('项目编译') {
      agent none
      when {
        environment name: 'BUILD_ENV', value: 'UAT_CICD'
      }
      steps {
        container('gradle') {
          sh 'gradle build --info'
        }

      }
    }

    stage('镜像构建') {
      agent none
      when {
        environment name: 'BUILD_ENV', value: 'UAT_CICD'
      }
      steps {
        container('gradle') {
          script {
            sh 'docker build -t $REGISTRY/$HARBOR_NAMESPACE/$MODULE_NAME:$MODULE_VERSION .'
          }

        }

      }
    }

    stage('镜像推送') {
      agent none
      when {
        environment value: 'UAT_CICD', name: 'BUILD_ENV'
      }
      steps {
        container('gradle') {
          withCredentials([usernamePassword(credentialsId : 'aliyun-harbor-secret' ,passwordVariable : 'name' ,usernameVariable : 'passwd' ,)]) {
            sh 'echo "$name" | docker login $REGISTRY -u "$passwd" --password-stdin'
            sh 'docker push $REGISTRY/$HARBOR_NAMESPACE/$MODULE_NAME:$MODULE_VERSION'
          }

        }

      }
    }

    stage('部署到UAT环境') {
      agent none
      steps {
        container('gradle') {
          withCredentials([kubeconfigFile(credentialsId: "$KUBECONFIG_CREDENTIAL_ID", variable: 'KUBECONFIG')]) {
            script {
              sh "echo \'${DEPLOY_YAML}\' > deploy.yaml"
              sh "cat deploy.yaml"
              sh "envsubst < deploy.yaml | kubectl apply -f -"
            }

          }

        }

      }
    }

  }
  environment {
    KUBECONFIG_CREDENTIAL_ID = 'k8s-kubeconfig'
    REGISTRY = 'registry.cn-hangzhou.aliyuncs.com'
    HARBOR_NAMESPACE = 'tanqidi-temp'
    PROJECT_NAMESPACE = 'test'
    DEPLOY_YAML = '''

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: ${MODULE_NAME}
  annotations:
     kubesphere.io/description: \'${HARBOR_NAMESPACE}/${MODULE_NAME}:$MODULE_VERSION\'
  name: ${MODULE_NAME}
  namespace: ${PROJECT_NAMESPACE}
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ${MODULE_NAME}
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 25%
      maxSurge: 25%
  revisionHistoryLimit: 10
  progressDeadlineSeconds: 600

  template:
    metadata:
      labels:
        app: ${MODULE_NAME}
    spec:
      imagePullSecrets:
        - name: harbor
      containers:
        - name: ${MODULE_NAME}
          imagePullPolicy: Always
          image: $REGISTRY/$HARBOR_NAMESPACE/$MODULE_NAME:$MODULE_VERSION
          ports:
            - name: http-8080
              containerPort: 8080
              protocol: TCP
          resources:
            limits:
              cpu: \'1\'
              memory: 2Gi
            requests:
              cpu: 25m
              memory: 850Mi
      restartPolicy: Always
      terminationGracePeriodSeconds: 30
---
apiVersion: v1
kind: Service
metadata:
  name: ${MODULE_NAME}
  namespace: ${PROJECT_NAMESPACE}
  labels:
    app: ${MODULE_NAME}
spec:
  ports:
    - port: 8080
      targetPort: 8080
  selector:
    app: ${MODULE_NAME}
  type: ClusterIP
  sessionAffinity: None

'''
  }
  parameters {
    choice(name: 'MODULE_NAME', choices: '''test-gradle
''', description: '模块构建')
    choice(name: 'BUILD_ENV', choices: '''UAT_CICD
UAT_CD''', description: '构建环境')
    string(name: 'MODULE_VERSION', defaultValue: 'v0.0Beta', description: '模块版本')
  }
}

2.3 构建测试

选择gradle6.9.1-openjdk11,运行结果完整正确

图片-hrsh.png

图片-pzqf.png

2.4 试验访问

流水线会自动生成deployment,service要手动变更为NodePort来试验访问

图片-vcmu.png

图片-gvvw.png

图片-dhly.png

3. 镜像制品

  • registry.cn-hangzhou.aliyuncs.com/tanqidi/build-gradle:gradle6.9.1-openjdk11

  • registry.cn-hangzhou.aliyuncs.com/tanqidi/build-gradle:gradle6.9.1-openjdk17

4. 操作总结

总的来说还是比较快速的就配置上了gradle并且构建通过了,在jenkins-case-conig那个部分比较晦涩难懂,可以看看前面的构建章节是有详细截图和描述的。