From d24c93788ebe6b3edbc912323d5443754c824dfa Mon Sep 17 00:00:00 2001 From: faweizhao26 Date: Wed, 10 Nov 2021 20:10:00 +0800 Subject: [PATCH] add new case of segmentfault Signed-off-by: faweizhao26 --- content/zh/case/_index.md | 4 + content/zh/case/segmentfault.md | 122 +++++++++++++++++++++++ static/images/case/segmentfault-logo.png | Bin 0 -> 18405 bytes 3 files changed, 126 insertions(+) create mode 100644 content/zh/case/segmentfault.md create mode 100644 static/images/case/segmentfault-logo.png diff --git a/content/zh/case/_index.md b/content/zh/case/_index.md index b2e674a4e..7b696315a 100644 --- a/content/zh/case/_index.md +++ b/content/zh/case/_index.md @@ -56,6 +56,10 @@ section2: content: "去哪儿网(Qunar.com)是中国领先的在线旅游平台,创立于 2005 年 5 月,总部位于北京。" link: "qunar/" + - icon: "images/case/segmentfault-logo.png" + content: "SegmentFault 思否是国内领先的新一代开发者社区和技术媒体,是中国最大的 Hackathon 组织者,目前已覆盖和服务上千万中国软件开发者和 IT 信息从业者。" + link: "segmentfault/" + section3: title: 'KubeSphere 助力各行各业' tip: 全部 diff --git a/content/zh/case/segmentfault.md b/content/zh/case/segmentfault.md new file mode 100644 index 000000000..21d6f38ee --- /dev/null +++ b/content/zh/case/segmentfault.md @@ -0,0 +1,122 @@ +--- +title: SegmentFault +description: + +css: scss/case-detail.scss + +section1: + title: SegmentFault 思否 + content: SegmentFault 思否是国内领先的新一代开发者社区和技术媒体,也是中国最大的 Hackathon 组织者,目前已经覆盖和服务了上千万中国软件开发者和 IT 信息从业者。 + +section2: + listLeft: + - title: 公司简介 + contentList: + - content: SegmentFault(https://segmentfault.com/)是一家综合性技术社区,由于它的内容跟编程技术紧密相关,因此访问量的波动也和这一群体的作息时间深度绑定。通常情况下 web 页面的请求量峰值在 800 QPS 左右,但我们还做了前后端分离,所以 API 网关的峰值 QPS 是请求量峰值的好几倍。 + image: + + - title: 架构历史 + contentList: + - content: 2012 年,为了帮助中文开发者用母语在像 StackOverflow 这样的网站上提问,SegmentFault 诞生。但是第一个版本非常简陋,访问量很少。将它放在了国外的 VPS 托管商 Linode 上,所有的应用、数据库、缓存都挤在一个实例上。 + - content: 2013-2014 年,我们选择了自己购买二手服务器去机房托管,经常遇到问题,我们团队在外地又去不了机房,只能等管理员去机房帮我们解决。正好在 2014 年我们的网站被 DDos 攻击了,机房为了不连累其他服务器,直接把我们的网线拔掉了。 + - content: 2014-2019 年,中国的云计算也开始起步了,于是我们把整个网站从物理服务器迁移到了云服务上。当然使用上并没有什么不同,只是把物理机器替换成了虚拟主机。 + - content: 2020 年至今,随着云原生理念的兴起,我们的业务模式也发生了很大变化,为了让系统架构适应这些变化,我们把网站的主要业务都迁移到了 KubeSphere 上。 + image: + + - title: 遇到的挑战 + contentList: + - content: 我们遇到了不少挑战,促使我们不得不往 K8s 架构上迁移。 + - content: 其次,复杂的场景引发了复杂的配置管理,不同的业务要用到不同的服务,不同的版本,即使用自动化脚本效率也不高。 + - content: 另外,我们内部人员不足,所以没有专职运维,现在 OPS 的工作是由后端开发人员轮值的。但后端开发人员还有自己本职工作要做,所以对我们最理想的场景是能把运维工作全部自动化。 + - content: 最后也是最重要的一点就是我们要控制成本。当然,如果资金充足,以上的问题都不是问题,但是对于创业公司(特别是像我们这种访问量比较大,但是又不像电商,金融那些盈利的公司)来说,我们必将处于且长期处于这个阶段。因此能否控制好成本,是一个非常重要的问题。 + image: + + - title: 前后端分离 + contentList: + - content: 2020 年以前,SegmentFault 的网站还是非常传统的后端渲染页面的方法,所以服务端的架构也非常简单。服务端将浏览器的 http 请求转发到后端的 php 服务,php 服务渲染好页面后再返回给浏览器。这种架构用原有的部署方法还能支撑,也就是在各个实例上部署 php 服务,再加一层负载均衡就基本满足需求了。 + image: https://pek3b.qingstor.com/kubesphere-community/images/1694153167.png + - title: + contentList: + - content: 然而随着业务的持续发展,后端渲染的方式已经不适合我们的项目规模了,因此我们在 2020 年做了架构调整,准备将前后端分离。前后端分离的技术特点我在这里就不赘述了,这里主要讲它给我们带来了哪些系统架构上的挑战。一个是入口增多,因为前后端分离不仅涉及到客户端渲染(CSR),还涉及到服务端渲染(SSR),所以响应请求的服务就从单一的服务变成了两类服务,一类是基于 node.js 的 react server 服务(用来做服务端渲染),另一类是 基于 php 写的 API 服务(用来给客户端渲染提供数据)。而服务端渲染本身还要调用 API,而我们为了优化服务端渲染的连接和请求响应速度,还专门启用了了使用专有通讯协议的内部 API 服务。 + image: https://pek3b.qingstor.com/kubesphere-community/images/2947375573.png + - title: + contentList: + - content: 所以实际上我们的 WEB SERVER 有三类服务,每种服务的环境各不相同,所需的资源不同,协议不同,各自之间可能还有相互连接的关系,还需要负载均衡来保障高可用。在快速迭代的开发节奏下,使用传统的系统架构很难再去适应这样的结构。 + - content: 我们迫切需要一种能够快速应用的,方便部署各种异构服务的成熟解决方案。 + image: + + - title: KubeSphere 带来了什么? + contentList: + - specialContent: + text: 开箱即用 + level: 3 + - content: 首先是开箱即用,理论上来说这应该是 KubeSphere 的优点,我们直接点一点鼠标就可以打造一个高可用的 K8s 集群。这一点对我们这种没有专职运维的中小团队来说很重要。根据我的亲身经历,要从零开始搭建一个高可用的 K8s 集群还是有点门槛的,没有接触过这方面的运维人员,一时半会是搞不定的,其中的坑也非常多。 + - content: 如果云厂商能提供这种服务是最好的,我们不用在服务搭建与系统优化上花费太多时间,可以把更多的精力放到业务上去。之前我们还自己搭建数据库,缓存,搜索集群,后来全部都使用云服务了。这也让我们的观念有了转变,云时代的基础服务,应该把它视为基础设施的一部分加以利用。 + image: https://pek3b.qingstor.com/kubesphere-community/images/41259074.png + - title: + contentList: + - specialContent: + text: 用代码管理部署 + level: 3 + - content: 如果能把运维工作全部用代码来管理,那就再理想不过了。而目前 K8s 确实给我们提供了这样一个能力,现在我们每个项目都有一个 Docker 目录,里面放置了不同环境下的 Dockerfile,K8s 配置文件等等。不同的项目,不同的环境,不同的部署,一切都可以在代码中描述出来加以管理。 + - content: 比如我们之前提到的同样的 API 服务,使用两种协议,变成了两个服务。在这现在的架构下,就可以实现后端代码一次书写,分开部署。其实这些文件就代替了很多部署操作,我们需要做的只是定义好以后执行命令把它们推送到集群。 + - content: 而一旦将这些运维工作代码化以后,我们就可以利用现有的代码管理工具,像写代码一样来调整线上服务。更关键的一点是,代码化之后无形中又增加了版本管理功能,这离我们理想中的全自动化运维又更近了一步。 + image: + - title: + contentList: + - specialContent: + text: 持续集成,快速迭代 + level: 3 + - content: 持续集成标准化了代码发布流程,如果能将持续集成和 K8s 的部署能力结合起来,无疑能大大加快项目迭代速度。而在使用 K8s 之前我们就一直用 GitLab 作为版本管理工具,它的持续集成功能对我们来说也比较适用。在做了一些脚本改造之后,我们发现它也能很好地服务于现有的 K8s 架构,所以也没有使用 K8s 上诸如 Jenkins 这样的服务来做持续集成。 + - content: 步骤其实也很简单,做好安全配置就没什么问题。我们本地跑完单元测试之后,会自动上线到本地的测试环境。在代码合并到上线分支后,由管理员点击确认进行上线步骤。然后在本地 build 一个镜像推送到镜像服务器,通知 K8s 集群去拉取这个镜像执行上线,最后执行一个脚本来检查上线结果。整个流程都是可视化可追踪的,而且在代码管理界面就可以完成,方便开发者查看上线进度。 + image: https://pek3b.qingstor.com/kubesphere-community/images/qunar-gaizaodian.webp + + - type: 1 + contentList: + - content: 开箱即用的特性大大降低了企业容器化的使用门槛 + - content: 更加精细地控制服务资源粒度,降低企业运营成本 + - content: 实现全自动化测试部署,大大提高了发布效率 + + - title: 总结经验 + contentList: + - specialContent: + text: 管理好基础镜像 + level: 3 + - content: 目前我们用一个专门的仓库来管理这些基础镜像,这可以使开发人员拥有与线上一致的开发环境,而且后续的版本升级也可以在基础镜像中统一完成。 + - content: 除了将 Dockerfile 文件统一管理以外,我们还将镜像 build 服务与持续集成结合起来。每个 Dockerfile 文件都有一个所属的 VERSION 文件,每次修改里面的版本号并提交,系统都会自动 build 一个相应的镜像并推送到仓库。基础镜像的管理工作完全自动化了,大大减少了人为操作带来的错误与混乱。 + image: + - title: + contentList: + - specialContent: + text: KubeSphere 使用 + level: 3 + - content: 别把日志服务放到集群里。这一点在 KubeSphere 文档中就有提及。具体到日志服务,主要就是一个 Elastic 搜索服务,自建一个Elastic 集群即可。因为日志服务本身负载比较大,而且对硬盘的持续性需求高,如果你会发现日志服务本身就占据了集群里相当大的资源,就得不偿失了。 + - content: 如果生产环境要保证高可用,还是要部署 3 个或以上的节点。从我们使用的经验来看,主节点偶尔会出现问题。特别是遇到节点机器要维护或者升级的时候,多个主节点可以保证业务的正常运行。 + - content: 如果你本身不是专门提供数据库或缓存的服务商,这类高可用服务就不要上K8s,因为要保证这类服务高可用本身就要耗费你大量的精力。我建议还是尽量用云厂商的服务。 + - content: 副本的规模和集群的规模要匹配。如果你的容器只有几个节点,但一个服务里面扩展了上百个副本,系统的调度会过于频繁从而把资源耗尽。所以这两者要相匹配,在系统设计的时候就要考虑到。 + image: + + - type: 2 + content: 'KubeSphere 的应用改变了我们的整个开发流程,它让运维工作可视化,代码化,标准化。从而使得我们的开发人员可以参与到整个交付流程中去,大大提升了产品发布效率。而得益于 KubeSphere 良好的交互设计,我们还能快速定位和处理线上事故,提高了系统运行的稳定性。' + author: 'SegmentFault' + + - title: 未来展望 + contentList: + - content: 随着后端的不断微服务化,我们将越来越依赖 K8s 提供的低成本系统管理能力,而在这之中 KubeSphere 也扮演了越来越重要的角色。当前系统架构的趋势是自动化和标准化,管理系统的手段也将从配置变为代码,这大大增加系统的灵活性和可维护性,而复杂性也随之提升。软件决定了我们看待计算能力的方式,KubeSphere 这类软件带来的新的可能将促使我们不断探索系统架构的新思路。 + image: + + rightPart: + icon: /images/case/segmentfault-logo.png + list: + - title: 行业 + content: 技术社区 + - title: 地点 + content: 中国 + - title: 云类型 + content: 公有云 + - title: 挑战 + content: 人员、运营成本、自动化脚本效率低 + - title: 采用功能 + content: DevOps、CI/CD + +--- diff --git a/static/images/case/segmentfault-logo.png b/static/images/case/segmentfault-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2eec6f416b2ef3f4c9c2ac480b88af879a4c5007 GIT binary patch literal 18405 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