VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > temp > JavaScript教程 >
  • 基于云原生DevOps服务自动化部署前端项目学习总结

本文主要以部署前端Vue项目为例,讲述了如何基于云原生DevOps服务自动化部署前端项目~从开发完成到线上环境,我们只需提交代码即可~

 

 

一、引言

    作为一名开发人员,日常工作中我们除了需要负责代码的开发外,通常还需要负责代码的部署,运维等工作。而在传统的手工部署方法中,在每次版本迭代或需求变更完成后,除了将代码提交到代码仓库外,如果需要更新线上环境,我们还需要重复本地构建打包、连接远程服务器、上传代码到服务器指定目录等步骤。这些步骤虽然简单,但是通常耗时耗力,若同时存在多个环境时,也容易引起部署错误。

    而随着DevOps理念、容器技术IT自动化等理念与技术的兴起,我们可以利用现有的技术和工具,以IT自动化以及持续集成(CI)、持续部署(CD)为基础,搭建一个完整的工作流,用于优化程序开发、测试、系统运维等所有环节。如下面这个图所示,从开发完成到线上环境,我们只需提交代码即可。

    接下来,将以部署前端Vue项目为例,讲述如何通过腾讯云CODING DevOps容器镜像服务TCR容器服务TKE负载均衡CLB等云产品提供的强大云原生DevOps服务来实现vue项目的自动化部署,重点记录了自己的学习过程~

 

二、需要掌握的技术

    在学习基于云原生DevOps服务自动化部署项目之前,我们需要先熟悉以下技术及工具的基本使用方法~

1、Docker

    DevOps是一种理念,而其具体实现通常需要基于容器技术。而Docker作为一个开源容器项目,提供了高效、敏捷和轻量级的容器方案,并支持部署到本地环境和多种主流云平台。下面主要列举了Docker的一些常用操作:

从仓库拉取镜像

[]表示可省略

docker [image] pull nginx:latest

列出本机的所有镜像文件

docker [image] ls

删除镜像

docker [image] rm nginx:latest

上传镜像

docker [image] push nginx:latest

使用Dockerfile构建镜像

-t:指定镜像的标签列表

-f:Dockerfile名称及路径

docker [image] build -t nginx:new -f /dockerfile_path

运行镜像,并生成一个容器

-p:容器端口映射

-i:分配伪终端,并绑定到容器的标准输入上

-t:让容器的标准输入保持打开

-d:让容器在后台以守护态形式运行

docker [container] run -p 80:80 -it -d nginx:latest

列出所有正在运行的容器 docker [container] ps
列出所有容器,包括终止运行的容器 docker [container] ps  -a
启动容器 docker [container] start container_name/container_id
暂停容器 docker [container] stop container_name/container_id
删除容器 docker [container] rm container_name/container_id

 

2、Kubernetes

   Kubernetes(K8S)是负责自动化运维管理多个Docker容器的集群,解决了容器的管理和调度问题,需要理解Node、Pod、Deployment、ServiceIngress等相关概念。

   相关学习网站:https://kubernetes.io/zh/docs/concepts/overview/what-is-kubernetes/

 

3、持续集成/持续部署工具

    现有的持续集成/持续部署(CI/CD)工具通常包括了Jenkins、Travis CI、Circle CI、TeamCity、CodeShip、GitLab CI和Bamboo等,由于CODING持续集成全面兼容Jenkins的持续集成服务,所以这里也使用到了Jenkins,需要掌握Jenkinsfile的使用。

 

4、用到的云产品

    CODING DevOps:https://cloud.tencent.com/product/coding-ci

    容器镜像服务TCR:https://cloud.tencent.com/product/tcr

    容器服务TKE:https://cloud.tencent.com/product/tke

    负载均衡CLB:https://cloud.tencent.com/product/clb

    CODING DevOps能够与TCR和TKE紧密结合,当CODING代码仓库的源代码发生更新时,就能够自动触发镜像构建,并推送到TCR镜像仓库。同时,通过在TCR设置交付流水线,当TCR镜像仓库发生更新时,能够自动触发TKE集群进行部署,从而更新线上环境。

    

 

三、先从一个简单例子讲起

    由于采用基于云原生的DevOps需要使用容器技术实现项目的部署,因此这里以Vue项目为例,介绍了如何采用Docker容器部署前端项目。

