devops(前端)
1.前言
前端的打包流程和后端的流程是一样的,只是打包的环境和制作的镜像有所不同,前端需要使用nodejs环境打包,镜像也是使用nginx镜像,因为用的是k8s的pod运行镜像,还需要使用configmap挂载nginx的配置,一套流程还是gitlab+jenkins+harbor+k8s的架构
2.基础环境配置
我们这里就引用之前后端的环境配置,在额外部署一些环境即可
参考:devops(后端)_Apex Predator的博客-CSDN博客
jenkins主机配置
安装nodejs环境
参考:nodejs环境部署_Apex Predator的博客-CSDN博客
gitlab配置
创建前端项目仓库上传代码,我这边是创建了一个nodejs的项目仓库


并且上传了前端的代码,需要做实验的可以到以下连接下载项目代码
项目代码:Release v4.9.2 · Meedu/frontend-v3 · GitHub
harbor配置
创建项目镜像仓库

我这里是创建了一个名为nginx的仓库存放前端的镜像,基础镜像依然是存放在之前创建的base_image仓库中
3.配置项目发布
jenkins配置
创建前端pipeline项目

配置构建流程
这里我们就不配置参数化选择,在执行pipeline的时候让它自动生成,不过这样就会导致在第一次执行的时候会出现报错




构建脚本如下
pipeline { #该pipeline和后端发布的pipeline并没有太大区别,只是打包命令和项目的参数改变了agent anyenvironment { #配置环境变量参数registry = "harbor.apex.com"harbor_auth = "a1e2c627-dc62-4599-a035-8e98d74665ab"project = "nginx"app_name = "k8s-qd"namespace = "k8s-qd"k8s_auth = "k8s-kubeconfig"}parameters { #配置手动执行时选取的ParametergitParameter(branch: '', branchFilter: '.*', defaultValue: '', description: 'Branch for build and deploy', name: 'branch', quickFilterEnabled: false, selectedValue: 'NONE', sortMode: 'NONE', tagFilter: '*', type: 'PT_BRANCH')choice(choices: ['deploy','rollback'], description: '''deploy ---部署 rollback ---回滚''', name: 'status')}stages {stage ('checkout code') {parallel {stage ('webhook tigger') {when {expression { params.status == 'deploy' && env.gitlabBranch != null }}steps {checkout([$class: 'GitSCM', branches: [[name: '${env.gitlabBranch}']], extensions: [], userRemoteConfigs: [[credentialsId: 'gitlab_auth', url: 'git@10.1.60.114:gitlab-instance-c484dcfc/nodejs.git']]])sh "git branch"echo "Current branch: ${env.gitlabBranch}"script {commit_id = sh(returnStdout: true, script: "git log -n 1 --pretty=format:'%h'").trim()tag = BUILD_TAG + '-' + commit_id}}}stage ('jenkins scm') {when {expression { params.status == 'deploy' && env.gitlabBranch == null }}steps {checkout([$class: 'GitSCM', branches: [[name: '${branch}']], extensions: [], userRemoteConfigs: [[credentialsId: 'gitlab_auth', url: 'git@10.1.60.114:gitlab-instance-c484dcfc/nodejs.git']]])sh "git branch"echo "Current branch: ${branch}"script {commit_id = sh(returnStdout: true, script: "git log -n 1 --pretty=format:'%h'").trim()tag = BUILD_TAG + '-' + commit_id}}}}}stage ('build dist') {when {expression { params.status == 'deploy' }}steps { #使用nodejs的打包命令编译前端代码sh """npm install --registry=https://registry.npm.taobao.org #拉取依赖,并指定源npm run build #编译构建ls dist #编译后的前端静态文件都在dist目录下"""}}stage ('docker image build and push') {when {expression { params.status == 'deploy' }}steps {withCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: 'password', usernameVariable: 'username')]) {sh """docker build -t ${registry}/${project}/${app_name}:${tag} .docker push ${registry}/${project}/${app_name}:${tag}"""}}}stage ('k8s update image version') {parallel {stage ('to master') {when {expression { params.status == 'deploy' && (env.gitlabBranch == 'master' || params.branch == 'master') }}steps {withCredentials([file(credentialsId: "${k8s_auth}", variable: 'KUBECONFIG')]) {sh "kubectl --kubeconfig ${KUBECONFIG} set image deployment ${app_name} ${app_name}=${registry}/${project}/${app_name}:${tag} -n ${namespace} --record"}}} stage ('to qd_apex') {when {expression { params.status == 'deploy' && (env.gitlabBranch == 'qd_apex' || params.branch == 'qd_apex')}}steps {withCredentials([file(credentialsId: "${k8s_auth}", variable: 'KUBECONFIG')]) {sh "kubectl --kubeconfig ${KUBECONFIG} set image deployment ${app_name} ${app_name}=${registry}/${project}/${app_name}:${tag} -n ${namespace} --record"}}}}}stage ('rollback version') {parallel {stage ('to master') {when {expression { params.status == 'rollback' && params.branch == 'master' }}steps {withCredentials([file(credentialsId: "${k8s_auth}", variable: 'KUBECONFIG')]) {sh "kubectl --kubeconfig ${KUBECONFIG} rollout undo deployment ${app_name} -n ${namespace}" }}}stage ('to qd_apex') {when {expression { params.status == 'rollback' && params.branch == 'qd_apex' }}steps {withCredentials([file(credentialsId: "${k8s_auth}", variable: 'KUBECONFIG')]) {sh "kubectl --kubeconfig ${KUBECONFIG} rollout undo deployment ${app_name} -n ${namespace}" }}}} }}
}
制作基础镜像
vi dockerfile
FROM alpine:latest #使用alpine系统作为基础镜像
ENV TZ="Asia/Shanghai" #配置变量
RUN sed -i 's/dl-cdn.alpinelinux.org/repo.huaweicloud.com/g' /etc/apk/repositories \
&& apk add --upgrade --no-cache nginx tzdata ttf-dejavu fontconfig \ #安装nginx和一些软件
&& cp /usr/share/zoneinfo/${TZ} /etc/localtime \
&& echo ${TZ} > /etc/timezone
使用dockefile生成镜像
docker build -t harbor.apex.com/base_image/nginx:latest .
推送镜像到harbor仓库
docker push harbor.apex.com/base_image/nginx:latest
gitlab配置
在创建的前端代码仓库中配置webhook
参考:gitlab配置webhook_Apex Predator的博客-CSDN博客
在项目中新建dockerfile文件用于制作每次前端发版的新版本镜像


