本文是根据 KubeSphere 云原生 Meetup 杭州站讲师祁宁分享内容整理而成。

SegmentFault 是一家综合性技术社区,由于它的内容跟编程技术紧密相关,因此访问量的波动也和这一群体的作息时间深度绑定。通常情况下 web 页面的请求量峰值在 800 QPS 左右,但我们还做了前后端分离,所以 API 网关的峰值 QPS 是请求量峰值的好几倍。

架构历史

SegmentFault 作为一个技术社区的系统架构变化,里面有些东西还是很有意思的。

  • 2012 年当时我还在北京的一家公司打工,当我在出租屋里写下它的第一行代码时,我不会想象到它到后面会成为我的事业。当时我的想法很简单,就是想帮助中文开发者用母语在像 StackOverflow 这样的网站上提问,因此它的第一个版本非常简陋,考虑到它的访问量很少以及自己的经济能力不足,我将它放在了国外的 VPS 托管商 Linode 上,所有的应用、数据库、缓存都挤在一个实例上。
  • 2013-2014 年,单独出来创业,业务逐渐步入正轨。我们选择了自己购买服务器去机房托管,当然服务器也是从淘宝上购买的二手服务器,经常遇到问题,我们团队在外地又去不了机房,只能等管理员去机房帮我们解决。正好在2014年我们的网站被 DDos 攻击了,机房为了不连累其他服务器,直接把把我们的网线拔掉了。
  • 2014-2019 年,中国的云计算也开始起步了,于是我们把整个网站从物理服务器迁移到了云服务上。当然使用上并没有什么不同,只是把物理机器替换成了虚拟主机。
  • 2020 年至今,随着云原生理念的兴起,我们的业务模式也发生了很大变化,为了让系统架构适应这些变化,我们把网站的主要业务都迁移到了 KubeSphere 上。

遇到的挑战

紧接着,我们遇到了不少挑战,促使使我们不得不往 K8s 架构上迁移。

  • 首先,虽然我们是一家小公司,但是业务线却非常复杂,整个公司只有 30 人左右,技术人员只占其中三分之一左右,所以承载这么大的业务量负担还是很重的。而且创业公司的业务线调整非常频繁,临时性工作也比较多,传统的系统架构在应对这种伸缩性要求比较高的场景是比较吃力的。

  • 其次,复杂的场景引发了复杂的配置管理,不同的业务要用到不同的服务,不同的版本,即使用自动化脚本效率也不高。

  • 另外,我们内部人员不足,所以没有专职运维,现在 OPS 的工作是由后端开发人员轮值的。但后端开发人员还有自己本职工作要做,所以对我们最理想的场景是能把运维工作全部自动化。

  • 最后也是最重要的一点就是我们要控制成本,这是高情商的说法,低情商就是一个字“穷”(笑)。当然,如果资金充足,以上的问题都不是问题,但是对于创业公司(特别是像我们这种访问量比较大,但是又不像电商,金融那些挣钱的公司)来说,我们必将处于且长期处于这个阶段。因此能否控制好成本,是一个非常重要的问题。

前后端分离

2020 年以前,SegmentFault 的网站还是非常传统的后端渲染页面的方法,所以服务端的架构也非常简单。服务端将浏览器的 http 请求转发到后端的 php 服务,php 服务渲染好页面后再返回给浏览器。这种架构用原有的部署方法还能支撑,也就是在各个实例上部署 php 服务,再加一层负载均衡就基本满足需求了。

然而随着业务的持续发展,后端渲染的方式已经不适合我们的项目规模了,因此我们在 2020 年做了架构调整,准备将前后端分离。前后端分离的技术特点我在这里就不赘述了,这里主要讲它给我们带来了哪些系统架构上的挑战。一个是入口增多,因为前后端分离不仅涉及到客户端渲染(CSR),还涉及到服务端渲染(SSR),所以响应请求的服务就从单一的服务变成了两类服务,一类是基于 node.js 的 react server 服务(用来做服务端渲染),另一类是 基于 php 写的 API 服务(用来给客户端渲染提供数据)。而服务端渲染本身还要调用 API,而我们为了优化服务端渲染的连接和请求响应速度,还专门启用了了使用专有通讯协议的内部 API 服务。

所以实际上我们的 WEB SERVER 有三类服务,每种服务的环境各不相同,所需的资源不同,协议不同,各自之间可能还有相互连接的关系,还需要负载均衡来保障高可用。在快速迭代的开发节奏下,使用传统的系统架构很难再去适应这样的结构。

我们迫切需要一种能够快速应用的,方便部署各种异构服务的成熟解决方案。

Kubernetes 带来了什么?

开箱即用

首先是开箱即用,理论上来说这应该是 KubeSphere 的优点,我们直接点一点鼠标就可以打造一个高可用的 K8s 集群。这一点对我们这种没有专职运维的中小团队来说很重要。根据我的亲身经历,要从零开始搭建一个高可用的 K8s 集群还是有点门槛的,没有接触过这方面的运维人员,一时半会是搞不定的,其中的坑也非常多。