1、基于Docker容器部署Vue项目

    前提条件:一台已经安装了Docker环境的服务器(云服务器CVM),以及一个Vue项目,并且通过npm run build生成了dist目录。

    1)编写Dockerfile文件

     Dockerfile文件一般存放在项目根目录,也可以自由指定存放目录。Dockerfile的内容如下:

 
# 前端应用部署在nginx里面,所以需要依赖nginx镜像
FROM nginx
# 可以指定镜像的所有者,非必须
MAINTAINER iceshuang@tencent.com
# 将构建后的资源目录复制到nginx默认的静态资源托管目录中
COPY dist/ /usr/share/nginx/html/
# 非守护态运行,使容器不会自动退出
CMD nginx -g 'daemon off;'

     2)将dist目录和Dockerfile上传到服务器指定目录下

    3)根据Dockerfile文件构建镜像,这里将镜像的标签名称命名为web

    4)构建好镜像后,会根据这个镜像创建并启动容器,这里将容器名称命名为为vue

    5)由于创建容器时绑定了端口号8080,因此可以通过ip:8080访问前端项目

  

 

2、使用CODING DevOps创建自己的构建计划

    接下来,将基于上面的基础,使用CODING DevOps创建一个完整的工作流,实现从开发完成到线上环境,只需提交代码即可。

    前提条件:已经申请了CODING DevOps的团队域名和团队项目,并且已经创建并初始化了一个项目仓库(详细文档)。

   1)创建Docker类制品库

    选择制品管理 -> 制品仓库,创建Docker类制品库。创建成功后,点击使用访问令牌生成配置,记录下对应的登录名和密码(详细文档),如下图所示,创建了一个名为image的镜像仓库。

    点击项目设置(左下角)-> 开发者选项 -> 凭据管理 -> 录入凭据,配置登录名密码生成凭据,创建成功后,会生成一个凭据ID。该凭据用于向制品库拉取和上传镜像。

    2)云服务器创建SSH密钥对

    在云服务器控制器创建SSH密钥对,并且将密钥对绑定到对应的云服务器(详细文档)。 

    点击项目设置(左下角)-> 开发者选项 -> 凭据管理 -> 录入凭据,根据上面生成的密钥信息,配置SSH密钥生成凭据,创建成功后,会生成一个凭据ID。该凭据用于登录云服务器。 

   3)创建Jenkinsfile文件

   Jenkinsfile文件主要用于自定义持续集成流水线过程,可以根据实际情况设置Jenkinsfile的路径。这里主要在Vue项目根目录新建了deploy目录,并将Jenkinsfile和Dockerfile放入deploy中。

 
vue
|- package.json
|- README.md
|- /deploy
  |- Dockerfile
  |- Jenkinsfile
|- /node_modules
|- .src
|- .dockerignore

     Dockfile内容和前面保持一致,Jenkinsfile内容如下,其中,变量DOCKER_REGISTRY_CREDENTIALS_ID、CVM_REGISTRY_CRENDENTIALS_ID、CVM_NAME、CVM_IP和CVM_USER需要在步骤4)中进行设置。

 
