作者:肖念康,东莞怡合达智能制造供应链资深 Java 开发工程师,主要负责公司内部 DevOps、代码托管平台、任务需求管理平台的研发及其他项目的管理,云原生的研究与开发工作。

怡合达致力于自动化零部件研发、生产和销售,提供 FA 工厂自动化零部件一站式供应,怡合达深耕自动化设备行业,基于应用场景对自动化设备零部件进行标准化设计和分类选型,通过标准设定、产品开发、供应链管理、平台化运营,以信息和数字化为驱动,为自动化设备行业提供高品质、低成本、短交期的自动化零部件产品。
目前公司拥有 3000+ 的员工,其中研发团队(运维,开发,测试,产品等)超过 300 人,在苏州,湖北都有研发团队。
目前行业正在向自动化、云原生靠近,传统的互联网模式已经无法满足大公司的业务需求了,为了让开发人员将更多的精力放在业务上,自动化部署、项目的全方位监控就变得越来越重要。
目前公司云原生是刚刚起步,很多东西需要去探索发现,所以技术上有很多欠缺,需要非常细致的理解各个组件的运行原理和模式。
拥抱云原生就意味着公司的 IT 层面将上升一个等级,原有的项目治理将完全摒弃,将会以一套全新的方式来全方位地治理项目,使用 Kubernetes 和容器化技术将减少服务的运维成本和项目的容错成本,为客户带来的使用体验也将提升一个层次。
在使用 KubeSphere 之前,我们也使用了很多其他的项目,如 KubeOperator,DaoCloud,Choerodon等。但是在使用过程中发现,其他工具的功能并不是很完善,遇到问题很难排查,社区也不是很活跃,这就导致我们的使用成本和维护成本大大增加。
我通过博客和论坛发现了 KubeSphere,Issue 的提出与解决非常的完善和及时。KubeSphere 官网有很多案例与讲解,社区活跃度非常高。这不正是我想要的吗?
经过实践使用 KubeSphere 搭建的集群更加稳定,资源管控更加便捷,与同类云原生产品相比,KubeSphere 几乎实现了我们在生产环境会用到的所有功能。
于是我们就开始在测试环境搭建并使用,随后慢慢地向生产环境迁移。目前我们公司有三分一的项目已经迁移到 KubeSphere 平台上,并且回收了之前的旧服务器,大大提高了资源使用率。
Kubernetes 与 KubeSphere 的搭建也非常简单,根据官方文档先下载 KubeKey, 使用 KubeKey 搭建就可以了。
目前我们使用私有环境来搭建 Kubernetes 与 KubeSphere,因为是在我们内部使用,所以不考虑在云上进行搭建。
基础服务器采用的是 Linux Centos 7,内核版本是 5.6。
在搭建 Kubernetes 集群时,我选择使用 Keepalived 和 HAproxy 创建高可用 Kubernetes 集群,其中包括两个负载均衡入口。

然后是 3 个 Master 节点,3 个 Worker 节点,一个 Etcd 集群,因为是多集群,我会为公司每个项目创建一个集群,所有我们单个集群分配的资源不是很多,当资源不够使用时需要进行申请。

平台的持久化存储我们使用的是第三方杉岩,这就需要对方来提供存储卷和创建存储系统空间,所以在这里就不做过多介绍。大家也可以使用开源的存储插件来做,KubeSphere 文档中提到了很多开源存储插件,使用起来也非常的方便。
在集群内部我们采用的是 Calico CNI 插件负责集群的内部通讯,当我们的服务部署至 Kubernetes 集群时会产生一个内部访问地址,这个地址在我们集群内是可以 ping 通和访问的,但外部无法访问。
所以在外部网络通讯方面我做了两套方案:

搭建方式也非常简单,创建一个 APISIX 模板,再创建一个应用就可以了:

创建完成之后集群内的项目就可以使用 APISIX 了,将 APISIX 开启对外访问,作为集群的唯一入口,接下来在服务中创建路由,就会在 APISIX 中自动生成一条路由规则与上游服务:

官方文档:https://openelb.io/docs/getting-started/usage/use-openelb-in-vip-mode/
安装和使用也很方便,可以直接在 KubeSphere 应用商店中选择安装,也可以在集群中通过 yaml 进行安装:

但是需要注意的是,通过应用商店进行安装一定要注意集群的内存空间是否充足,否则会导致集群监控组件异常。
安装完成之后,我们只需要开启 strictARP: true,并设置 EIP 池就可以了,然后我们在部署服务时加上注解:
annotations:
lb.kubesphere.io/v1alpha1: openelb
protocol.openelb.kubesphere.io/v1alpha1: layer2
eip.openelb.kubesphere.io/v1alpha2: eip-layer2-pool
将 type 改为:LoadBalance,就会在我们的 IP 池中获取一个对外访问的 IP 分配给服务进行对外访问了。
我们搭建了一套 EFK 的日志系统,通过 Filebeat 收集服务端的数据,再通过 Kafka 发送到 es 中,然后通过 Kibana 查询日志数据,另外我们增加了一套 SkyWalking,它会给我们生成一个链路 ID,这样我们就可以根据这个链路 ID 直接查找当前请求下的所有日志。
在监控方面除了 KubeSphere 自带的监控之外,我们还用了一套外部的监控系统:


我们开启了 KubeSphere 的 DevOps 模块,里面集成了 Jenkins,流水线的构建,实现了项目从拉取代码,质量检查到项目部署一键化的流程。
在 DevOps 模块中用的是自定义 GitLab 仓库,如果是自己实践的话可以去 KubeSphere 应用商店中下载使用,在这里我就介绍一下自定义实现。
首先需要打开 KubeSphere 自带的 Jenkins,进入页面创建一个 GitLab 的凭证,然后在系统配置自定义 GitLab 的地址。

这里的凭据就是我们刚刚创建的 GitLab 凭据,地址就直接填自己仓库的地址,然后就可以在 KubeSphere 中看到刚刚填写的地址了。

我是根据官方文档创建的流水线,其中有些地方需要自己指定。
在 Jenkins 中是提供一个 Maven,在这里我需要改成自定义的 Maven,不然项目构建的时候会失败,我们只需要在 configMap 中修改 setting.xml 文件就可以了。
镜像仓库用的是自定义 Harbor 仓库,要在 Harbor 中先创建存放镜像的地址,然后创建权限,在 KubeSphere 中添加凭证就可以使用了。

在使用流水线之前一定要把 GitLab、Kubernetes、镜像仓库的凭证建好,后面直接使用就可以了。

一些前置的条件配置好之后就可以直接去创建流水线了。

运行后可以看到运行记录。

流水线跑完之后就可以在项目中看到之前部署的项目了。

包括服务和容器组,在里面就可以对项目进行管理了,包括负载均衡,网关,路由,扩容等一些操作。
未来我们将把公司内部系统与 KubeSphere 完全打通,成立云原生小组来负责云原生的研发工作。
公司的服务器资源将完全回收,将会以集群分配的方式管理项目,之后会自研一些插件和组件使用并进行开源。
对于 KubeSphere,我们也有一些建议:
希望 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)如果我想为成千上万的用户存储此类信息,它就无法工作。推荐的方法是什么?我希望能够在这些服务之上构建一个界面,因此每次用户进行交易时都必须输入凭据是不可行的。