作者:谢元昌,广西交科集团有限公司软件院开发工程师。平时主要负责软件的开发以及运维工作。目前主要从事广西高速公路联网电子不停车收费 (ETC) 运营服务系统的设计与开发工作。本人对云原生工作有强烈向往,但一直苦于云原生门槛较高,实践机会少。自从公司落地了 KubeSphere 后,得到很多实践的机会。
广西交科集团有限公司软件研究院成立于 2017 年,前身为公司智能交通所软件研发中心,主要从事高速公路领域的软件开发、系统集成业务 , 为行业客户提供相关解决方案。现拥有软件著作权 74 项、软件产品 90 项,并通过 IS09001 质量体系认证,是广西高速公路领域最大的软件服务提供商。该院已获得美国 CMMI 研究院颁发的 CMMI5 级评估证书,在软件研发能力成熟度和项目管理方面达到了国际较高水平。
该院专注高速公路收费领域,在高速公路收费、高速公路运营管理支持、城市公共交通支付等领域取得突出成果,研发的“高速公路 IC 卡‘一卡通’联网收费系统”使广西率先成为全国第一批实现高速 : 公路联网收费的省份 ; 成功研发了广西第-套具有完全知识产权的“ETC 不停车收费系统”,包含广西高速公路联网电子不停车收费 (ETC) 系统服务及结算平台、ETC 联网清分中心系统、ETC 密钥管理系统等,ETC 不停车收费车道系统已经覆盖全广西范围内的高速公路并实现全国互联互通。二十多年来在广西累计建设 MTC 车道 3300 多条,ETC 车道 1600 多条,自动发卡机车道 370 多条。除专注发展高速公路收费领域外,该院在发展高速公路建管养一体化领域、口岸信息化领域也取得显著成果。
我们期望基于 K8s 搭建 PaaS 云计算平台。使用多租户方式管理和使用资源。集成 CI/CD 支持灵活扩容与升级集群。构建企业级一站式 DevOps 架构,提供集群资源的可监控性服务。
在使用 k8s 前,我们使用由第三方的运维团队负责的虚拟机管理平台。开发部署环境混乱,运维管理成本大,服务器资源利用率低。由于安全需要,每次登陆虚拟机都需要先经过一个堡垒机,然后再输入目标虚拟机的账户密码才能登录。
由于虚拟机的账户密码每 3 个月就会更换一次,所以每次登录都需要先查表才能知道最新的密码,非常麻烦。另外,每次更换密码也都需要运维人员大量纯手工操作,极其耗费时间。开发人员上线新应用时,需要运维人员支持先分配一台或多台虚拟机后将 IP 和账户密码发给开发人员,从此开发人员就拥有这个虚拟机的使用权,开发人员需要从 0 开始配置虚机的系统环境,安装中间件,手动上传应用,最后,再手动将应用运行起来。
应用下线时,开发人员一般是不会及时通知运维人员去回收资源的,因为重新配置一台机器非常麻烦,所以总是优先考虑留着资源,以备新的应用上线。由于运维人员对每个虚机的实际使用情况根本无法掌握,所以虚拟机资源经常无法回收,造成了大量服务器资源的浪费。
基础设施运维 3 人 , 开发团队 70 人。
在拥抱云原生之前,我们有上百台虚拟机被运维和开发人员同时管理,应用分布散乱,管理起来既费时又费力,已经是失控的边缘。拥抱云原生,使用 K8s 之后,我们采用 DevOps,统一分配资源。释放了运维人员的生产力,提升了开发人员的开发效率。
初期,我们部署了原生 K8s, 使用原生 Dashboard 运行了一段时间。后来觉得它对用户的认证方式过于粗放,UI 界面也不太友好,学习成本过高。直到有同事推荐了 KubeShpere,尝试着登录他们的官网,浏览帮助文档,登录社区论坛。 "more then Kubernetes and easier then Kubernetes"——“比 K8s 强大,又比 K8s 易用”从部署到运维体现得淋漓尽致。相对于同类产品的优势在于国人开发,本地化程度很高,面向开发用户友好,多租户的权限细粒度管理,日志查询界面便捷,周边生态整合全面,可灵活配置需要模块。
目前,我们已经搭建了两套 KubeSphere 环境。测试环境由 2 台物理机和一台虚机构成(1 个主节点 2 个工作节点)。生产环境由 5 台物理机构成(2 个主节点 3 个工作节点)。借着最近一个系统改造契机,我们已经把 80% 的应用运行在 KubeSphere 之上,后续的新开发的应用也都会直接部署 KubeSphere 环境上。
我们依托 KubeSphere 部署 Redis、RabbitMq、搭建 Elasticsearch 集群,Kibana 等。




现在核心业务的数据库我们使用的是物理机部署 Oracle,后续的一些轻量级应用我们计划可以依托 KubeSphere 部署 MySQL。
由于在使用 KubeSphere 之前,我们已经有一套 CI/CD 流程,所以我们的 Jenkins 和 Harbor 没有使用 KubeSphere 提供的构建流水线服务,后续我们会进行一些探索,尝试采用 Helm 构建应用,更好贴合 KubeSphere 的应用市场。