pipeline {
  agent any
  stages {
    stage('检出') {
      steps {
        checkout([$class: 'GitSCM',
        branches: [[name: GIT_BUILD_REF]],
        userRemoteConfigs: [[
          url: GIT_REPO_URL,
          credentialsId: CREDENTIALS_ID
        ]]])
      }
    }
    stage('安装依赖') {
      steps {
        sh 'npm install'
      }
    }
    stage('构建') {
      steps {
        sh 'npm run build'
      }
    }
    stage('构建镜像') {
      steps {
        echo '构建镜像...'
        script {
          sh "docker build -t icesices-docker.pkg.coding.net/vue/image/${env.GIT_LOCAL_BRANCH}-${env.CI_BUILD_NUMBER} -f ./deploy/Dockerfile ."
        }
        echo '构建镜像完成'
      }
    }
    stage('推送镜像') {
      steps {
        echo '推送镜像...'
        script {
          // DOCKER_REGISTRY_CREDENTIALS_ID需要在变量与缓存中进行设置
          withCredentials([usernamePassword(credentialsId: env.DOCKER_REGISTRY_CREDENTIALS_ID, usernameVariable: 'REGISTRY_USER', passwordVariable: 'REGISTRY_PASS')]) {
            sh "docker login -u ${env.REGISTRY_USER} -p ${env.REGISTRY_PASS} icesices-docker.pkg.coding.net"
            sh "docker push icesices-docker.pkg.coding.net/vue/image/${env.GIT_LOCAL_BRANCH}-${env.CI_BUILD_NUMBER}"
          }
        }
       echo '推送镜像完成'
      }
    }
    stage('部署') {
      steps {
        echo '部署中...'
        script {
          // CVM_NAME 服务器名称 CVM_IP 服务器ip CVM_USER 账号名称,需要在变量与缓存中进行设置
          def remote = [:]
          remote.name = env.CVM_NAME
          remote.allowAnyHosts = true
          remote.host = env.CVM_IP
          remote.port = 22
          remote.user = env.CVM_USER
          // CVM_REGISTRY_CRENDENTIALS_ID需要在变量与缓存中进行设置,该步骤主要通过SSH登录到云服务器,并且拉取Docker镜像,启动并运行容器
          withCredentials([sshUserPrivateKey(credentialsId: env.CVM_REGISTRY_CRENDENTIALS_ID, keyFileVariable: 'id_rsa')]) {
            remote.identityFile = id_rsa
            // DOCKER_REGISTRY_CREDENTIALS_ID需要在变量与缓存中进行设置
            withCredentials([usernamePassword(credentialsId: env.DOCKER_REGISTRY_CREDENTIALS_ID, usernameVariable: 'REGISTRY_USER', passwordVariable: 'REGISTRY_PASS')]) {
              sshCommand remote: remote, command: "docker login -u ${env.REGISTRY_USER} -p ${env.REGISTRY_PASS} icesices-docker.pkg.coding.net"
              sshCommand remote: remote, command: "docker pull icesices-docker.pkg.coding.net/vue/image/${env.GIT_LOCAL_BRANCH}-${env.CI_BUILD_NUMBER}"
              sshCommand remote: remote, command: "docker stop vue | true"
              sshCommand remote: remote, command: "docker rm vue | true"
              sshCommand remote: remote, command: "docker run --name vue -p 8080:80 -d icesices-docker.pkg.coding.net/vue/image/${env.GIT_LOCAL_BRANCH}-${env.CI_BUILD_NUMBER}"
            }
          }
        }
        echo '部署完成'
      }
    }
  }
}

    4)创建构建计划

    点击持续集成 -> 构建计划 -> 自定义构建过程,选择对应的仓库,并且填入Jenkinsfile的路径。 

    配置节点池,这里可以采用CODING提供的云主机构建(有构建限制,需要提高配额才能有更好的体验),也可以采用自定义构建节点devcloud构建(详细文档),可以根据实际需要进行选择。 

    设置触发规则,当代码发生更新就自动触发构建。 

    设置变量与缓存,这里设置的变量为在Jenkinsfile中定义的变量,其中,DOCKER_REGISTRY_CREDENTIALS_ID为制品库的推送凭据,CVM_REGISTRY_CRENDENTIALS_ID为云服务器的SSH密钥,这里的值对应了步骤2)和步骤3)中生成的凭据的ID,将对应的值复制过来就好。CVM_NAME、CVM_IP和CVM_USER分别表示云服务器的名称、IP和账号名称。 

    5)执行构建计划

    完成上述步骤之后,当我们本地完成开发,只要推送代码到代码仓库,就能够触发构建计划,自动进行代码编译构建、镜像推送和代码部署等工作,当构建成功后,重新访问我们的网站,就能够看到线上环境更新了。同时,在制品库也能够看到每次推送的镜像。

 

 

四、进阶学习

    在实际的项目中,通常我们需要部署的服务器往往不止一台,而一台服务器上通常又会运行多个Docker容器。因此,为了更加高效的管理和调度Docker容器,并且得到更加安全,独享的高性能应用制品托管分发服务,接下来,将会介绍如何基于CODING DevOps、TCR、TKE和CLB等云产品提供的的强大的云原生DevOps服务来部署前端项目。

