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 any
  environment {        #配置环境变量参数
    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 {         #配置手动执行时选取的Parameter
    gitParameter(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-qd
  name: k8s-qd
  namespace: k8s-qd
spec:
  replicas: 4
  progressDeadlineSeconds: 600
  minReadySeconds: 10
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  selector:
    matchLabels:
      app: k8s-qd
  template:
    metadata:
      labels:
        app: k8s-qd
    spec:
      containers:
      - name: k8s-qd
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
        readinessProbe:
          httpGet:
            path: /
            port: 80
            scheme: HTTP
          initialDelaySeconds: 30
          periodSeconds: 10
          timeoutSeconds: 2
          successThreshold: 1
          failureThreshold: 2
        livenessProbe:
          tcpSocket:
            port: 80
          initialDelaySeconds: 30
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 2
          failureThreshold: 2
        volumeMounts:       #配置挂载configmap
        - name: nginx-configmap
          mountPath: /etc/nginx/nginx.conf
          subPath: nginx.conf
      volumes:       #引用configmap挂载
      - name: nginx-configmap
        configMap:
          name: qd-nginx     #填入刚刚配置的configmap名称
          items:
          - key: nginx.conf
            path: nginx.conf
      imagePullSecrets:      #使用配置的secret
      - name: qd-harbor-secret
      restartPolicy: Always

---
apiVersion: v1
kind: Service
metadata:
  name: k8s-qd
  namespace: k8s-qd
spec:
  selector:
    app: k8s-qd
  type: NodePort
  clusterIP:
  ports:
  - port: 80
    targetPort: 80
    nodePort: 30001
    protocol: 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需要安装插件

 

 

至此配置完成 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/55923.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

CDH基于Kerberos开启身份验证实践总结

CDH基于Kerberos开启身份验证实践总结 前言简介Kerberos是什么Kerberos解决什么问题 Kerberos基本概念Kerberos认证流程Kerberos基本配置principalkeytabkrb5.confkdc.confkadm5.aclkerberos数据库 访问示例数据库访问信息 其他kerberos常用命令[Git Bash支持make命令](https:/…

【计算机网络】11、网络连通性:ping、traceroute、nslookup

文章目录 一、ping1.1 禁 ping 二、traceroute三、nslookup3.1 非交互模式3.2 交互模式 注意,测试网络连通性时,有的机器无法 ping 通,但可能 telnet 能通。不要因为无法 ping 通就放弃尝试。 一、ping 1.1 禁 ping 禁 ping 是通过忽略 IC…

SpringBoot 统⼀功能处理

目录 前言 1.⽤户登录权限效验 1.1、最初⽤户登录效验 1.2、Spring AOP ⽤户统⼀登录验证的问题 1.3、Spring 拦截器 了解 创建一个 Spring 拦截器 的流程 1、 创建自定义拦截器,实现 HandlerInterceptor 接⼝的preHandle(执⾏具体⽅法之前的预处理…

day17 | 654.最大的二叉树 617.合并二叉树 700.二叉搜索树中的搜索 98.验证二叉搜索树

文章目录 一、最大的二叉树二、合并二叉树三、二叉搜索树中的搜索四、验证二叉搜索树 一、最大的二叉树 654.最大的二叉树 构建二叉树的题目,都用前序遍历。 因为我们一定要先构建根节点,才能继续向后构建。 递归函数的参数和返回值: Tree…

【MyBatis】MyBatis把空字符串转换成0的问题处理方案(96)

先看问题: Postman入参: MyBatis采用map循环插入: // Mapper接口层void addPar(Param(value "question") Map<String, Object> paramMap);<!-- 新增&#xff1a;参数 --><insert id"addPar" parameterType"map">INSERT IGNO…

小研究 - JVM 垃圾回收方式性能研究(一)

本文从几种JVM垃圾回收方式及原理出发&#xff0c;研究了在 SPEC jbb2015基准测试中不同垃圾回收方式对于JVM 性能的影响&#xff0c;并通过最终测试数据对比&#xff0c;给出了不同应用场景下如何选择垃圾回收策略的方法。 目录 1 引言 2 垃圾回收算法 2.1 标记清除法 2.2…

构建语言模型:BERT 分步实施指南

学习目标 了解 BERT 的架构和组件。了解 BERT 输入所需的预处理步骤以及如何处理不同的输入序列长度。获得使用 TensorFlow 或 PyTorch 等流行机器学习框架实施 BERT 的实践知识。了解如何针对特定下游任务(例如文本分类或命名实体识别)微调 BERT。为什么我们需要 BERT? 正…

使用docker部署Wordpress

文章目录 1.创建网络2.创建volume存储3.拉取镜像4.创建mysql容器mysql修改密码 5.创建wordpress容器6.访问localhost:80就可以直接使用啦 1.创建网络 docker network create --subnet172.18.0.0/24 pro-net2.创建volume存储 # mysql 存储 docker volume create volume_mysql…

怎么才能远程控制笔记本电脑?

为什么选择AnyViewer远程控制软件&#xff1f; 为什么AnyViewer是远程控制笔记本电脑软件的首选&#xff1f;以下是选择AnyViewer成为笔记本电脑远程控制软件的主要因素。 跨平台能力 AnyViewer作为一款跨平台远程控制软件&#xff0c;不仅可以用于从一台Windows电…

如何制作VR全景地图,VR全景地图可以用在哪些领域?

引言&#xff1a; 随着科技的迅速进步&#xff0c;虚拟现实&#xff08;VR&#xff09;技术正逐渐渗透到各个领域。VR全景地图作为其中的重要应用之一&#xff0c;为人们提供了身临其境的全新体验。 一.什么是VR全景地图&#xff1f; VR全景地图是一种利用虚拟现实技术&…

PHP8的数据类型-PHP8知识详解

在PHP8中&#xff0c;变量不需要事先声明&#xff0c;赋值即声明。 不同的数据类型其实就是所储存数据的不同种类。在PHP8.0、8.1中都有所增加。以下是PHP8的15种数据类型&#xff1a; 1、字符串&#xff08;String&#xff09;&#xff1a;用于存储文本数据&#xff0c;可以使…

【LeetCode每日一题】——1572.矩阵对角线元素的和

文章目录 一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目示例】六【题目提示】七【解题思路】八【时间频度】九【代码实现】十【提交结果】 一【题目类别】 矩阵 二【题目难度】 简单 三【题目编号】 1572.矩阵对角线元素的和 四【题目描述】 给你一…

HTML5网页设计小案例:网页导航栏的设计

什么是导航栏&#xff0c;按我的理解就是位于网页顶部或者侧边一组链接或者按钮&#xff0c;用来指导大家找到网页的不同板块&#xff0c;大家可以一目了然的找到自己想看的板块内容。今天我们设计一个位于网页顶部的的导航栏。按我的生活经验来说&#xff0c;网页的顶部导航栏…

Django学习记录:使用ORM操作MySQL数据库并完成数据的增删改查

Django学习记录&#xff1a;使用ORM操作MySQL数据库并完成数据的增删改查 数据库操作 MySQL数据库pymysql Django开发操作数据库更简单&#xff0c;内部提供了ORM框架。 安装第三方模块 pip install mysqlclientORM可以做的事&#xff1a; 1、创建、修改、删除数据库中的…

网络安全进阶学习第八课——信息收集

文章目录 一、什么是信息收集&#xff1f;二、信息收集的原则三、信息收集的分类1.主动信息收集2.被动信息收集 四、资产探测1、Whois查询#常用网站&#xff1a; 2、备案信息查询#常用网站&#xff1a; 3、DNS查询#常用网站&#xff1a; 4、子域名收集#常用网站&#xff1a;#常…

Linux编辑器 - vim使用

1.vim的基本概念 Vim是一个广泛使用的文本编辑器&#xff0c;它是在Unix和Linux系统中常用的命令行文本编辑器之一。 vim的主要三种模式 ( 其实有好多模式&#xff0c;目前掌握这 3 种即可 ), 分别是 命令模式 &#xff08; command mode &#xff09;、 插入模式 &#xff0…

html学习5(表单)

1、表单是一个包含表单元素的区域&#xff0c;用于收集用户的输入信息。 2、表单元素是允许用户在表单中输入内容&#xff0c;比如&#xff1a;文本域&#xff08;textarea&#xff09;、下拉列表&#xff08;select&#xff09;、单选框&#xff08;radio-buttons&#xff09…

MySQL篇

文章目录 一、MySQL-优化1、在MySQL中&#xff0c;如何定位慢查询?2、SQL语句执行很慢, 如何分析呢&#xff1f;3、了解过索引吗&#xff1f;&#xff08;什么是索引&#xff09;4、索引的底层数据结构了解过嘛 ?5、什么是聚簇索引什么是非聚簇索引 ?6、知道什么是回表查询嘛…

go初识iris框架(三) - 路由功能处理方式

继了解get,post后 package mainimport "github.com/kataras/iris/v12"func main(){app : iris.New()//app.Handle(请求方式,url,请求方法)app.Handle("GET","/userinfo",func(ctx iris.Context){path : ctx.Path()app.Logger().Info(path) //获…

CEC2022:CEC2022测试函数及多种智能优化算法求解CEC2022对比

目录 一、CEC2022测试函数 二、多种智能优化算法求解CEC2022 2.1 本文参与求解CEC2022的智能优化算法 2.2 部分测试函数运行结果与收敛曲线 三、带标记收敛曲线代码(获得代码后可自行更改&#xff09; 一、CEC2022测试函数 CEC2022测试集共有12个单目标测试函数&#x…