目录
创建DevOps工程
拉取代码
项目编译
构建镜像
推送镜像
部署到Dev环境
邮件功能
激活微服务
这里是CS大白话专场,让枯燥的学习变得有趣!
没有对象不要怕,我们new一个出来,每天对ta说不尽情话!
好记性不如烂键盘,自己总结不如收藏别人!
本章我们来学习 DevOps 开发部署全流程,直接在 KubeSphere 中创建可视化流水线,将一个医疗项目自动化部署上云。
在创建工程之前我们先把 maven 配置修改一下,让它从阿里云下载镜像。流水线带有缓存机制,已经下载过的 jar包,下一次流水线启动不会重复下载。
nexus-aliyun
central
Nexus aliyun
http://maven.aliyun.com/nexus/content/groups/public
首先进入企业空间点击 DevOps 工程,创建一个 DevOps 工程。
进入创建的 DevOps 工程创建一个流水线,然后就可以对流水线进行可视化编辑。
第一步从 Gitee 上拉取代码,并查询下载的文件。
点击空白处选择代理 选择 Jenkins Agent (kubesphere.io),这里我们是Java应用指定 maven 。
点击第一个框,在右下角的任务处添加步骤指定 maven 容器。
添加嵌套步骤,通过 Git 拉取仓库中的项目代码,需要创建一个自己的凭证,选定代码分支。
拉取完代码之后通过 shell 命令 ls 显示下载的文件。
第二步项目编译,点击第二个框,添加 shell 命令:
mvn clean package -Dmaven.test.skip=true
第三步并发构建每个服务的镜像。
添加一个并行阶段,先检查上一步项目编译是否产生target文件,再构建镜像。
#检查编译文件target
ls hospital-manage/target
#构建镜像
docker build -t hospital-manage:latest -f hospital-manage/Dockerfile ./hospital-manage/
一个并行阶段构建一个服务镜像比较麻烦,接下来可以编辑 Jenkins 文件来构建并行阶段。
stage('default-2') {
parallel {
stage('build hospital-manage image') {
agent none
steps {
container('maven') {
sh 'ls hospital-manage/target'
sh 'docker build -t hospital-manage:latest -f hospital-manage/Dockerfile ./hospital-manage/'
}
}
}
stage('build server-gateway image') {
agent none
steps {
container('maven') {
sh 'ls server-gateway/target'
sh 'docker build -t server-gateway:latest -f server-gateway/Dockerfile ./server-gateway/'
}
}
}
stage('build service-cmn image') {
agent none
steps {
container('maven') {
sh 'ls service/service-cmn/target'
sh 'docker build -t service-cmn:latest -f service/service-cmn/Dockerfile ./service/service-cmn/'
}
}
}
stage('build service-hosp image') {
agent none
steps {
container('maven') {
sh 'ls service/service-hosp/target'
sh 'docker build -t service-hosp:latest -f service/service-hosp/Dockerfile ./service/service-hosp/'
}
}
}
stage('build service-order image') {
agent none
steps {
container('maven') {
sh 'ls service/service-order/target'
sh 'docker build -t service-order:latest -f service/service-order/Dockerfile ./service/service-order/'
}
}
}
stage('build service-oss image') {
agent none
steps {
container('maven') {
sh 'ls service/service-oss/target'
sh 'docker build -t service-oss:latest -f service/service-oss/Dockerfile ./service/service-oss/'
}
}
}
stage('build service-sms image') {
agent none
steps {
container('maven') {
sh 'ls service/service-sms/target'
sh 'docker build -t service-sms:latest -f service/service-sms/Dockerfile ./service/service-sms/'
}
}
}
stage('build service-statistics image') {
agent none
steps {
container('maven') {
sh 'ls service/service-statistics/target'
sh 'docker build -t service-statistics:latest -f service/service-statistics/Dockerfile ./service/service-statistics/'
}
}
}
stage('build service-task image') {
agent none
steps {
container('maven') {
sh 'ls service/service-task/target'
sh 'docker build -t service-task:latest -f service/service-task/Dockerfile ./service/service-task/'
}
}
}
stage('build service-user image') {
agent none
steps {
container('maven') {
sh 'ls service/service-user/target'
sh 'docker build -t service-user:latest -f service/service-user/Dockerfile ./service/service-user/'
}
}
}
}
}
第四步并行推送每个镜像到阿里云镜像仓库上,每个服务器从镜像仓库下载镜像,和上一步类似。
阿里云容器镜像服务中创建命名空间。容器镜像服务 (aliyun.com)
点击第四个框,添加阿里云凭证。
编辑 Jenkinsfile 的环境。
environment {
DOCKER_CREDENTIAL_ID = 'dockerhub-id'
GITHUB_CREDENTIAL_ID = 'github-id'
KUBECONFIG_CREDENTIAL_ID = 'demo-kubeconfig'
REGISTRY = 'registry-vpc.cn-beijing.aliyuncs.com' //REGISTRY地址
DOCKERHUB_NAMESPACE = 'jodie-hospital' //命名空间名称
GITHUB_ACCOUNT = 'kubesphere'
APP_NAME = 'devops-java-sample'
}
在添加凭证中添加嵌套步骤。
echo "$DOCKER_PWD_VAR" | docker login $REGISTRY -u "$DOCKER_USER_VAR" --password-stdin
docker tag hospital-manage:latest $REGISTRY/$DOCKERHUB_NAMESPACE/hospital-manage:SNAPSHOT-$BUILD_NUMBER
docker push $REGISTRY/$DOCKERHUB_NAMESPACE/hospital-manage:SNAPSHOT-$BUILD_NUMBER
编辑 Jenkinsfile 并行阶段。
stage('default-3') {
parallel {
stage('push hospital-manage image') {
agent none
steps {
container('maven') {
withCredentials([usernamePassword(credentialsId : 'aliyun-id' ,usernameVariable : 'DOCKER_USER_VAR' ,passwordVariable : 'DOCKER_PWD_VAR' ,)]) {
sh 'echo "$DOCKER_PWD_VAR" | docker login $REGISTRY -u "$DOCKER_USER_VAR" --password-stdin'
sh 'docker tag hospital-manage:latest $REGISTRY/$DOCKERHUB_NAMESPACE/hospital-manage:SNAPSHOT-$BUILD_NUMBER'
sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/hospital-manage:SNAPSHOT-$BUILD_NUMBER'
}
}
}
}
stage('push hospital-gateway image') {
agent none
steps {
container('maven') {
withCredentials([usernamePassword(credentialsId : 'aliyun-id' ,usernameVariable : 'DOCKER_USER_VAR' ,passwordVariable : 'DOCKER_PWD_VAR' ,)]) {
sh 'echo "$DOCKER_PWD_VAR" | docker login $REGISTRY -u "$DOCKER_USER_VAR" --password-stdin'
sh 'docker tag hospital-gateway:latest $REGISTRY/$DOCKERHUB_NAMESPACE/hospital-gateway:SNAPSHOT-$BUILD_NUMBER'
sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/hospital-gateway:SNAPSHOT-$BUILD_NUMBER'
}
}
}
}
stage('push service-cmn image') {
agent none
steps {
container('maven') {
withCredentials([usernamePassword(credentialsId : 'aliyun-id' ,usernameVariable : 'DOCKER_USER_VAR' ,passwordVariable : 'DOCKER_PWD_VAR' ,)]) {
sh 'echo "$DOCKER_PWD_VAR" | docker login $REGISTRY -u "$DOCKER_USER_VAR" --password-stdin'
sh 'docker tag service-cmn:latest $REGISTRY/$DOCKERHUB_NAMESPACE/service-cmn:SNAPSHOT-$BUILD_NUMBER'
sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/service-cmn:SNAPSHOT-$BUILD_NUMBER'
}
}
}
}
stage('push service-hosp image') {
agent none
steps {
container('maven') {
withCredentials([usernamePassword(credentialsId : 'aliyun-id' ,usernameVariable : 'DOCKER_USER_VAR' ,passwordVariable : 'DOCKER_PWD_VAR' ,)]) {
sh 'echo "$DOCKER_PWD_VAR" | docker login $REGISTRY -u "$DOCKER_USER_VAR" --password-stdin'
sh 'docker tag service-hosp:latest $REGISTRY/$DOCKERHUB_NAMESPACE/service-hosp:SNAPSHOT-$BUILD_NUMBER'
sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/service-hosp:SNAPSHOT-$BUILD_NUMBER'
}
}
}
}
stage('push service-order image') {
agent none
steps {
container('maven') {
withCredentials([usernamePassword(credentialsId : 'aliyun-id' ,usernameVariable : 'DOCKER_USER_VAR' ,passwordVariable : 'DOCKER_PWD_VAR' ,)]) {
sh 'echo "$DOCKER_PWD_VAR" | docker login $REGISTRY -u "$DOCKER_USER_VAR" --password-stdin'
sh 'docker tag service-order:latest $REGISTRY/$DOCKERHUB_NAMESPACE/service-order:SNAPSHOT-$BUILD_NUMBER'
sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/service-order:SNAPSHOT-$BUILD_NUMBER'
}
}
}
}
stage('push service-oss image') {
agent none
steps {
container('maven') {
withCredentials([usernamePassword(credentialsId : 'aliyun-id' ,usernameVariable : 'DOCKER_USER_VAR' ,passwordVariable : 'DOCKER_PWD_VAR' ,)]) {
sh 'echo "$DOCKER_PWD_VAR" | docker login $REGISTRY -u "$DOCKER_USER_VAR" --password-stdin'
sh 'docker tag service-oss:latest $REGISTRY/$DOCKERHUB_NAMESPACE/service-oss:SNAPSHOT-$BUILD_NUMBER'
sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/service-oss:SNAPSHOT-$BUILD_NUMBER'
}
}
}
}
stage('push service-sms image') {
agent none
steps {
container('maven') {
withCredentials([usernamePassword(credentialsId : 'aliyun-id' ,usernameVariable : 'DOCKER_USER_VAR' ,passwordVariable : 'DOCKER_PWD_VAR' ,)]) {
sh 'echo "$DOCKER_PWD_VAR" | docker login $REGISTRY -u "$DOCKER_USER_VAR" --password-stdin'
sh 'docker tag service-sms:latest $REGISTRY/$DOCKERHUB_NAMESPACE/service-sms:SNAPSHOT-$BUILD_NUMBER'
sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/service-sms:SNAPSHOT-$BUILD_NUMBER'
}
}
}
}
stage('push service-statistics image') {
agent none
steps {
container('maven') {
withCredentials([usernamePassword(credentialsId : 'aliyun-id' ,usernameVariable : 'DOCKER_USER_VAR' ,passwordVariable : 'DOCKER_PWD_VAR' ,)]) {
sh 'echo "$DOCKER_PWD_VAR" | docker login $REGISTRY -u "$DOCKER_USER_VAR" --password-stdin'
sh 'docker tag service-statistics:latest $REGISTRY/$DOCKERHUB_NAMESPACE/service-statistics:SNAPSHOT-$BUILD_NUMBER'
sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/service-statistics:SNAPSHOT-$BUILD_NUMBER'
}
}
}
}
stage('push service-task image') {
agent none
steps {
container('maven') {
withCredentials([usernamePassword(credentialsId : 'aliyun-id' ,usernameVariable : 'DOCKER_USER_VAR' ,passwordVariable : 'DOCKER_PWD_VAR' ,)]) {
sh 'echo "$DOCKER_PWD_VAR" | docker login $REGISTRY -u "$DOCKER_USER_VAR" --password-stdin'
sh 'docker tag service-task:latest $REGISTRY/$DOCKERHUB_NAMESPACE/service-task:SNAPSHOT-$BUILD_NUMBER'
sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/service-task:SNAPSHOT-$BUILD_NUMBER'
}
}
}
}
stage('push service-user image') {
agent none
steps {
container('maven') {
withCredentials([usernamePassword(credentialsId : 'aliyun-id' ,usernameVariable : 'DOCKER_USER_VAR' ,passwordVariable : 'DOCKER_PWD_VAR' ,)]) {
sh 'echo "$DOCKER_PWD_VAR" | docker login $REGISTRY -u "$DOCKER_USER_VAR" --password-stdin'
sh 'docker tag service-user:latest $REGISTRY/$DOCKERHUB_NAMESPACE/service-user:SNAPSHOT-$BUILD_NUMBER'
sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/service-user:SNAPSHOT-$BUILD_NUMBER'
}
}
}
}
}
}
第五步给每一个微服务准备一个 deploy.yaml(k8s的部署配置文件),并在流水线中指定文件位置。
点击第五个框 kubernetesDeploy 插件会报错 ,我们先在工程管理里添加凭证,ID 为之前环境中给出的 demo-kubeconfig。
和之前步骤一样直接编写并行阶段,参考构建和部署 Maven 项目 (kubesphere.io)。
stage('default-4') {
parallel {
stage('deploy hospital-manage to dev') {
agent none
steps {
container('maven') {
withCredentials([
kubeconfigFile(
credentialsId: env.KUBECONFIG_CREDENTIAL_ID,
variable: 'KUBECONFIG')
]) {
sh 'envsubst < hospital-manage/deploy/deploy.yml | kubectl apply -f -'
}
}
}
}
stage('deploy server-gateway to dev') {
agent none
steps {
container('maven') {
withCredentials([
kubeconfigFile(
credentialsId: env.KUBECONFIG_CREDENTIAL_ID,
variable: 'KUBECONFIG')
]) {
sh 'envsubst < server-gateway/deploy/deploy.yml | kubectl apply -f -'
}
}
}
}
stage('deploy service-cmn to dev') {
agent none
steps {
container('maven') {
withCredentials([
kubeconfigFile(
credentialsId: env.KUBECONFIG_CREDENTIAL_ID,
variable: 'KUBECONFIG')
]) {
sh 'envsubst < service/service-cmn/deploy/deploy.yml | kubectl apply -f -'
}
}
}
}
stage('deploy service-hosp to dev') {
agent none
steps {
container('maven') {
withCredentials([
kubeconfigFile(
credentialsId: env.KUBECONFIG_CREDENTIAL_ID,
variable: 'KUBECONFIG')
]) {
sh 'envsubst < service/service-hosp/deploy/deploy.yml | kubectl apply -f -'
}
}
}
}
stage('deploy service-order to dev') {
agent none
steps {
container('maven') {
withCredentials([
kubeconfigFile(
credentialsId: env.KUBECONFIG_CREDENTIAL_ID,
variable: 'KUBECONFIG')
]) {
sh 'envsubst < service/service-order/deploy/deploy.yml | kubectl apply -f -'
}
}
}
}
stage('deploy service-oss to dev') {
agent none
steps {
container('maven') {
withCredentials([
kubeconfigFile(
credentialsId: env.KUBECONFIG_CREDENTIAL_ID,
variable: 'KUBECONFIG')
]) {
sh 'envsubst < service/service-oss/deploy/deploy.yml | kubectl apply -f -'
}
}
}
}
stage('deploy service-sms to dev') {
agent none
steps {
container('maven') {
withCredentials([
kubeconfigFile(
credentialsId: env.KUBECONFIG_CREDENTIAL_ID,
variable: 'KUBECONFIG')
]) {
sh 'envsubst < service/service-sms/deploy/deploy.yml | kubectl apply -f -'
}
}
}
}
stage('deploy service-statistics to dev') {
agent none
steps {
container('maven') {
withCredentials([
kubeconfigFile(
credentialsId: env.KUBECONFIG_CREDENTIAL_ID,
variable: 'KUBECONFIG')
]) {
sh 'envsubst < service/service-statistics/deploy/deploy.yml | kubectl apply -f -'
}
}
}
}
stage('deploy service-task to dev') {
agent none
steps {
container('maven') {
withCredentials([
kubeconfigFile(
credentialsId: env.KUBECONFIG_CREDENTIAL_ID,
variable: 'KUBECONFIG')
]) {
sh 'envsubst < service/service-task/deploy/deploy.yml | kubectl apply -f -'
}
}
}
}
stage('deploy service-user to dev') {
agent none
steps {
container('maven') {
withCredentials([
kubeconfigFile(
credentialsId: env.KUBECONFIG_CREDENTIAL_ID,
variable: 'KUBECONFIG')
]) {
sh 'envsubst < service/service-user/deploy/deploy.yml | kubectl apply -f -'
}
}
}
}
}
}
项目配置中心中添加阿里云密钥。
第六步搭建邮件发送功能,部署成功后给指定邮箱发送通知。
使用QQ邮箱,开启POP3/SMTP服务。 jxqkqmuaapegbebh
编辑工作负载 ks-jenkins 配置文件。
KuberSphere 平台设置-通知管理-邮件中设置SMTP服务器。
点击第六个框,选择嵌套步骤-邮件。修改Jenkinsfile的符号body: "XXX"。
至此项目的后端部分就上云部署完成啦!!成功收取邮件的那一刻要流泪了!!
到工作负载里如果发现一些微服务一直在更新,可能要扩展以下服务器内存和CPU,或者在master节点上curl 容器组IP:8080 激活一下。