dockerfile内容如下
FROM harbor.apex.com/base_image/nginx:latest #从harbor仓库获取nginx基础镜像
RUN mkdir -p /opt/web #新建静态文件目录
WORKDIR /opt/web #设置该目录为工作目录,即相当于cd进入该目录下
COPY ./dist/ ./ #讲编译构建好的静态文件拷贝到该工作目录下
EXPOSE 80 #暴露端口为80
ENTRYPOINT /usr/sbin/nginx -g "daemon off;"
#启动nginx服务,nginx默认是后台启动的,但是容器是必须要在前台运行服务,不然就视为没有服务在容器中运行,就会导致容器自动关闭,所以使用-g参数使nginx服务在前台运行
k8s集群配置
在master节点上执行
新建命名空间
kubectl create namespace k8s-qd
拷贝nginx配置文件过来,也可以在我这个配置中修改,用于创建configmap服务
vi nginx.conf
# For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;events {worker_connections 1024;
}http {log_format main '$remote_addr - $remote_user [$time_local] "$request" ''$status $body_bytes_sent "$http_referer" ''"$http_user_agent" "$http_x_forwarded_for"';log_format log_json '{ "time_local": "$time_local", ''"remote_addr": "$remote_addr", ''"referer": "$http_referer", ''"request": "$request", ''"status": $status, ''"bytes": $body_bytes_sent, ''"agent": "$http_user_agent", ''"x_forwarded": "$http_x_forwarded_for", ''"up_addr": "$upstream_addr", ''"up_host": "$upstream_http_host", ''"up_resp_time": "$upstream_response_time", ''"request_time": "$request_time" }';access_log /var/log/nginx/access.log log_json;sendfile on;tcp_nopush on;tcp_nodelay on;keepalive_timeout 65;types_hash_max_size 4096;include /etc/nginx/mime.types;default_type application/octet-stream;# Load modular configuration files from the /etc/nginx/conf.d directory.# See http://nginx.org/en/docs/ngx_core_module.html#include# for more information.include /etc/nginx/conf.d/*.conf;server {listen 80;listen [::]:80;server_name _;root /opt/web/; #配置为存放静态文件的目录# Load configuration files for the default server block.include /etc/nginx/default.d/*.conf;error_page 404 /404.html;location = /404.html {}error_page 500 502 503 504 /50x.html;location = /50x.html {}location / { #配置访问规则,访问到html页面,因为html中应用的文件路径都是写死的,所以只需要配置了root指定静态目录即可root /opt/web/;index index.html;}}# Settings for a TLS enabled server.
#
# server {
# listen 443 ssl http2;
# listen [::]:443 ssl http2;
# server_name _;
# root /usr/share/nginx/html;
#
# ssl_certificate "/etc/pki/nginx/server.crt";
# ssl_certificate_key "/etc/pki/nginx/private/server.key";
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 10m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
#
# # Load configuration files for the default server block.
# include /etc/nginx/default.d/*.conf;
#
# error_page 404 /404.html;
# location = /40x.html {
# }
#
# error_page 500 502 503 504 /50x.html;
# location = /50x.html {
# }
# }}
根据以上的nginx配置创建configmap
kubectl create configmap qd-nginx --from-file=/root/nginx.conf -n k8s-qd
kubectl describe configmap qd-nginx -n k8s-qd

可以看到configmap是挂载了nginx配置的
创建secret,用于拉取harbor仓库镜像验证
kubectl create secret docker-registry qd-harbor-secret --namespace=k8s-qd --docker-server=harbor.apex.com --docker-username=admin --docker-password=Harbor12345
新建前端服务的yaml文件
vi k8s-qd.yaml
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: k8s-qdname: k8s-qdnamespace: k8s-qd
spec:replicas: 4progressDeadlineSeconds: 600minReadySeconds: 10strategy:rollingUpdate:maxSurge: 1maxUnavailable: 0type: RollingUpdateselector:matchLabels:app: k8s-qdtemplate:metadata:labels:app: k8s-qdspec:containers:- name: k8s-qdimage: nginximagePullPolicy: IfNotPresentports:- containerPort: 80readinessProbe:httpGet:path: /port: 80scheme: HTTPinitialDelaySeconds: 30periodSeconds: 10timeoutSeconds: 2successThreshold: 1failureThreshold: 2livenessProbe:tcpSocket:port: 80initialDelaySeconds: 30periodSeconds: 10successThreshold: 1timeoutSeconds: 2failureThreshold: 2volumeMounts: #配置挂载configmap- name: nginx-configmapmountPath: /etc/nginx/nginx.confsubPath: nginx.confvolumes: #引用configmap挂载- name: nginx-configmapconfigMap:name: qd-nginx #填入刚刚配置的configmap名称items:- key: nginx.confpath: nginx.confimagePullSecrets: #使用配置的secret- name: qd-harbor-secretrestartPolicy: Always---
apiVersion: v1
kind: Service
metadata:name: k8s-qdnamespace: k8s-qd
spec:selector:app: k8s-qdtype: NodePortclusterIP:ports:- port: 80targetPort: 80nodePort: 30001protocol: TCP
启动该yaml服务
kubectl apply -f k8s-qd.yaml
4.发布展示
手动构建

可以看到手动构建的时候,git parameter选框会自动去拉取gitlab项目中的所有分支,默认是没有选择的,需要手动选择,status是默认选择deploy为发布

也可以看到第一次构建是失败的,这是因为没有手动配置parameter的原因,在第一次执行时会根据pipeline脚本中的配置自动生成parameter

再次进入配置也可以看到,配置构建流程的时候是没有配置这些参数的,这些都配置在pipeline脚本中,第一次构建的时候会自动生成,但是相应的,第一次构建也会执行失败
自动化构建
我在gitlab配置了过滤只有推分支合并master的时候才触发构建,现在来合并一下master触发构建

点击批准合并后查看jenkins是否触发构建


可以看到通过自动触发的构建也是成功完成了发布的
也可以通过blue ocean功能更直观的看到构建流程,blue ocean需要安装插件



至此配置完成
相关文章:
devops(前端)
1.前言 前端的打包流程和后端的流程是一样的,只是打包的环境和制作的镜像有所不同,前端需要使用nodejs环境打包,镜像也是使用nginx镜像,因为用的是k8s的pod运行镜像,还需要使用configmap挂载nginx的配置,一…...
SpringBoot中MongoDB的使用
SpringBoot中MongoDB的使用 MongoDB 是最早热门非关系数据库的之一,使用也比较普遍,一般会用做离线数据分析来使用,放到内网的居 多。由于很多公司使用了云服务,服务器默认都开放了外网地址,导致前一阵子大批 MongoD…...
Spring学习之GOF的工厂模式
文章目录 工厂模式的三种形态简单工厂模式工厂方法模式抽象工厂模式(了解) 设计模式:一种可以杯冲覅利用的解决方案GoF(Gang of Four),中文名——四人组《Design Patterns: Elements of Reusable Object-Or…...
整数转字符串
描述 用递归法将一个整数 n 转换成字符串。例如,输人 483,应输出字符串"483”。 n的位数不确定,可以是任意位数的整数。 输入 输入一个整数 输出 输出一个字符串 输入样例 1 483 输出样例 1 483 代码一(如下&…...
【ARM Coresight 系列文章 2.4 - Coresight 寄存器:DEVARCH,DEVID, DEVTYPE】
文章目录 1.1 DEVARCH(device architecture register)1.2 DEVID(Device configuration Register)1.3 DEVTYPE(Device Type Identifier Register) 1.1 DEVARCH(device architecture register) DEVARCH 寄存器标识了coresight 组件的架构信息。 bits[31:21] 定义了组件架构&…...
Could not locate supplied template: react+ts搭建
1. reactts创建 我们在是用下create-react-app之前要下载一下 npm install create-react-app -g使用一下命令创建ts的react框架 create-react-app my-app --scripts-versionreact-scripts-ts 2. 遇见问题 我们用以上创建之后会提示一段代码选择“Y”之后发现我们创建的项目…...
fatal error C1128: 节数超过对象文件格式限制: 请使用 /bigobj 进行编译
问题 默认情况下,对象文件最多可存放 65,536 (2^16) 个可寻址的节。 /bigobj将该地址容量增加至 4,294,967,296 (2^32)。大多数模块将从来不会生成包含数超过 65,536 的 .obj 文件。 但是,计算机生成的代码或大量使用模板库的代码可能需要可存放更多节的…...
xml文件转成yolo中的txt文件
xml文件转成yolo中的txt文件 # codingutf-8import os import xml.dom.minidom import cv2 as cvdef xml_to_txt(indir, outdir):os.chdir(indir)xmls os.listdir(.)for i, file in enumerate(xmls):file_save file.split(.)[0] .txtfile_txt os.path.join(outdir, file_sa…...
[Linux]手把手教你制作进度条小程序
[Linux]制作进度条小程序 文章目录 [Linux]制作进度条小程序C语言中的\n和\r字符缓冲区的刷新策略进行进度条代码编写 C语言中的\n和\r字符 C语言中字符分为两种: 可显字符控制字符 其中可显字符就是字符a这类的字符,控制字符就是\n这种控制字符。 对于我们制作…...
centos 重启 nginx 的三种方式
重启nginx的方式都有哪些,ChatGPT给出了比较全面的答案 1.service nginx restart 2.systemctl restart nginx 3.cd /usr/local/nginx/sbin 停止:./nginx -s stop 启动: ./nginx 重新加载配置: ./nginx -s reload 注意:cd /usr/local/nginx/s…...
跨境新手必看,海外推广的7个方式
如何根据自己的产品定位选择合适的平台推广,是作为跨境卖家都需要深入探讨的问题,由于每个社交平台覆盖的群体不同,所以在不同的平台进行广告投放时,要考虑受众群体和目标客户是匹配的。今天给大家分享几种常用的营销方式可以帮助…...
SpringBoot之logback-spring.xml详细配置
《logback官网》 各种指导文件,有空自己去看,比如:我们需要调整的是布局,直接看Layouts。 pom.xml <!-- 环境配置 --><profiles><profile><id>dev</id><properties><spring.profiles.a…...
P2141 [NOIP2014 普及组] 珠心算测验
题目背景 NOIP2014 普及 T1 题目描述 珠心算是一种通过在脑中模拟算盘变化来完成快速运算的一种计算技术。珠心算训练,既能够开发智力,又能够为日常生活带来很多便利,因而在很多学校得到普及。 某学校的珠心算老师采用一种快速考察珠心算…...
[回馈]ASP.NET Core MVC开发实战之商城系统(四)
经过一段时间的准备,新的一期【ASP.NET Core MVC开发实战之商城系统】已经开始,在之前的文章中,讲解了商城系统的整体功能设计,页面布局设计,环境搭建,系统配置,及首页【商品类型,ba…...
Vue.js常见错误处理包含代码
目录 以下是 Vue.js 中常见的错误,以及相应的处理方法和代码示例: 语法错误 错误信息:Error: [vm] "name" is not defined 解决方法:确保组件的 data 中定义了相同的属性。 示例代码: <template> &l…...
Go项目实现日志按时间及文件大小切割并压缩
关于日志的一些问题: 单个文件过大会影响写入效率,所以会做拆分,但是到多大拆分? 最多保留几个日志文件?最多保留多少天,要不要做压缩处理? 一般都使用 lumberjack[1]这个库完成上述这些操作 lumberjack //info文件wr…...
容器化的好处
容器化,是指使用容器技术(Docker/containerd等)运行应用程序(容器),并使用容器编排技术(例如 K8s)来管理这些容器。 我在之前的文章 《使用 Dockerfile 构建生产环境镜像》 提及普通…...
TPlink DDNS 内网穿透?外网访问设置方法
有很多小伙伴都想知道:TPlink路由器怎么设置DDNS内网穿透?今天,小编就给大家分享一下TPlink DDNS 外网访问设置方法,下面是图文教程,帮助新手快速入门DDNS设置。 本文介绍的是云路由器TP-LINK DDNS的设置方法。TP-LIN…...
以CS32F031为例浅说国产32位MCU的内核处理器
芯片内核又称CPU内核,它是CPU中间的核心芯片,是CPU最重要的组成部分。由单晶硅制成,CPU所有的计算、接受/存储命令、处理数据都由核心执行。各种CPU核心都具有固定的逻辑结构,一级缓存、二级缓存、执行单元、指令级单元和总线接口…...
享元模式(Flyweight)
享元模式是一种结构型设计模式,主要通过共享技术有效地减少大量细粒度对象的复用,以减少内存占用和提高性能。由于享元模式要求能够共享的对象必须是细粒度对象,因此它又称为轻量级模式。 Flyweight is a structural pattern, which effecti…...
未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...
【kafka】Golang实现分布式Masscan任务调度系统
要求: 输出两个程序,一个命令行程序(命令行参数用flag)和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽,然后将消息推送到kafka里面。 服务端程序: 从kafka消费者接收…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...
Android15默认授权浮窗权限
我们经常有那种需求,客户需要定制的apk集成在ROM中,并且默认授予其【显示在其他应用的上层】权限,也就是我们常说的浮窗权限,那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...
Spring Boot + MyBatis 集成支付宝支付流程
Spring Boot MyBatis 集成支付宝支付流程 核心流程 商户系统生成订单调用支付宝创建预支付订单用户跳转支付宝完成支付支付宝异步通知支付结果商户处理支付结果更新订单状态支付宝同步跳转回商户页面 代码实现示例(电脑网站支付) 1. 添加依赖 <!…...
【阅读笔记】MemOS: 大语言模型内存增强生成操作系统
核心速览 研究背景 研究问题:这篇文章要解决的问题是当前大型语言模型(LLMs)在处理内存方面的局限性。LLMs虽然在语言感知和生成方面表现出色,但缺乏统一的、结构化的内存架构。现有的方法如检索增强生成(RA…...
uni-app学习笔记二十七--设置底部菜单TabBar的样式
官方文档地址:uni.setTabBarItem(OBJECT) | uni-app官网 uni.setTabBarItem(OBJECT) 动态设置 tabBar 某一项的内容,通常写在项目的App.vue的onLaunch方法中,用于项目启动时立即执行 重要参数: indexnumber是tabBar 的哪一项&…...
vue3 手动封装城市三级联动
要做的功能 示意图是这样的,因为后端给的数据结构 不足以使用ant-design组件 的联动查询组件 所以只能自己分装 组件 当然 这个数据后端给的不一样的情况下 可能组件内对应的 逻辑方式就不一样 毕竟是 三个 数组 省份 城市 区域 我直接粘贴组件代码了 <temp…...
全面解析网络端口:概念、分类与安全应用
在计算机网络的世界里,数据的传输与交互如同一场繁忙的物流运输,而网络端口就是其中不可或缺的 “货运码头”。无论是日常浏览网页、收发邮件,还是运行各类网络服务,都离不开网络端口的参与。本文将深入介绍网络端口的相关知识&am…...
SpringBoot离线应用的5种实现方式
在当今高度依赖网络的环境中,离线应用的价值日益凸显。无论是在网络不稳定的区域运行的现场系统,还是需要在断网环境下使用的企业内部应用,具备离线工作能力已成为许多应用的必备特性。 本文将介绍基于SpringBoot实现离线应用的5种不同方式。…...