1、容器镜像服务TCR

    TCR主要用来存储镜像,使用交付流水线实现容器DevOps,从而更新TKE集群中工作负载的镜像(详细文档)。

    1)创建容器镜像实例

    TCR包括了个人版和企业版,企业版能够提供更加安全、独享的高性能应用制品托管分发服务,因此这里使用了企业版,需要购买后才能使用。

    创建实例成功后,点击实例进入配置,并新建访问凭证。记下该访问凭证的账号密码,并在CODING DevOps的凭据管理中进行录入,从而使得CODING DevOps能够向TCR推送镜像,具体见下文CODING DevOps的步骤2)。

    2)创建命名空间和镜像仓库

    由于创建镜像仓库时需要选取命名空间,因此这里需要先创建命名空间,然后再创建镜像仓库,生成的仓库地址就是我们在后续中拉取和推送镜像的地址。

    3)配置网络访问策略

    访问控制包括内网访问(详细文档)和公网访问(详细文档)。

    内网访问通过配置内网访问链路,指定可以访问镜像数据的私有网络VPC,通过内网方式拉取镜像可以提高推送和拉取速度。下文TKE集群在配置TCR插件拉取镜像时,需要先配置好内网访问策略。

    4)配置交付流水线

    前提条件:已经按照下文的部署创建好TKE集群和工作负载,部署了容器应用。

    配置交付流水线包括两种场景,第一种是推送代码后自动触发镜像构建和应用部署,第二种是本地推送镜像后自动触发部署(详细文档)。这里使用到了第二种场景。

    选择容器镜像服务 -> 交付中心 -> 交付流水线,新建流水线,填写流水线的相关信息。选择需要拉取的镜像仓库及所需要更新的TKE集群。

    创建成功后,在容器镜像服务 -> 运维中心 -> 触发器中可以看到自动生成了触发器。

    此外,在容器镜像服务 -> 实例列表 -> 访问凭据中可以看到自动生成了流水线交付专用凭据。

    完成上述步骤后,当有新的镜像推送到镜像仓库时,就会触发触发器,更新TKE集群的工作负载。同时,交付流水线也会被触发执行。

 

2、CODING DevOps

    CODING DevOps主要用来托管代码,通过配置构建计划,实现代码编译构建,镜像构建和推送镜像到TCR(详细文档)。

    前提:已经申请了CODING DevOps的团队域名和团队项目,并且已经创建并初始化了一个项目仓库。

    1)创建Jenkinsfile文件

    同前面的例子一样,仍然在Vue根目录中创建了deploy目录,并将Dockerfile和Jenkinsfile放入deploy中。Dockerfile的内容仍然保持不变,Jenkinsfile的内容如下:

 
pipeline {
  agent any
  stages {
    stage('检出') {
      steps {
        checkout([$class: 'GitSCM',
        branches: [[name: GIT_BUILD_REF]],
        userRemoteConfigs: [[
          url: GIT_REPO_URL,
          credentialsId: CREDENTIALS_ID
        ]]])
      }
    }
    stage('安装依赖') {
      steps {
        sh 'npm install'
      }
    }
    stage('构建') {
      steps {
        sh 'npm run build'
      }
    }
    stage('构建镜像') {
      steps {
        echo '构建镜像...'
        script {
          sh "docker build -t vue-web.tencentcloudcr.com/vue/image:${env.GIT_LOCAL_BRANCH}-${env.CI_BUILD_NUMBER} -f ./deploy/Dockerfile ."
        }
        echo '构建镜像完成'
      }
    }
    stage('推送镜像') {
      steps {
        echo '推送镜像...'
        script {
          // DOCKER_REGISTRY_CREDENTIALS_ID需要在变量与缓存中进行设置
          withCredentials([usernamePassword(credentialsId: env.DOCKER_REGISTRY_CREDENTIALS_ID, usernameVariable: 'REGISTRY_USER', passwordVariable: 'REGISTRY_PASS')]) {
            sh "echo ${REGISTRY_PASS} | docker login -u ${REGISTRY_USER} --password-stdin vue-web.tencentcloudcr.com"
            sh "docker push vue-web.tencentcloudcr.com/vue/image:${env.GIT_LOCAL_BRANCH}-${env.CI_BUILD_NUMBER}"
          }
        }
       echo '推送镜像完成'
      }
    }
  }
}

    2)设置访问凭据

    点击项目设置(左下角)-> 开发者选项 -> 凭据管理 -> 录入凭据,配置账号密码生成凭据,该凭据是推送镜像到TCR的凭据,账号密码需要在TCR中获取,具体见上文容器镜像服务TCR的步骤1)。

   3)创建构建计划

    点击持续集成 -> 构建计划 -> 自定义构建过程,选择代码仓库,填写Jenkinsfile的路径,创建构建计划。

    创建成功后,需要进行基础信息和触发规则的配置。

    此外,还需要进行变量与缓存的配置,其中,DOCKER_REGISTRY_CREDENTIALS_ID的值为步骤2)中生成的凭据ID。

 

 

