From 367a5ff1661eba3ec213613a136092b3e28f8b13 Mon Sep 17 00:00:00 2001 From: faweizhao26 Date: Tue, 9 May 2023 18:55:40 +0800 Subject: [PATCH] add one new case Signed-off-by: faweizhao26 --- content/en/case/_index.md | 2 + content/zh/case/_index.md | 6 + content/zh/case/excelsecu.md | 164 ++++++++++++++++++++++++++ static/images/case/logo-excelsecu.png | Bin 0 -> 20464 bytes 4 files changed, 172 insertions(+) create mode 100644 content/zh/case/excelsecu.md create mode 100644 static/images/case/logo-excelsecu.png diff --git a/content/en/case/_index.md b/content/en/case/_index.md index 3fb4e55cd..91036fe85 100644 --- a/content/en/case/_index.md +++ b/content/en/case/_index.md @@ -115,6 +115,8 @@ section3: icon: 'images/case/logo-turing.png' - name: 'pigeon' icon: 'images/case/logo-pigeon.png' + - name: 'excelsecu' + icon: 'images/case/logo-excelsecu.png' - name: 'Internet' children: diff --git a/content/zh/case/_index.md b/content/zh/case/_index.md index 2bd657614..5d37a4755 100644 --- a/content/zh/case/_index.md +++ b/content/zh/case/_index.md @@ -108,6 +108,10 @@ section2: content: "无锡广播电视集团成立于 1999 年,为全国首家广电集团。" link: "wuxitv/" + - icon: "images/case/logo-excelsecu.png" + content: "深圳市文鼎创数据科技有限公司创立于 2006 年,是全球领先的线上身份认证解决方案提供商。" + link: "excelsecu/" + section3: title: 'KubeSphere 助力各行各业' tip: 全部 @@ -183,6 +187,8 @@ section3: icon: 'images/case/logo-turing.png' - name: 'pigeon' icon: 'images/case/logo-pigeon.png' + - name: 'excelsecu' + icon: 'images/case/logo-excelsecu.png' - name: '互联网' children: diff --git a/content/zh/case/excelsecu.md b/content/zh/case/excelsecu.md new file mode 100644 index 000000000..ddcf4cf77 --- /dev/null +++ b/content/zh/case/excelsecu.md @@ -0,0 +1,164 @@ +--- +title: excelsecu +description: + +css: scss/case-detail.scss + +section1: + title: 文鼎创 + content: 深圳市文鼎创数据科技有限公司创立于 2006 年,是全球领先的线上身份认证解决方案提供商。 + +section2: + listLeft: + - title: 公司简介 + contentList: + - content: 深圳市文鼎创数据科技有限公司创立于 2006 年,是全球领先的线上身份认证解决方案提供商,专注网络身份认证,数据安全领域,坚持稳健经营,持续创新、开放合作,在金融电子化、政府、企业办公等应用中提供解决方案,成为众多国有商业银行、全国性股份制银行、城市商业银行、农村商业银行、各省市税务、政府、各大 CA 机构以及跨国企业的合作伙伴,累积服务近亿用户,不断满足客户差异化需求。 + - content: 公司多年来持续创新,申请了大量的发明专利、实用新型专利和产品外观专利;登记了多项计算机软件着作权,同时是国家级高新技术企业;拥有商用密码产品型号证书、密码检测证书、银联认证证书、ISO9001:2015 国际质量管理体系认证及 ISO14001 环境管理体系认证;产品通过了 CE/FCC 认证、RoHS 认证。 + - content: 公司作为国际线上快速身份验证联盟(FIDO)的核心成员之一,致力于实现全球统一的在线验证标准,我们将运用该技术为不同地区的人们提供享有平等的安全网络世界的权利。 + image: + + - title: 背景介绍 + contentList: + - content: “文鼎创智能物联”是深圳市文鼎创数据科技有限公司针对物联网应用,推出的物联网解决方案,方案包含统一的物联网服务平台,”云打印机“,”收款云音箱“,”收款云扫码盒子“等旗下产品,为用户的数据安全保驾护航。 + - content: 作为一家 TO B 解决方案的硬件提供商,“硬件为主,软件为辅”是公司长期以来的开发模式,因此前期在对服务端的开发、部署、架构设计重视不够。传统的项目停留在单机(虚拟机)部署,人工打包上传,不仅费时费力,还容易出错,造成服务的不可用。 + - content: 在拥抱 K8s 之前,我们也尝试过 docker-compose 的方案,相对于人工打包部署,docker-compose 也确实给我们带来了一些便利: + - content: 1. ALL-IN-ONE,提供一键式的软件部署方案,无需执行繁琐的部署流程; + - content: 2. 隔离了宿主机系统的差异性; + - content: 3. 减少了运维人员进行版本迭代的操作,降低操作失误的可能性。 + - content: 在面向物联网行业推出新产品,新解决方案之后,对服务的稳定性,以及可靠性带来了新的挑战,现有的开发模式逐步跟不上业务的迭代需求,为此我们迫切需要打破现有的框架,探索新的一套软件迭代流程。 + image: + + - title: 选型说明 + contentList: + - content: 在决定拥抱云原生之时,我们对市面上的容器管理平台进行了调研,发现国外 Rancher 用户较多,国内 KubeSphere 位居前列。我们对容器管理平台的选型有几个标准: + - content: 1. 生态:一个开源项目的生态是否完善很重要,周边配套的工具能带来极佳的使用体验和可维护性。 + - content: 2. 社区活跃度:官方仓库 Issue 或问答社区是否回应及时,代码提交是否活跃? + - content: 3. 商业公司或基金会支持:是否有商业公司或开源基金会支持,如果为个人项目,后续停止维护,则可能会给用户带来的一定的风险。 + - content: 4. 技术栈:使用的技术栈与团队是否吻合,是否有能力解决和维护? + - content: 5. 用户体验:是否有 UI 操作界面,界面是否美观,使用流畅? + - content: 6. 本土化:是否做了一些本土化的优化,符合国人的使用习惯? + - content: 在调研选型时,我们发现 KubeSphere 能充分满足的我们的要求。KubeSphere 团队开源的 KubeKey 工具,能帮助我们快速搭建一个 KubeSphere 集群,省去了繁琐且复杂的部署流程,OpenELB 项目则为我们提供了本地集群负载均衡的解决方案。 + - content: 在使用过程中发现的问题,在中文问答社区基本都能找到对应的解决方案。KubeSphere 的控制台简化了 Kubernetes 服务的部署,使得团队一些没有 K8s 使用经验的成员也能快速上手,用过的同事都说好。 + image: https://pek3b.qingstor.com/kubesphere-community/images/excelsecu-kubesphere-1.png + + - type: 1 + contentList: + - content: 安装部署便捷,开箱即用 + - content: 降低了学习成本 + - content: 简化了中间件的部署 + + - title: 目前架构 + contentList: + - content: 目前采用微服务设计,开发语言以 Golang、Java 为主,服务之间通信使用 gRPC。 + image: https://pek3b.qingstor.com/kubesphere-community/images/excelsecu-kubesphere-2.jpeg + - title: + contentList: + - content: 生产环境使用两个腾讯云 CLB 分别接入来自业务和物联网终端的流量。整个业务服务部署在腾讯云 TKE 集群,并使用 KubeSphere 来管理应用的日常发布。而集群的基础设施,本着“能买就买,实在不能买就自建”的原则(并不是不差钱,而是小公司运维压力大)。之所以没有使用 TKE 的控制台来管理应用的发布,主要是 TKE 的控制台体验并不是很友好,另外一个很重要的原因,应用商店对第三方 Helm 仓库支持很差,无法充分利用 Helm 的生态。 + image: https://pek3b.qingstor.com/kubesphere-community/images/excelsecu-kubesphere-3.jpeg + + - title: 实践过程 + contentList: + - specialContent: + text: 硬件资源 + level: 3 + - content: 测试环境:10 台 ESXI 虚拟机,自建 Kubernetes 集群。 + - content: 生产环境:7 台 腾讯云 CVM 节点,Kubernetes 使用腾讯云托管 TKE 集群。 + image: https://pek3b.qingstor.com/kubesphere-community/images/excelsecu-kubesphere-4.png + - title: + contentList: + - specialContent: + text: 存储方案 + level: 3 + - content: 测试环境:使用 3 台 ESXI 虚拟机作为分布式存储 Ceph 的 OSD 节点。 + - content: 生产环境:出于成本和稳定性的考虑,使用腾讯云 CBS 作为 K8s 存储方案。 + image: + - title: + contentList: + - specialContent: + text: 最小化安装 + level: 3 + - content: 由于生产环境和测试环境已经有一些外部服务,比如 Prometheus 和 Logging,为了最大化利用现有资源,在部署 KubeSphere 采取了最小化安装。 + image: https://pek3b.qingstor.com/kubesphere-community/images/excelsecu-kubesphere-5.png + - title: + contentList: + - content: 值得一提的是,Monitor 并不是可插拔组件,即使最小化安装,KubeSphere 依然会默认安装,在生产环境中,安装 TKE 监控的 prometheus-operator 会与其冲突,需要关闭 KubeSphere 的 Prometheus 或者手动卸载。 + image: + - title: + contentList: + - specialContent: + text: DevOps + level: 3 + - content: 在早期开发阶段,版本迭代是一件非常痛苦的事情,开发人员在本地编译打包后人工上传到服务器进行部署。在经历了多次各种环境差异,人工操作失误教训后,团队下定决心改变现有的流程,决定搭建适合团队自身的 DevOps 体系。 + image: https://pek3b.qingstor.com/kubesphere-community/images/excelsecu-kubesphere-6.jpeg + - title: + contentList: + - content: 1. 持续集成(CI):开发在每次提交代码之前都进行 CI,以确保代码的质量和一致性。这包括运行单元测试,代码静态分析,编译和构建过程等。当 CI 失败时,开发立即修复代码并重新提交。 + - content: 2. 持续交付(CD):一旦代码通过了 CI 流程,就将其交付给测试团队进行测试。测试团队进行测试以确保产品的质量。在测试环境,使用了 Coding 的自定义节点作为 CI 的自动化构建,CI 通过后通过脚本自动更新 KubeSphere 的镜像版本。在生产环境,由于涉及发布评审流程,配置变更,各个业务团队的协调,目前暂时还是交由运维人员手动变更应用版本进行发布。 + - content: 3. 监控和警报:一旦代码被部署到生产环境,对其进行监控。监控可以帮助团队快速发现和解决问题,确保产品的可用性和性能。 + - content: 目前的 DevOps 实践,主要解决了团队以下的痛点: + - content: 1. 统一编译环境:规定项目内应编写 Dockerfile,使用 Docker 容器内的编译环境进行编译,同时通过代码提交事件触发代替开发机本地编译,从而隔离各个开发机环境的差异。 + - content: 2. 发布版本可追溯:早期项目版本管理十分随意,全凭开发人员心情命名。导致出现问题时无法快速定位。为此,我们约定在 CI 构建时,镜像版本需要满足特定的命名格式,如:`${VERSION}-${ENV}-\${CI_NUMBER}`,这种命名格式可以帮助我们快速定位到某个环境出现问题某次 CI 构建的版本。 + - content: 3. 平滑迭代:早期项目使用单机单体部署,在进行迭代时,常常有短时间的服务不可用,导致流量损失。在进行容器化改造后,利用 Kubernetes 的探针,可以进行服务的平滑更新,并且在服务状态不健康时,能自动重启,无需人工介入,大大提升了服务的可用性。 + - content: 4. 运维效率:充分发挥 Kubernetes 的运维体系和云原生的可观测性实践,降低了多业务多环境运维的压力。在服务故障发生时,能够及时感知。 + image: + + - title: 使用效果 + contentList: + - specialContent: + text: 流水线配置 + level: 3 + - content: + image: https://pek3b.qingstor.com/kubesphere-community/images/excelsecu-kubesphere-7.png + - title: + contentList: + - content: 流水线使用了 Coding 的方案,有以下几方面的考虑: + - content: 1. 能够深度融合企业微信,在 CI 过程,有任何问题能够及时通过 IM 工具通知到开发; + - content: 2. 配套工具完善,官方的 Jenkins 有点跟不上云原生的发展,需要安装一系列的插件才能满足需求,配置过程也很繁琐。 + image: + - title: + contentList: + - specialContent: + text: 应用部署 + level: 3 + - content: + image: https://pek3b.qingstor.com/kubesphere-community/images/excelsecu-kubesphere-8.png + - title: + contentList: + - content: “文鼎创智能物联”项目已全部使用 Helm 应用发布,在使用过程,发现 KubeSphere 一个比较不友好的体验,如果升级应用因 yaml 文件配置错误导致应用升级失败,会无法再次升级。在生产环境中,应用无法升级是一个很糟糕的问题,发现该 Bug 后,已提交了修复代码给社区并合并。 + image: + - title: + contentList: + - specialContent: + text: 集群资源监控 + level: 3 + - content: + image: https://pek3b.qingstor.com/kubesphere-community/images/excelsecu-kubesphere-9.png + - title: + contentList: + - content: KubeSphere 内置的监控系统,满足运维人员日常对集群健康状态的巡检,同时 KubeSphere 提供了多个层面的监控,针对 namespace 和服务本身,团队使用频次较高的是服务监控,以便开发人员对自身发布的服务的资源使用情况有所了解。 + image: + + - type: 2 + content: 'KubeSphere 安装部署便捷,开箱即用,且简化了 K8s 的部署,大大降低了学习成本。应用商店支持第三方 Helm 仓库,简化了中间件的部署。' + author: '文鼎创' + + - title: 未来规划 + contentList: + - content: 1. “文鼎创智能物联”作为公司探索的新项目已全面完成容器化工作,运行在 KubeSphere 集群,未来打算将历史遗留的 TO B 项目进行容器化改造和迁移到 KubeSphere 集群,提升项目的可维护性和可用性。 + - content: 2. 探索 Service Mesh 方案,进一步提升服务的平稳发布和可观测性。 + image: + + rightPart: + icon: /images/case/logo-excelsecu.png + list: + - title: 行业 + content: 物联网 + - title: 地点 + content: 中国深圳 + - title: 云类型 + content: 公有云 + - title: 挑战 + content: 高可用、交付效率,资源利用率 + - title: 采用功能 + content: 应用商店、监控、存储管理 +--- diff --git a/static/images/case/logo-excelsecu.png b/static/images/case/logo-excelsecu.png new file mode 100644 index 0000000000000000000000000000000000000000..b405db6f232841fccda8ce5e4465aa3bd9929a29 GIT binary patch literal 20464 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