前言

前端从过去的script引入资源的方式,到今天随着工程化的发展,前端应用的可用性以及效率都得到了大的提升。这些提升的背景便是devOps的兴起,而前端部署的变化主要考虑的两个问题便是:
1 缓存,前端应用中的返回header由谁来控制,目前得益于工程化的发展,可以让所有历史版本的带hash值的文件都保存在线上。
2 基于/api的跨域处理谁来做,在开发环境可以利用webpack-dev-server,生产环境并不可行。

连接远程,部署

必备资料:

1 一台跳板机,连接服务器 2 生产服务器 3 部署脚本

经常会出现的情况下,前端本地没有问题,但在生产服务器有问题。

docker镜像部署

使用dock镜像,这样首先解决了部署脚本跑不起来的问题,因为这时候前端提供的是一个http服务。

运维除了配置 Nginx 之外,还要执行一个命令:docker-compose up -d。

这时候再思考文章最前面两个问题:

  1. 缓存,由于从静态文件转换为服务,缓存开始交由前端控制(但是镜像中的 http-server 不太适合做这件事情)
  2. 跨域,跨域仍由运维在 Nginx 中配置

前端可以做他应该做的事情中的一部分了,这是一件令人开心的事情。
当然,前端对于 Dockerfile 的改进也是一个慢慢演进的过程,那这个时候镜像有什么问题呢?

  1. 构建镜像体积过大
  2. 构建镜像时间过长

使用多阶段构建优化镜像

使用docerk部署前端应用:https://mp.weixin.qq.com/s?__biz=MzA5OTAyNzQ2OA==&mid=2649700687&idx=1&sn=a656b7c7fdacc1b3df97c1d2630e50d9&scene=21#wechat_redirect

自动化:CI/CD 与 GitLab


此时前端成就感爆棚,运维呢?运维还在一遍一遍地上线,重复着一遍又一遍的三个动作用来部署:

  1. 拉代码
  2. docker-compose up -d
  3. 重启 Nginx

运维觉得再也不能这么下去了,于是他引进了 CI:与现有代码仓库 GitLab 配套的 GitLab CI。

  • CI,Continuous Integration,持续集成
  • CD,Continuous Delivery,持续交付

重要的不是 CI/CD 是什么,重要的是现在运维不用跟着业务上线走了,不需要一直盯着前端部署了。这些都是 CI/CD 的事情了,它被用来做自动化部署。上述提到的三件事交给了 CI/CD。
.gitlab-ci.yml 是 GitLab 的 CI 配置文件,它大概长这个样子:

  1. deploy:
  2. stage:deploy
  3. only:
  4. - master
  5. script:
  6. - docker -compose up --build -d
  7. tags:
  8. - shell

CI/CD 不仅仅更解放了业务项目的部署,也在交付之前大大加强了业务代码的质量,它可以用来 lint,test,package 安全检查,甚至多特性多环境部署,我将会在我以后的文章写这部分事情。
我的一个服务器渲染项目 https://github.com/shfshanyue/shici 以前在我的服务器中就是以 docker/docker-compose/gitlab-ci 的方式部署,有兴趣的可以看看它的配置文件:

如果你有个人服务器的话,也建议你做一个自己感兴趣的前端应用和配套的后端接口服务,并且配套 CI/CD 把它部署在自己的自己服务器上。
而你如果希望结合 GitHub 做 CI/CD,那可以试一试 GitHub + GitHub Action。

使用 Kubernetes 部署


随着业务越来越大,镜像越来越多,docker-compose 已经不太能应付,Kubernetes 应时而出。这时服务器也从 1 台变成了多台,多台服务器就会有分布式问题。
一门新技术的出现,在解决以前问题的同时也会引进复杂性。
Kubernetes 部署的好处很明显:健康检查,滚动升级,弹性扩容,快速回滚,资源限制,完善的监控等等。
那现在遇到的新问题是什么?
构建镜像的服务器,提供容器服务的服务器,做持续集成的服务器是一台!
需要一个私有的镜像仓库,这是运维的事情,Harbor 很快就被运维搭建好了,但是对于前端部署来说,复杂性又提高了。
先来看看以前的流程:

  1. 前端配置 Dockerfile 与 docker-compose
  2. 生产环境服务器的 CI runner 拉代码(可以看做以前的运维),docker-compose up -d 启动服务。然后再重启 Nginx,做反向代理,对外提供服务