3、容器服务TKE

    容器服务TKE主要用于创建集群,并拉取TCR中的镜像创建工作负载,部署业务应用,对外提供服务(详细文档)。

    1)创建TKE集群

    根据官网的指引(详细文档)创建TKE集群,根据实际需求选择节点数量,配置安全组等。创建集群成功后,在云服务器控制台可以看到创建了相应的节点服务器(这里创建时选择了两个节点)。

    2)安装TCR插件

    在TKE集群中通过使用TCR插件,能够实现内网免密拉取企业版实例内容器镜像(详细文档)。但是需要TKE集群和TCR部署在同一个地域,并且在容器镜像服务 -> 访问管理 -> 内网访问中需要已经创建好了私有网络VPC,具体见上文步骤。

    在组件管理中,点击新建,选择TCR容器镜像服务插件,并勾选“使用TCR插件为集群配置关联实例内网访问链路的自动解析”。

    创建成功后,会在命名空间tcr-assistant-system下,自动创建名称为tcr-assistant-controller-manager的Deployment和名称为tcr-assistant-webhook-service的Service。

    同时,在容器镜像服务 -> 实例列表 -> 实例 -> 访问凭证中也可以看到生成了TKE集群的专用访问凭据。

    3)创建工作负载

    点击工作负载 -> Deploment -> 新建,创建工作负载(详细文档)。

    设置工作负载的名称和命名空间。

    设置实例内容容器的名称、镜像仓库、镜像版本、镜像拉取策略和实例数量。由于这里创建的TKE集群包含了2个节点,所以创建了2个pod实例,可以根据实际情况进行设置。

    访问设置,由于下文中需要通过负载均衡CLB转发流量到Node,因此这里采用了主机端口访问的方式(详细文档)。在端口映射中,由于这里希望向外提供服务的端口为80,而容器内nginx服务的端口为80,因此需要将对外服务的端口和nginx服务的端口进行映射。

    创建成功后,可以看到pod实例已经成功运行,通过实例所在节点IP,可以看到pod实例运行在哪个节点上。同时,在服务与路由 -> Servide中,也可以看到在对应命名空间下生成了对应的Service。

    创建好工作负载后,如果登录到节点所在的云服务器上,通过kubectl get pod -o wide查看,也可以看到pod正常运行在云服务器中。

 

4、负载均衡CLB

    负载均衡CLB能够提供安全快捷的流量分发服务,访问流量经由CLB可以自动分配到多台云服务器上。当某台云服务器发生故障时,CLB能够将流量调度到正常的节点,从而使得服务不会发生中断(详细文档)。

    1)创建负载均衡实例

    2)配置监听器和规则

    点击新建HTTP/HTTPS监听器,选择需要监听的端口号,创建监听器。

    创建好监听器后,还需要配置转发规则,这里需要输入域名(支持IPV4地址)、URL路径和均衡方式等信息。若选择输入域名,域名需要和该CLB的VIP已经进行了绑定。

    配置好转发规则后,需要进行绑定后端服务绑定,这里选择的云服务器为TKE集群中的节点,端口就是在TKE集群创建工作负载时生成的Service的主机端口。Service的主机端口可以在容器服务 -> 集群 -> 服务与路由 -> Service中查看。

    配置完上述步骤之后,通过域名加端口号,就可以访问到web服务了。此外,如果服务是需要通过https访问的,还需要设置443端口的监听,并将http服务重定向到https服务,具体操作可以查看官方文档。

 

5、遇到的问题