整体监控

各个节点资源监控

应用监控

应用日志查看

自定义报警监控

我们项目组成员缺乏 Docker 和 K8s 的使用经验。KubeSphere 无缝契合 K8s,操作画面友好,我们的开发人员能够低成本上手使用 K8s,享受 K8s 带来的便携性。
KubeSphere 的多租户架构与我们集团公司的企业架构一致。架构分三个层级。集群,企业空间和项目。其中,KubeSphere 中的最底层的项目等同于 Kubernetes 的命名空间。集群、企业空间是构建在 K8s 的名字空间之上的进一步抽象。KubeSphere 可以为建立多个集群,对应一个集团公司,一个集群下可以建立多个企业空间,对应一个公司,一个企业空间可以建立多个项目,对应公司实际产品线,每个层级的一个实例就是一个 Workspace,其他与同层次其他实例的资源隔离。
我们在落地了 KubeSphere 之后,有了以下成效。
本文由博客一文多发平台 OpenWrite 发布!
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵
我认为我的问题最好用一个例子来描述。假设我有一个名为“Thing”的简单模型,它有一些简单数据类型的属性。像...Thing-foo:string-goo:string-bar:int这并不难。数据库表将包含具有这三个属性的三列,我可以使用@thing.foo或@thing.bar之类的东西访问它们。但我要解决的问题是当“foo”或“goo”不再包含在简单数据类型中时会发生什么?假设foo和goo代表相同类型的对象。也就是说,它们都是“Whazit”的实例,只是数据不同。所以现在事情可能看起来像这样......Thing-bar:int但是现在有一个新的模型叫做“Whazit”,看起来
我有一个要在我的Rails3项目中使用的数组扩展方法。它应该住在哪里?我有一个应用程序/类,我最初把它放在(array_extensions.rb)中,在我的config/application.rb中我加载路径:config.autoload_paths+=%W(#{Rails.root}/应用程序/类)。但是,当我转到railsconsole时,未加载扩展。是否有一个预定义的位置可以放置我的Rails3扩展方法?或者,一种预先定义的方式来添加它们?我知道Rails有自己的数组扩展方法。我应该将我的添加到active_support/core_ext/array/conversion
我似乎经常遇到一些设计问题,但我不知道是什么是真的很合适。一方面我经常听到我应该限制耦合和坚持单一职责,但当我这样做时,我常常发现它很困难到在需要时将信息获取到程序的一部分。为了例如,classSingerdefinitialize(name)@name=nameendattr:nameend那么Song应该是:classSongdefnew(singer)@singer=singerendend或classSongdefnew(singer_name)@singer_name=singer_nameendend后者耦合性小,按道理应该用。但如果我以后发现宋有什么需要了解更多歌手,我的
我需要使用ActiveMerchant库在我们的一个Rails应用程序中设置支付解决方案。尽管这个问题非常主观,但人们对主要网关(BrainTree、Authorize.net等)的体验如何?它必须:处理定期付款。有能力记入个人帐户。能够取消付款。有办法存储用户的付款详细信息(例如Authotize.netsCIM)。干杯 最佳答案 ActiveMerchant很棒,但在过去一年左右的时间里,我在使用它时发现了一些问题。首先,虽然某些网关可能会得到“支持”——但并非所有功能都包含在内。查看功能矩阵以确保完全支持您选择的网关-http
我有一个像这样的ruby散列{"stuff_attributes"=>{"1"=>{"foo"=>"bar","baz"=>"quux"},"2"=>{"foo"=>"bar","baz"=>"quux"}}}我想把它变成一个看起来像这样的散列{"stuff_attributes"=>[{"foo"=>"bar","baz"=>"quux"},{"foo"=>"bar","baz"=>"quux"}]}我还需要保留键的数字顺序,并且键的数量是可变的。上面是super简化的,但我在底部包含了一个真实的例子。执行此操作的最佳方法是什么?附言还需要递归就递归而言,这是我们可以假设的:1)
参见下面的示例,我想最好使用第二种方法,但第一种也可以。哪种方法最好,使用另一种的后果是什么?classTestdefstartp"started"endtest=Test.newtest.startendclassTest2defstartp"started"endendtest2=Test2.newtest2.start 最佳答案 我肯定会说第二种变体更有意义。第一个不会导致错误,但对象实例化完全过时且毫无意义。外部变量在类的范围内不可见:var="string"classAvar=A.newendputsvar#=>strin
如果我构建了一个应用程序来访问来自Gmail、Twitter和Facebook的一些数据,并且我希望用户只需输入一次他们的身份验证信息,并且在几天或几周后重置,那会怎样是在Ruby中动态执行此操作的最佳方法吗?我看到很多人只是拥有他们客户/用户凭证的配置文件,如下所示:gmail_account:username:myClientpassword:myClientsPassword这看起来a)非常不安全,b)如果我想为成千上万的用户存储此类信息,它就无法工作。推荐的方法是什么?我希望能够在这些服务之上构建一个界面,因此每次用户进行交易时都必须输入凭据是不可行的。