cloud-security-wiki/docs/ci-cd/integration/README.md

300 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 集成
快速开发系统采用前后端分离试开发后端为Spring Cloud 体系架构前端现有React后期会继续更新Vue3.0版本前端页面
## gitea + drone 集成
在安装drone的时候可知drone需要获取到gitea的oauth2的授权这样drone就可以通过携带秘钥信息去请求到gitea当前用户下的所有仓库了
当gitea中的仓库有request的时候gitea会发送一个Web沟子请求到drone
![webhook.png](./webhook.png)
请求内容中就会包括到当前提交的相关信息drone就可以拿到这些信息获取到gitea仓库中的最新代码
## drone + k8s(rancher)
drone触发k8s是非常简单的需要准备一个带有kubectl命令行工具的docker镜像当drone的steps运行到了这一步了之后只需要使用命令行工具运行:
```shell
kubectl apply -f deployment.yml -n dev --kubeconfig=/app/config/kubectl_conf.yml
```
其中 kubectl_conf.yml 则是k8s的连接配置文件deployment.yml文件则是需要构建内容的配置文件
当命令成功运行后即可在k8s中看到新构建的内容但是现在看来drone只是触发了k8s的构建但是k8s构建所需要的docker镜像现在还未知在docker中有一种叫做docker镜像仓库的存在我们制作好的docker镜像就可以推送到镜像仓库中并将仓库中对应的docker pull路径放到deployment.yml文件中可以由k8s pull下来。
## Harbor
Harbor是一个docker的镜像仓库他可以独立部署在drone和k8s中当做粘合剂当drone中构建好了对应docker镜像后将docker镜像推送到harbor然后将pull 的路径又放到k8s的deployment.yml文件中这样全链路就打通了。
为了方便区分每一次drone提交的docker镜像都是不同的并且在k8s的机制中如果你的pull 地址完全相同k8s认为你没有对镜像进行更新所以需要一个随机的变量那么在gitea中存在一个值叫做commit id这个值是每一次提交的唯一标识符所以也可以作为区分镜像版本的变量。
## 前端
在前端项目中,有这
```
.drone.yml -- drone ci/cd管道配置命令
deployment.yml -- k8s部署文件
default.conf -- Nginx的映射配置文件
Dockerfile -- 将前端的打包内容构建docker镜像的文件
docker.sh -- 进行docker打包并且按照约定格式推送到Harbor仓库
.dockerignore -- docker的ignore文件
```
### .drone.yml文件内容详情
```yaml
kind: pipeline # drone配置文件类型 pipeline管道
type: docker # 使用对应steps对应的类型drone是基于docker容器进行每一个步骤的
name: security-react # 本次构建任务的名称
steps:
- name: build-package-react # 当前steps的名称
image: node:16.18.0 # 需要使用到的镜像与react项目中packjson中配置的node版本一致
volumes: # 将容器内容部的地址映射到宿主机上
- name: cache # node构建是的缓存防止多次下载提高build速度
path: /drone/src/node_modules
- name: build # 内容挂在将打包的好产物放到当前目录下方便后续steps的时候
path: /app/build
commands: # 容器中需要执行的命令
- export CI=false
- rm -rf /app/build/react/* # 初始化需要使用的目录
- cp deployment.yml /app/build/react/ # 将k8s构建文件cp到产物挂在目录
- cp Dockerfile /app/build/react/ #
- cp .dockerignore /app/build/react/
- cp default.conf /app/build/react/
- cp docker.sh /app/build/react/
- cp nginx.conf /app/build/react/
- mkdir -p ./node_modules # 创建node依赖目录
- export NODE_MODULES_PATH=`pwd`/node_modules # 构建与缓存目录之间的关联
# - npm config set registry https://registry.npm.taobao.org # 可以开启淘宝npm的镜像加速
# - set NODE_OPTIONS=--openssl-legacy-provider
- npm install # 下载依赖虽然已经进行了依赖的缓存但是一旦有新的依赖加入缓存中没有则无法构建所以还需要install一下
- npm run build # 开始构建产物
- mkdir -p /app/build/react # 创建存放产物的映射目录
- cp -r build /app/build/react # 将打包好之后的内容放入的对应的目录中
- name: build-docker # 制作docker镜像
image: docker # 使用官方docker镜像
volumes: # 将容器内目录挂载到宿主机
- name: build
path: /app/build
- name: docker # 挂载宿主机的docker
path: /var/run/docker.sock
- name: config
path: /config
environment: # 获取到密文的docker用户名和密码
DOCKER_USERNAME:
from_secret: docker_username
DOCKER_PASSWORD:
from_secret: docker_password
REGISTRY:
from_secret: registry
REGISTRY_NAMESPACE:
from_secret: registry_namespace
commands: # 定义在Docker容器中执行的shell命令
- cd /app/build/react/
- cat Dockerfile
# 将一下文件中的密文信息替换成对应的内容
- sed -i 's/$REGISTRY/'"$REGISTRY"'/' deployment.yml
- sed -i 's/$REGISTRY_NAMESPACE/'"$REGISTRY_NAMESPACE"'/' deployment.yml
- sed -i 's/$DRONE_REPO_NAME/'"$DRONE_REPO_NAME"'/' deployment.yml
- sed -i 's/$DRONE_COMMIT/'"$DRONE_COMMIT"'/' deployment.yml
# docker登录不能在脚本中登录并且不能使用docker login -u -p
- echo $DOCKER_PASSWORD | docker login $REGISTRY --username $DOCKER_USERNAME --password-stdin
- chmod +x docker.sh
- sh docker.sh # 运行docker打包脚本
# 执行完脚本删除本次制作的docker镜像避免多次后当前runner空间不足
- docker rmi -f $(docker images | grep $DRONE_REPO_NAME | awk '{print $3}')
- name: drone-rancher # rancher运行
image: registry.cn-hangzhou.aliyuncs.com/claywang/kubectl #阿里云的kubectl镜像里面包含kubectl命令行工具
volumes: # 将容器内目录挂载到宿主机
- name: build
path: /app/build # 将应用打包好的Jar和执行脚本挂载出来
- name: config
path: /app/config # 将kubectl 配置文件挂载出来
commands: # 定义在Docker容器中执行的shell命令
- cd /app/build/react/
# 将deployment中定义的变量替换为drone中的内置变量
- cat deployment.yml
# 通过kubectl指令运行deployment.yml并指定授权文件kubectl_conf.yml
- kubectl apply -f deployment.yml -n dev --kubeconfig=/app/config/kubectl_conf.yml
volumes:
- name: build
host:
path: /home/build
- name: cache
host:
path: /var/lib/npm/cache
- name: config # k8s对接的配置文件
host:
path: /.kube/config
- name: maven-cache # maven的缓存文件
host:
path: /home/data/maven/cache
- name: docker # 宿主机中的docker
host:
path: /var/run/docker.sock
```
## 后端
后端采用的为maven聚合工程情况要比前端负责一些下面是后端聚合工程的模块划分:
```lua
security-cloud
├── auth -- 授权服务模块
├── gateway -- 网关服务模块
└── common -- 系统公共模块
├── common-core -- 公共工具类核心包
├── common-mybatis -- mybatis 扩展封装
├── common-security -- 安全工具类
├── common-swagger -- 接口文档
├── common-feign -- feign 扩展封装
└── common-log -- 系统日志记录
└── upms -- 通用用户权限管理模块
└── upms-api -- 通用用户权限管理系统公共api模块
└── upms-biz -- 通用用户权限管理系统业务处理模块[4000]
└── visual -- 图形化管理模块
└── monitor -- 服务监控
└── codegen -- 图形化代码生成
```
现阶段需要进行ci/cd构建的模块有 auth(授权服务模块) umps-biz(通用用户权限管理系统业务处理模块) gateway(网关服务模块);在这样的前提下,后端就不能同前端一样,一个.drone.yml文件只是服务于单独的一个镜像构建打包了在后端的情况下则需要通过其他方式来区分每一个模块并对每一个模块进行从打包构建到发布的全部流程;所以ci/cd配置难度将加大。
在整个ci/cd活动中唯一能够区分他们并且能够伴随到整个ci/cd流程的只有分支名称所以通过分支名称作为他们的发布名称比如auth(授权服务模块)的发布名称就叫做auth同时项目的jar包名称以及后续的docker镜像名称还有k8s的发布名称都需要统一
在drone中用于储存分支名称的变量为$DRONE_COMMIT_BRANCH 需要了解其他drone变量则可以前往 [Drone内置变量](https://blog.odliken.cn/2022/08/06/drone%e5%86%85%e7%bd%ae%e5%8f%98%e9%87%8f/)
在编写ci/cd的过程中则使用该变量贯穿整个ci/cd的流程配合commit id实现区分不同的版本。
并且在获取分支的时候直接cd $DRONE_COMMIT_BRANCH即可进入到对应模块下然后找到target下$DRONE_COMMIT_BRANCH.jar就可以将这个jar包放到构建的缓存路径下进行下一步的操作了。
## 模块下的模块构建方式
上方的结构图中出现了umps-biz模块这个模块是在umps下方他的分支名应该是什么呢
当前模块的分支名当然是umps-biz但是cd $DRONE_COMMIT_BRANCH的时候真正的运行命令则是 cd umps-biz在项目路径中没有当前的路径所以这是我们需要使用到drone的when 关键词区分分支名称分支为umps-biz的时候我们需要将cd $DRONE_COMMIT_BRANCH 改为cd umps/当前模块的分支名当然是umps-biz但是cd $DRONE_COMMIT_BRANCH的时候真正的运行命令则是 cd umps-biz在项目路径中没有当前的路径所以这是我们需要使用到drone的when 关键词区分分支名称分支为umps-biz的时候我们需要将cd $DRONE_COMMIT_BRANCH 改为$DRONE_COMMIT_BRANCH这样就可以继续完成下面的steps了
## .drone.yml文件详细
```yaml
kind: pipeline
type: docker
name: security-cloud
steps:
- name: build-jar # 流水线名称
image: maven:3.8.5-openjdk-8 # 定义创建容器的Docker镜像maven:3.8.5-openjdk-8用于对java进行打包使用
volumes: # 将容器内目录挂载到宿主机仓库需要开启Trusted设置
- name: maven-cache
path: /root/.m2 # 将maven下载依赖的目录挂载出来防止重复下载
- name: maven-build
path: /app/build # 将应用打包好的Jar和执行脚本挂载出来
commands: # 定义在Docker容器中执行的shell命令
- rm -rf /app/build/*
- mvn clean package -DskipTests=true # 应用打包命
- cp start.sh /app/build/ # java包的启动脚本
- cp Dockerfile /app/build/ # docker镜像打包时的文件
- cp deployment.yml /app/build/ # k8s部署文件
- cp .dockerignore /app/build/ # docker镜像打包时过滤文件
- cp docker.sh /app/build/ # docker 镜像打包脚本
- cd $DRONE_COMMIT_BRANCH
- cp target/$DRONE_COMMIT_BRANCH.jar /app/build/$DRONE_COMMIT_BRANCH.jar # 将打包后的内容复制到挂载目录下
when:
branch:
- gateway
- auth
- name: build-jar-umps-biz # 流水线名称
image: maven:3.8.5-openjdk-8 # 定义创建容器的Docker镜像maven:3.8.5-openjdk-8用于对java进行打包使用
volumes: # 将容器内目录挂载到宿主机仓库需要开启Trusted设置
- name: maven-cache
path: /root/.m2 # 将maven下载依赖的目录挂载出来防止重复下载
- name: maven-build
path: /app/build # 将应用打包好的Jar和执行脚本挂载出来
commands: # 定义在Docker容器中执行的shell命令
- rm -rf /app/build/*
- mvn clean package -DskipTests=true # 应用打包命
- cp start.sh /app/build/ # java包的启动脚本
- cp Dockerfile /app/build/ # docker镜像打包时的文件
- cp deployment.yml /app/build/ # k8s部署文件
- cp .dockerignore /app/build/ # docker镜像打包时过滤文件
- cp docker.sh /app/build/ # docker 镜像打包脚本
- cd umps/$DRONE_COMMIT_BRANCH
- cp target/$DRONE_COMMIT_BRANCH.jar /app/build/$DRONE_COMMIT_BRANCH.jar # 将打包后的内容复制到挂载目录下
when:
branch:
- umps-biz
- name: build-docker # 制作docker镜像
image: docker # 使用官方docker镜像
volumes: # 将容器内目录挂载到宿主机
- name: maven-build
path: /app/build # 将应用打包好的Jar和执行脚本挂载出来
- name: docker
path: /var/run/docker.sock # 挂载宿主机的docker
environment: # 获取到密文的docker用户名和密码
DOCKER_USERNAME:
from_secret: docker_username
DOCKER_PASSWORD:
from_secret: docker_password
REGISTRY:
from_secret: registry
REGISTRY_NAMESPACE:
from_secret: registry_namespace
commands: # 定义在Docker容器中执行的shell命令
- cd /app/build
- sed -i 's/$REGISTRY/'"$REGISTRY"'/' deployment.yml
- sed -i 's/$REGISTRY_NAMESPACE/'"$REGISTRY_NAMESPACE"'/' deployment.yml
- sed -i 's/$DRONE_COMMIT_BRANCH/'"$DRONE_COMMIT_BRANCH"'/' start.sh
- sed -i 's/$DRONE_COMMIT_BRANCH/'"$DRONE_COMMIT_BRANCH"'/' Dockerfile
- sed -i 's/$DRONE_COMMIT_BRANCH/'"$DRONE_COMMIT_BRANCH"'/' .dockerignore
- sed -i 's/$DRONE_COMMIT_BRANCH/'"$DRONE_COMMIT_BRANCH"'/' deployment.yml
- sed -i 's/$DRONE_COMMIT/'"$DRONE_COMMIT"'/' deployment.yml
# docker登录不能在脚本中登录并且不能使用docker login -u -p
- cat Dockerfile
- echo $DOCKER_PASSWORD | docker login $REGISTRY --username $DOCKER_USERNAME --password-stdin
- chmod +x docker.sh
- sh docker.sh
# 执行完脚本删除本次制作的docker镜像避免多次后当前runner空间不足
- docker rmi -f $(docker images | grep $DRONE_COMMIT_BRANCH | awk '{print $3}')
- name: drone-rancher # rancher运行
image: registry.cn-hangzhou.aliyuncs.com/claywang/kubectl #阿里云的kubectl镜像里面包含kubectl命令行工具
volumes: # 将容器内目录挂载到宿主机
- name: maven-build
path: /app/build # 将应用打包好的Jar和执行脚本挂载出来
- name: config
path: /app/config # 将kubectl 配置文件挂载出来
commands: # 定义在Docker容器中执行的shell命令
- cd /app/build
# 通过kubectl指令运行deployment.yml并指定授权文件kubectl_conf.yml
# - kubectl apply -f deployment.yml -n $DRONE_COMMIT_BRANCH --kubeconfig=/app/config/kubectl_conf.yml
- kubectl apply -f deployment.yml -n dev --kubeconfig=/app/config/kubectl_conf.yml
volumes: # 定义流水线挂载目录,用于共享数据
- name: maven-build # maven打包后的文件
host:
path: /home/data/maven/build # 从宿主机中挂载的目录
- name: config # k8s对接的配置文件
host:
path: /.kube/config
- name: maven-cache # maven的缓存文件
host:
path: /home/data/maven/cache
- name: docker # 宿主机中的docker
host:
path: /var/run/docker.sock
# 定义触发条件
trigger:
branch:
- gateway
- auth
- umps-biz
event:
- push
```