问题一:当本地推送代码到CODING仓库后,交付流水线成功执行,但是集群的pod在更新时一直处于pending状态,重新访问页面不能看到更新。

原因:TKE集群默认采用滚动更新方式更新(只有新的pod运行成功,才会终止原来的pod),这里主要是因为节点的内存不足,所以无法完成pod更新。

解决方法:因为集群节点运行时K8S自身相关组件会占用一部分系统资源,所以在创建集群节点时配置不能太低。

 

问题二:当本地推送代码到CODING仓库后,交付流水线成功执行,但是集群对应的pod没有触发更新(即上图页面中一直只有旧的pod处于Running状态)。

原因:每次向镜像仓库推送镜像时不要使用相同的tag,对于同名的tag,会认为是同一个镜像,所以集群不会进行更新。

解决方法:在Jenkinsfile中构建镜像时可以使用CI_BUILD_NUMBER变量进行版本标记,这样每次构建镜像时镜像的tag都会不同。

 
sh "docker build -t vue-web.tencentcloudcr.com/vue/image:${env.GIT_LOCAL_BRANCH}-${env.CI_BUILD_NUMBER} -f ./deploy/Dockerfile ."

 

问题三:TKE集群创建工作负载后,怎么验证pod已经在节点上正常运行

解决方法: 方法1:可以在云服务器控制台找到服务器的公网ip,通过NodePort访问web服务是否能够正常访问

方法2:找到集群节点对应的云服务器,登录云服务器,通过运行kubectl get pod -o wide查看pod是否正常运行

 

问题四:负载均衡CLB能够提供流量分发服务,当其中一个节点发生故障时,能够将流量转发到正常节点,但是实现过程中,总共包括两个节点,将其中一个集群节点关机,发现web服务会中断几分钟才能访问,并且CLB对两个节点的健康检查状态都是异常(正常应该是服务不会中断,并且一个节点正常,一个节点异常)。

原因:TKE集群创建的工作负载pod实例数量小于节点数量,比如有两个集群节点,但是只创建了一个pod,这个时候pod只会运行在其中一个节点中,因此,当关机的节点刚好就是pod运行的那个节点时,需要花一些时间在另一个节点上重新创建并运行pod,pod启动成功后,CLB才会将流量调度到该节点,因此中间会有几分钟不能方法。

解决方法:TKE集群在创建pod实例时,有多少节点就应该创建至少多少个pod,比如上面创建了2个节点,就创建两个pod,并且设置反亲和性,这样能够保证每个节点至少运行一个pod,当其中一个节点发生故障时,CLB能够快速将流量转发到正常节点,不会中断服务。

 

问题五:开发时通常会有很多个环境,需要创建不同的镜像仓库,怎么修改Jenkinsfile才能自动根据当前分支推送镜像到对应的镜像仓库

解决方法:假设现在有develop,test和master三个不同环境,并且对应三个不同镜像仓库,可以在Jenkinsfile加入下面代码

 
stage('构建镜像') {
      steps {
        echo '构建镜像...'
        script {
          switch(env.GIT_LOCAL_BRANCH) {
            case 'develop':
              sh "docker build -t vue-web.tencentcloudcr.com/vue/image-develop:${env.GIT_LOCAL_BRANCH}-${env.CI_BUILD_NUMBER} -f ./deploy/Dockerfile ."
              break
            case 'test':
              sh "docker build -t vue-web.tencentcloudcr.com/vue/image-test:${env.GIT_LOCAL_BRANCH}-${env.CI_BUILD_NUMBER} -f ./deploy/Dockerfile ."
              break
            case 'master':
              sh "docker build -t vue-web.tencentcloudcr.com/vue/image-master:${env.GIT_LOCAL_BRANCH}-${env.CI_BUILD_NUMBER} -f ./deploy/Dockerfile ."
              break
          }
        }
        echo '构建镜像'
      }
    }
}

 

 

    当完成上面的所有步骤之后,只要我们推送代码到CODING仓库,就能够自动执行代码构建、镜像构建、推送镜像和更新TKE集群工作负载等步骤。当我们重新访问页面时,就可以看到线上环境已经自动更新啦~

 

  • 本文作者: Yellow-ice
  • 本文链接: https://www.cnblogs.com/Yellow-ice/p/14487416.html

 

    

    

  



相关教程