如果云厂商能提供这种服务是最好的,我们不用在服务搭建与系统优化上花费太多时间,可以把更多的精力放到业务上去。之前我们还自己搭建数据库,缓存,搜索集群,后来全部都使用云服务了。这也让我们的观念有了转变,云时代的基础服务,应该把它视为基础设施的一部分加以利用。

用代码管理部署

如果能把运维工作全部用代码来管理,那就再理想不过了。而目前 K8s 确实给我们提供了这样一个能力,现在我们每个项目都有一个 Docker 目录,里面放置了不同环境下的 Dockerfile,K8s 配置文件等等。不同的项目,不同的环境,不同的部署,一切都可以在代码中描述出来加以管理。

比如我们之前提到的同样的 API 服务,使用两种协议,变成了两个服务。在这现在的架构下,就可以实现后端代码一次书写,分开部署。其实这些文件就代替了很多部署操作,我们需要做的只是定义好以后执行命令把它们推送到集群。

而一旦将这些运维工作代码化以后,我们就可以利用现有的代码管理工具,像写代码一样来调整线上服务。更关键的一点是,代码化之后无形中又增加了版本管理功能,这离我们理想中的全自动化运维又更近了一步。

持续集成,快速迭代

持续集成标准化了代码发布流程,如果能将持续集成和 K8s 的部署能力结合起来,无疑能大大加快项目迭代速度。而在使用 K8s 之前我们就一直用 GitLab 作为版本管理工具,它的持续集成功能对我们来说也比较适用。在做了一些脚本改造之后,我们发现它也能很好地服务于现有的 K8s 架构,所以也没有使用 K8s 上诸如 Jenkins 这样的服务来做持续集成。

步骤其实也很简单,做好安全配置就没什么问题。我们本地跑完单元测试之后,会自动上线到本地的测试环境。在代码合并到上线分支后,由管理员点击确认进行上线步骤。然后在本地 build 一个镜像推送到镜像服务器,通知 K8s 集群去拉取这个镜像执行上线,最后执行一个脚本来检查上线结果。整个流程都是可视化可追踪的,而且在代码管理界面就可以完成,方便开发者查看上线进度。

总结经验

管理好基础镜像

目前我们用一个专门的仓库来管理这些基础镜像,这可以使开发人员拥有与线上一致的开发环境,而且后续的版本升级也可以在基础镜像中统一完成。

除了将 Dockerfile 文件统一管理以外,我们还将镜像 build 服务与持续集成结合起来。每个 Dockerfile 文件都有一个所属的 VERSION 文件,每次修改里面的版本号并提交,系统都会自动 build 一个相应的镜像并推送到仓库。基础镜像的管理工作完全自动化了,大大减少了人为操作带来的错误与混乱。

KubeSphere 使用

  1. 别把日志服务放到集群里。这一点在 KubeSphere 文档中就有提及。具体到日志服务,主要就是一个 Elastic 搜索服务,自建一个Elastic 集群即可。因为日志服务本身负载比较大,而且对硬盘的持续性需求高,如果你会发现日志服务本身就占据了集群里相当大的资源,就得不偿失了。
  2. 如果生产环境要保证高可用,还是要部署 3 个或以上的节点。从我们使用的经验来看,主节点偶尔会出现问题。特别是遇到节点机器要维护或者升级的时候,多个主节点可以保证业务的正常运行。
  3. 如果你本身不是专门提供数据库或缓存的服务商,这类高可用服务就不要上K8s,因为要保证这类服务高可用本身就要耗费你大量的精力。我建议还是尽量用云厂商的服务。
  4. 副本的规模和集群的规模要匹配。如果你的容器只有几个节点,但一个服务里面扩展了上百个副本,系统的调度会过于频繁从而把资源耗尽。所以这两者要相匹配,在系统设计的时候就要考虑到。

最后是一点感想:当做完容器化后,会发现应用在集群里运行的时候并不需要占用那么多台服务器。这是因为降低了资源的粒度,所以可以做更多的精细化规划,因此使用效率也提高了。

本文由博客一文多发平台 OpenWrite 发布!

