|
1 | | -# devops-java-sample |
2 | | -A Java sample for devops on kubesphere |
| 1 | +## 基于springboot构建流水线示例项目 |
| 2 | + |
| 3 | +Jenkinsfile in SCM 意为将 Jenkinsfile 文件本身作为源代码管理 (Source Control Management) 的一部分,根据该文件内的流水线配置信息快速构建工程内的 CI/CD 功能模块,比如阶段 (Stage),步骤 (Step) 和任务 (Job)。因此,在代码仓库中包含 Jenkinsfile。 |
| 4 | + |
| 5 | +## 项目介绍 |
| 6 | + |
| 7 | +#### 本项目为kubesphere 基于springboot构建流水线示例项目,具体参见kubesphere [V2.1教程](https://v2-1.docs.kubesphere.io/docs/zh-CN/quick-start/devops-online/),[V3.0教程](https://kubesphere.com.cn/docs/devops-user-guide/how-to-use/create-a-pipeline-using-jenkinsfile/) |
| 8 | + |
| 9 | +项目中包含**Jenkinsfile in SCM** :Jenkinsfile-online文件(Jenkinsfile in SCM 意为将 Jenkinsfile 文件本身作为源代码管理 (Source Control Management) 的一部分),kubesphere 内置Jenkins容器,**Jenkins**可以根据该文件内的流水线配置信息快速构建工程内的 CI/CD 功能模块,比如阶段 (Stage),步骤 (Step) 和任务 (Job)。 |
| 10 | + |
| 11 | + Jenkinsfile 来创建流水线,流水线共包括 8 个阶段,最终将演示示例部署到 KubeSphere 集群中的开发环境和生产环境且能够通过公网访问。 仓库中的 dependency 分支为缓存测试用例,测试方式与 master 分支类似,对 dependency 的多次构建可体现出利用缓存可以有效的提升构建速度。 |
| 12 | + |
| 13 | +## 项目使用 |
| 14 | + |
| 15 | +* 项目完成fork后,根据教程修改 Jenkinsfile-online中的环境变量为您自己值。 |
| 16 | + |
| 17 | + |
| 18 | + |
| 19 | +* 根据教程,使用项目管理员 `project-admin`账号登录 KubeSphere,在之前创建的企业空间 (demo-workspace) 下,点击 **项目 → 创建**,创建两个 **资源型项目** `kubesphere-sample-dev` 、kubesphere-sample-prod |
| 20 | + |
| 21 | + * 名称:固定为 `kubesphere-sample-dev`,kubesphere-sample-prod,若需要修改项目名称则需在本项目中的 [[deploy/dev-ol/](deploy/dev-ol/)] 、 [[deploy/prod-ol/](deploy/prod-ol/)]中修改 namespace 属性 |
| 22 | + |
| 23 | + ## Jenkinsfile-online文件介绍 |
| 24 | + |
| 25 | + 考虑到初学者可能对Jenkins文件不熟悉,对此文件进行介绍,方便您理解我们的流水线做了什么. |
| 26 | + |
| 27 | + ``` yaml |
| 28 | + pipeline { |
| 29 | + agent { |
| 30 | + node { |
| 31 | + label 'maven' // 定义流水线的代理为 maven,kubesphere内置了四个默认代理,在目前版本当中我们内置了 4 种类型的 podTemplate,base、 // nodejs、maven、go,并且在 Pod 中提供了隔离的 Docker 环境。具体参见官方文档 |
| 32 | + } |
| 33 | + } |
| 34 | + |
| 35 | + parameters { |
| 36 | + string(name:'TAG_NAME',defaultValue: '',description:'') //定义 流水线描述 |
| 37 | + } |
| 38 | + environment { //定义流水线环境变量 |
| 39 | + DOCKER_CREDENTIAL_ID = 'dockerhub-id' |
| 40 | + GITHUB_CREDENTIAL_ID = 'github-id' |
| 41 | + KUBECONFIG_CREDENTIAL_ID = 'demo-kubeconfig' |
| 42 | + REGISTRY = 'docker.io' |
| 43 | + DOCKERHUB_NAMESPACE = 'docker_username' |
| 44 | + GITHUB_ACCOUNT = 'kubesphere' |
| 45 | + APP_NAME = 'devops-java-sample' |
| 46 | + } |
| 47 | + ``` |
| 48 | + |
| 49 | + **[Jenkins Agent 说明]( https://v2-1.docs.kubesphere.io/docs/zh-CN/devops/jenkins-agent/)** |
| 50 | + |
| 51 | + * **第一步**检出代码 |
| 52 | + |
| 53 | + ```yaml |
| 54 | + stages { |
| 55 | + stage ('checkout scm') { |
| 56 | + steps { |
| 57 | + checkout(scm) |
| 58 | + } |
| 59 | + } |
| 60 | + ``` |
| 61 | + |
| 62 | + * **第二步** 执行单元测试 |
| 63 | + |
| 64 | + ```yaml |
| 65 | + stage ('unit test') { |
| 66 | + steps { |
| 67 | + container ('maven') { |
| 68 | + sh 'mvn clean -gs `pwd`/configuration/settings.xml test' |
| 69 | + } |
| 70 | + } |
| 71 | + } |
| 72 | + ``` |
| 73 | + |
| 74 | + * **第三步** 执行单元测试 |
| 75 | + |
| 76 | + ```yaml |
| 77 | + stage('push latest'){ |
| 78 | + when{ |
| 79 | + branch 'master' |
| 80 | + } |
| 81 | + steps{ |
| 82 | + container ('maven') { |
| 83 | + sh 'docker tag $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:latest ' |
| 84 | + sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:latest ' |
| 85 | + } |
| 86 | + } |
| 87 | + } |
| 88 | + |
| 89 | + ``` |
| 90 | + |
| 91 | + * **第四步** 编译并推送 |
| 92 | + |
| 93 | + ```yaml |
| 94 | + stage ('build & push') { |
| 95 | + steps { |
| 96 | + container ('maven') { |
| 97 | + sh 'mvn -Dmaven.test.skip=true -gs `pwd`/configuration/settings.xml clean package' |
| 98 | + sh 'docker build -f Dockerfile-online -t $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER .' |
| 99 | + withCredentials([usernamePassword(passwordVariable : 'DOCKER_PASSWORD' ,usernameVariable : 'DOCKER_USERNAME' ,credentialsId : "$DOCKER_CREDENTIAL_ID" ,)]) { |
| 100 | + sh 'echo "$DOCKER_PASSWORD" | docker login $REGISTRY -u "$DOCKER_USERNAME" --password-stdin' |
| 101 | + sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER' |
| 102 | + } |
| 103 | + } |
| 104 | + } |
| 105 | + } |
| 106 | + ``` |
| 107 | + |
| 108 | + * **第五步** 推送至docker hub latest版本 |
| 109 | + |
| 110 | + ```yaml |
| 111 | + stage('push latest'){ |
| 112 | + when{ |
| 113 | + branch 'master' |
| 114 | + } |
| 115 | + steps{ |
| 116 | + container ('maven') { |
| 117 | + sh 'docker tag $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:latest ' |
| 118 | + sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:latest ' |
| 119 | + } |
| 120 | + } |
| 121 | + } |
| 122 | + |
| 123 | + ``` |
| 124 | + |
| 125 | + * **第六步** 弹出审核确认,是否部署到开发环境 |
| 126 | + |
| 127 | + ```yaml |
| 128 | + stage('deploy to dev') { |
| 129 | + when{ |
| 130 | + branch 'master' |
| 131 | + } |
| 132 | + steps { |
| 133 | + input(id: 'deploy-to-dev', message: 'deploy to dev?') |
| 134 | + kubernetesDeploy(configs: 'deploy/dev-ol/**', enableConfigSubstitution: true, kubeconfigId: "$KUBECONFIG_CREDENTIAL_ID") |
| 135 | + } |
| 136 | + } |
| 137 | + stage('push with tag'){ |
| 138 | + when{ |
| 139 | + expression{ |
| 140 | + return params.TAG_NAME =~ /v.*/ |
| 141 | + } |
| 142 | + } |
| 143 | + steps { |
| 144 | + container ('maven') { |
| 145 | + input(id: 'release-image-with-tag', message: 'release image with tag?') |
| 146 | + withCredentials([usernamePassword(credentialsId: "$GITHUB_CREDENTIAL_ID", passwordVariable: 'GIT_PASSWORD', usernameVariable: 'GIT_USERNAME')]) { |
| 147 | + sh 'git config --global user.email "kubesphere@yunify.com" ' |
| 148 | + sh 'git config --global user.name "kubesphere" ' |
| 149 | + sh 'git tag -a $TAG_NAME -m "$TAG_NAME" ' |
| 150 | + sh 'git push http://$GIT_USERNAME:$GIT_PASSWORD@github.com/$GITHUB_ACCOUNT/devops-java-sample.git --tags --ipv4' |
| 151 | + } |
| 152 | + sh 'docker tag $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:$TAG_NAME ' |
| 153 | + sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:$TAG_NAME ' |
| 154 | + } |
| 155 | + } |
| 156 | + } |
| 157 | + ``` |
| 158 | + |
| 159 | + * **第七步** 部署到生产环境 |
| 160 | + |
| 161 | + ```yaml |
| 162 | + stage('deploy to production') { |
| 163 | + when{ |
| 164 | + expression{ |
| 165 | + return params.TAG_NAME =~ /v.*/ |
| 166 | + } |
| 167 | + } |
| 168 | + steps { |
| 169 | + input(id: 'deploy-to-production', message: 'deploy to production?') |
| 170 | + kubernetesDeploy(configs: 'deploy/prod-ol/**', enableConfigSubstitution: true, kubeconfigId: "$KUBECONFIG_CREDENTIAL_ID") |
| 171 | + } |
| 172 | + } |
| 173 | + ``` |
| 174 | + |
| 175 | + |
0 commit comments