本文是根据 KubeSphere 云原生 Meetup 杭州站讲师祁宁分享内容整理而成。php
SegmentFault 是一家综合性技术社区,因为它的内容跟编程技术紧密相关,所以访问量的波动也和这一群体的做息时间深度绑定。一般状况下 web 页面的请求量峰值在 800 QPS 左右,但咱们还作了先后端分离,因此 API 网关的峰值 QPS 是请求量峰值的好几倍。node
SegmentFault 做为一个技术社区的系统架构变化,里面有些东西仍是颇有意思的。react
紧接着,咱们遇到了很多挑战,促使使咱们不得不往 K8s 架构上迁移。web
首先,虽然咱们是一家小公司,可是业务线却很是复杂,整个公司只有 30 人左右,技术人员只占其中三分之一左右,因此承载这么大的业务量负担仍是很重的。并且创业公司的业务线调整很是频繁,临时性工做也比较多,传统的系统架构在应对这种伸缩性要求比较高的场景是比较吃力的。数据库
其次,复杂的场景引起了复杂的配置管理,不一样的业务要用到不一样的服务,不一样的版本,即便用自动化脚本效率也不高。编程
另外,咱们内部人员不足,因此没有专职运维,如今 OPS 的工做是由后端开发人员轮值的。但后端开发人员还有本身本职工做要作,因此对咱们最理想的场景是能把运维工做所有自动化。segmentfault
最后也是最重要的一点就是咱们要控制成本,这是高情商的说法,低情商就是一个字“穷”(笑)。固然,若是资金充足,以上的问题都不是问题,可是对于创业公司(特别是像咱们这种访问量比较大,可是又不像电商,金融那些挣钱的公司)来讲,咱们必将处于且长期处于这个阶段。所以可否控制好成本,是一个很是重要的问题。后端
2020 年之前,SegmentFault 的网站仍是很是传统的后端渲染页面的方法,因此服务端的架构也很是简单。服务端将浏览器的 http 请求转发到后端的 php 服务,php 服务渲染好页面后再返回给浏览器。这种架构用原有的部署方法还能支撑,也就是在各个实例上部署 php 服务,再加一层负载均衡就基本知足需求了。浏览器
然而随着业务的持续发展,后端渲染的方式已经不适合咱们的项目规模了,所以咱们在 2020 年作了架构调整,准备将先后端分离。先后端分离的技术特色我在这里就不赘述了,这里主要讲它给咱们带来了哪些系统架构上的挑战。一个是入口增多,由于先后端分离不只涉及到客户端渲染(CSR),还涉及到服务端渲染(SSR),因此响应请求的服务就从单一的服务变成了两类服务,一类是基于 node.js 的 react server 服务(用来作服务端渲染),另外一类是 基于 php 写的 API 服务(用来给客户端渲染提供数据)。而服务端渲染自己还要调用 API,而咱们为了优化服务端渲染的链接和请求响应速度,还专门启用了了使用专有通信协议的内部 API 服务。缓存
因此实际上咱们的 WEB SERVER 有三类服务,每种服务的环境各不相同,所需的资源不一样,协议不一样,各自之间可能还有相互链接的关系,还须要负载均衡来保障高可用。在快速迭代的开发节奏下,使用传统的系统架构很难再去适应这样的结构。
咱们迫切须要一种可以快速应用的,方便部署各类异构服务的成熟解决方案。
首先是开箱即用,理论上来讲这应该是 KubeSphere 的优势,咱们直接点一点鼠标就能够打造一个高可用的 K8s 集群。这一点对咱们这种没有专职运维的中小团队来讲很重要。根据个人亲身经历,要从零开始搭建一个高可用的 K8s 集群仍是有点门槛的,没有接触过这方面的运维人员,一时半会是搞不定的,其中的坑也很是多。
若是云厂商能提供这种服务是最好的,咱们不用在服务搭建与系统优化上花费太多时间,能够把更多的精力放到业务上去。以前咱们还本身搭建数据库,缓存,搜索集群,后来所有都使用云服务了。这也让咱们的观念有了转变,云时代的基础服务,应该把它视为基础设施的一部分加以利用。
若是能把运维工做所有用代码来管理,那就再理想不过了。而目前 K8s 确实给咱们提供了这样一个能力,如今咱们每一个项目都有一个 Docker 目录,里面放置了不一样环境下的 Dockerfile,K8s 配置文件等等。不一样的项目,不一样的环境,不一样的部署,一切均可以在代码中描述出来加以管理。
好比咱们以前提到的一样的 API 服务,使用两种协议,变成了两个服务。在这如今的架构下,就能够实现后端代码一次书写,分开部署。其实这些文件就代替了不少部署操做,咱们须要作的只是定义好之后执行命令把它们推送到集群。
而一旦将这些运维工做代码化之后,咱们就能够利用现有的代码管理工具,像写代码同样来调整线上服务。更关键的一点是,代码化以后无形中又增长了版本管理功能,这离咱们理想中的全自动化运维又更近了一步。
持续集成标准化了代码发布流程,若是能将持续集成和 K8s 的部署能力结合起来,无疑能大大加快项目迭代速度。而在使用 K8s 以前咱们就一直用 GitLab 做为版本管理工具,它的持续集成功能对咱们来讲也比较适用。在作了一些脚本改造以后,咱们发现它也能很好地服务于现有的 K8s 架构,因此也没有使用 K8s 上诸如 Jenkins 这样的服务来作持续集成。
步骤其实也很简单,作好安全配置就没什么问题。咱们本地跑完单元测试以后,会自动上线到本地的测试环境。在代码合并到上线分支后,由管理员点击确认进行上线步骤。而后在本地 build 一个镜像推送到镜像服务器,通知 K8s 集群去拉取这个镜像执行上线,最后执行一个脚原本检查上线结果。整个流程都是可视化可追踪的,并且在代码管理界面就能够完成,方便开发者查看上线进度。
目前咱们用一个专门的仓库来管理这些基础镜像,这可使开发人员拥有与线上一致的开发环境,并且后续的版本升级也能够在基础镜像中统一完成。
除了将 Dockerfile 文件统一管理之外,咱们还将镜像 build 服务与持续集成结合起来。每一个 Dockerfile 文件都有一个所属的 VERSION 文件,每次修改里面的版本号并提交,系统都会自动 build 一个相应的镜像并推送到仓库。基础镜像的管理工做彻底自动化了,大大减小了人为操做带来的错误与混乱。
最后是一点感想:当作完容器化后,会发现应用在集群里运行的时候并不须要占用那么多台服务器。这是由于下降了资源的粒度,因此能够作更多的精细化规划,所以使用效率也提升了。
本文由博客一文多发平台 OpenWrite 发布!