以前的流程有一个问题:构建镜像的服务器,提供容器服务的服务器,做持续集成的服务器是一台!所以需要一个私有的镜像仓库,一个能够访问 Kubernetes 集群的持续集成服务器。
流程改进之后结合 Kubernetes 的流程如下:

  1. 前端配置 Dockerfile,构建镜像,推到镜像仓库
  2. 运维为前端应用配置 Kubernetes 的资源配置文件,kubectl apply -f 时会重新拉取镜像,部署资源

前端看了看后端十几个 Kubernetes 配置文件之后,摇摇头说算了算了。
这个时候,gitlab-ci.yaml 差不多长这个样子,配置文件的权限由运维一人管理:

deploy:
stage:deploy
only:
- master
script:
- docker -build -t harbor.shanyue.tech/fe/shanyue 
- docker push harbor.shanyue.tech/fe/shanyue
- kubectl apply -f https:////k8s-config.default.svc.cluster.local/shanyue.yaml
tags:
- shell


这时候再思考文章最前面两个问题:

  1. 缓存,缓存由前端控制
  2. 跨域,跨域仍由运维控制,在后端 Kubernetes 资源的配置文件中控制 Ingress

使用helm部署

这时前端与运维已不太往来,除了偶尔新起项目需要运维帮个忙以外。
但好景不长,突然有一天,前端发现自己连个环境变量都没法传!于是经常找运维修改配置文件,运维也不胜其烦。
于是有了 Helm,如果用一句话解释它,那它就是一个带有模板功能的 Kubernetes 资源配置文件。作为前端,你只需要填参数。
假如我们使用 Bitnami/Nginx 作为 helm chart,前端可能写的配置文件长这个样子:

这时候再思考文章最前面两个问题:

  1. 缓存,缓存由前端控制
  2. 跨域,跨域由后端控制,配置在后端 Chart 的配置文件 values.yaml 中

到了这时前端和运维的职责所在呢?
前端需要做的事情有:

  1. 写前端构建的 Dockerfile,这只是一次性的工作,而且有了参考
  2. 使用 Helm 部署时指定参数

那运维要做的事情呢?

  1. 提供一个供所有前端项目使用的 helm chart,甚至不用提供,如果运维比较懒那就就使用 Bitnami/Nginx 吧。也是一次性工作
  2. 提供一个基于 Helm 的工具,禁止业务过多的权限,甚至不用提供,如果运维比较懒那就直接使用 Helm

这时前端可以关注于自己的业务,运维可以关注于自己的云原生,职责划分从未这般清楚。

统一前端部署平台

后来运维觉得前端应用的本质是一堆静态文件,较为单一,容易统一化,来避免各个前端镜像质量的参差不齐。于是运维准备了一个统一的 Node 基础镜像,做了一个前端统一部署平台,而这个平台可以做什么呢?

  1. CI/CD:当你 push 代码到仓库的特定分支会自动部署
  2. http headers:你可以定制资源的 http header,从而可以做缓存优化等
  3. http redirect/rewrite:如果一个 Nginx,这样可以配置 /api,解决跨域问题
  4. hostname:你可以设置域名
  5. CDN:把你的静态资源推到 CDN
  6. https:为你准备证书
  7. Prerender:结合 SPA,做预渲染

前端再也不需要构建镜像,上传 CDN 了,他只需要写一份配置文件就可以了,大致长这个样子:

image.png

此时,前端只需要写一份配置文件,就可以配置缓存,配置 Proxy,做应该属于前端做的一切,而运维也再也不需要操心前端部署的事情了 前端看着自己刚刚写好的配置文件,怅然若失的样子……

不过一般只有大厂会有这么完善的前端部署平台,如果你对它有兴趣,你可以尝试下 Netlify。

大部分前端应用本质上是静态资源,剩下的少部分就是服务端渲染了,服务端渲染的本质上是一个后端服务,它的部署可以视为后端部署。

后端部署的情况更为复杂,比如:

  1. 配置服务,后端需要访问敏感数据,但又不能把敏感数据放在代码仓库。你可以在 Environment variables, Consul 或者 Kubernetes ConfigMap 中维护
  2. 上下链路服务,你需要依赖数据库,上游服务
  3. 访问控制,限制 IP,黑白名单
  4. RateLimit
  5. 等等

参考链接

原文地址:https://mp.weixin.qq.com/s/BLvk-Z2sryLW29uTh5053Q