SegmentFault 基于 Kubernetes 的容器化与持续交付实践的更多相关文章

  1. 云端基于Docker的微服务与持续交付实践

    云端基于Docker的微服务与持续交付实践笔记,是基于易立老师在阿里巴巴首届在线技术峰会上<云端基于Docker的微服务与持续交付实践>总结而出的. 本次主要讲了什么? Docker Sw ...

  2. [置顶] Docker学习总结(7)——云端基于Docker的微服务与持续交付实践

    本文根据[2016 全球运维大会•深圳站]现场演讲嘉宾分享内容整理而成 讲师简介 易立 毕业于北京大学,获得学士学位和硕士学位:目前负责阿里云容器技术相关的产品的研发工作. 加入阿里之前,曾在IBM中 ...

  3. [持续交付实践] Jenkins Pipeline 高可用设计方法

    前言 这篇写好一段时间了,一直也没发布上来,今天稍微整理下了交下作业,部分内容偷懒引用了一些别人的内容.使用Jenkins做持续集成/持续交付,当业务达到一定规模的时候,Jenkins本身就很容易成为 ...

  4. Docker学习总结(14)——从代码到上线, 云端Docker化持续交付实践

    2016云栖大会·北京峰会于8月9号在国家会议中心拉开帷幕,在云栖社区开发者技术专场中,来自阿里云技术专家罗晶(瑶靖)为在场的听众带来<从代码到上线,云端Docker化持续交付实践>精彩分 ...

  5. ASP.NET Core应用程序容器化、持续集成与Kubernetes集群部署(一)(转载)

    本文结构 ASP.NET Core应用程序的构建 ASP.NET Core应用程序容器化所需注意的问题 应用程序的配置信息 端口侦听 ASP.NET Core的容器版本 docker镜像构建上下文(B ...

  6. IBM基于Kubernetes的容器云全解析

    基于Kubernetes的容器云 容器云最主要的功能是以应用为中心,帮助用户把所有的应用以容器的形式在分布式里面跑起来,最后把应用以服务的形式呈现给用户.容器云里有两个关键点,一是容器编排,二是资源调 ...

  7. 039.[转] 基于 Kubernetes 和 Spring Cloud 的微服务化实践

    http://dockone.io/article/2967 基于 Kubernetes 和 Spring Cloud 的微服务化实践 写在前面 网易云容器平台期望能给实施了微服务架构的团队提供完整的 ...

  8. 容器时代的持续交付工具---Drone:Drone介绍与安装

    Drone:Drone is a Container-Native, Continuous Delivery Platform. 官方给的定义,从上面的定义可以得出两个关键点: 1,Container ...

  9. 联想企业网盘:SaaS服务集群化持续交付实践

    1      前言 当代信息技术飞速发展,软件和系统的代码规模都变得越来越大,而且组件众多,依赖繁复,每次新版本的发布都仿佛是乘坐一次无座的绿皮车长途夜行,疲惫不堪.软件交付是一个复杂的工程,涉及到软 ...

  10. [持续交付实践] Jenkins 中国用户大会参会见闻

    前言 上周日在上海召开了Jenkins中国用户大会(Jenkins User Confluence China),这应该是Jenkins在中国第一次举办吧.Jenkins的创始人Kohsuke Kaw ...

随机推荐

  1. Regardless of the outcome of the Russia-Ukraine war, how can Ukraine avoid paying the weapon fees to the United States after the war?

    According to the agreement between the Ukrainian government and the United States, regardless of the ...

  2. 【转载】 PID原理与参数调试

    原文地址: http://m.elecfans.com/article/1153309.html --------------------------------------------------- ...

  3. batch normalization的multi-GPU版本该怎么实现? 【Tensorflow 分布式PS/Worker模式下异步更新的情况】

    最近由于实验室有了个AI计算平台,于是研究了些分布式和单机多GPU的深度学习代码,于是遇到了下面的讨论: https://www.zhihu.com/question/59321480/answer/ ...

  4. 一个好主板对CPU超频的现实意义————一次超频经历 (z390ws华硕工作站主板+i7-9700k CPU ,Ubuntu18.04.5系统,8核心超频 5.2Ghz以上,单核心满负荷运转可以稳定运行10多分钟后才重启)

    本人于今年2020年1月份在某宝上购买了一款workstation主板,也就是工作站主板,传说中的华硕Z390WS主板(购入价格为3900元),由于当时手里有些小钱,又弄了一个大蝴蝶1350w的电源( ...

  5. 后端开发学习敏捷需求-->专题的目标与价值成效

    专题的目标与价值成效 什么是专题 公司或企业为了抓住业务机会或者解决痛点问题,而采取的具体的行动和举措 专题的目标分析 1.业务调研了解目标的预期 利用5W2H来进行专题分析 what--是什么?目的 ...

  6. Python-目标检测-将xml文件转换成.txt文件

    代码说明:labels文件夹是工程下的一个文件夹,里面存放的是一些xml文件. 然后我们将这些xml文件中的内容取出来,放在路径path1的文件名下.这样也就完成了xml文件到txt文件的转化. 该代 ...

  7. 017.Kubernetes二进制集群扩容worker

    一 前置准备 1.1 互信配置 为了更方便远程分发文件和执行命令,本实验配置master节点到其它节点的 ssh 信任关系. 1 [root@master01 ~]# ssh-copy-id -i ~ ...

  8. 卷积神经网络CNN实战:MINST手写数字识别——数据集下载与网络训练

    数据集下载 这一部分比较简单,就不过多赘述了,把代码粘贴到自己的项目文件里,运行一下就可以下载了. from torchvision import datasets, transforms # 定义数 ...

  9. .net core 依赖注入,运行报错 Cannot consume scoped 'xxx' service from singleton 'yyy'

    这是因为 xxx 的生命周期是 AddScoped 注入的,而 yyy 的生命周期是 AddSingleton ,然后 yyy 这个单例的对象中,它又依赖了xxx 也就是说,单例注入的对象中依赖了 A ...

  10. 小忙半个月搞个CKA,可还行,搞完后发现自己被割韭菜了