作者:毛伟,现任无锡广电集团新媒体中心系统架构师,曾负责全国多个省级、市级、区县融媒体平台设计建设,有着丰富的新媒体行业建设系统架构设计经验。现主要从事无锡博报系列新媒体平台建设,推动各业务产品线向云原生转型,并在此领域开展相关布道工作。
无锡广播电视集团成立于 1999 年,为全国首家广电集团。2007 年底组建成立无锡广播电视台(与无锡广播电视集团两块牌子、一套班子)。集团作为主流媒体和市属文化国企,承担宣传与经营双重职能:一方面为市委市政府中心工作和全市改革发展稳定大局提供舆论服务,一方面通过保持提升经营效益,为宣传工作提供支撑,为全市文化产业发展贡献力量。集团目前拥有 6 个广播频率、7 个电视频道(其中 1 个公交、地铁移动电视频道)、“无锡博报”领衔的新媒体矩阵。
作为国内最早提出媒体融合发展理念,并付诸实践和不断创新的城市广电媒体之一,无锡广电早在2012年就开始布局移动端战略并不断创新,在 2021 年将旗下两大客户端升级迭代全新的“无锡博报”客户端,并形成系列化的“博报”微信公众号、微博和视频号,组成传播力和影响力更强的新媒体矩阵。近期荣获国家广电总局 2022 年度“全国广播电视媒体融合先导单位”和“新时代 新品牌 新影响”等荣誉。
在长期的实践中,无锡广电逐步摸索出适合城市广电的媒体融合发展思路和经验。以传播力建设为引领,对外积极打造新型传播体系,坚持“移动优先”战略,做大做强移动端平台,占领新兴传播阵地。以全网传播和本地运营需求为导向,持续推动内部组织架构、体制机制、业务流程、技术平台的再造和优化。推动“主力军全面挺进主战场”,将传统广播电视的团队和产能向新媒体端转移,打造具有城市媒体特色舆论主阵地。
这就要求无锡广电必须快速适应不断变化的运营和市场需求,用高效、敏捷的应用部署和运维对各类成几何式增长业务提供有力支撑。
在进行容器化改造前,无锡广电主要是采用基于虚拟化技术的基础设施环境,每个业务应用根据各自的需求采用独立虚机部署,随着时间的积累虚机规模变得越来越庞大、复杂。架构不足日益凸显,具体如下:
这些问题导致运维效率相对较低,无法满足业务快速迭代的需求。因此,无锡广电新媒体运维团队决定进行容器化改造,以提升系统的弹性、灵活性和可维护性,实现如下功能:
为此,拥抱云原生已经成为整个行业的趋势,可以帮助降低成本、提高效率、增强竞争力。
通过前期初步使用容器化及 Kubernetes 的积累上,在决定全面转型容器化前我们对未来整个 Kubernetes 的管理平台规划上面建立了结合自身的一些需求:
在选型期间我们正好在规划部署自研业务的集群,在 CNCF 认证的 Kubernetes 部署工具中发现了 KubeSphere 和 Kubekey 这个解决方案,并在集群部署和生命周期管理方面进行了深度的测试,主要围绕下面一些维度:

通过测试,发现 KubeSphere+Kubekey 在各个方面都更加契合当初对管理平台的需求,为此采用 KubeSphere+Kubekey 来搭建了自研业务(运营类为主)的一套 Kubernetes 集群以及管理平台。
基础设施以自己的机房虚拟化集群为基础,并使用虚拟机来构建 Kubernetes 集群。在集群规划方面,分为两个生产集群,分别用于内容生产业务和运营业务。对于内容生产业务集群,更注重稳定性,因此采用了 1.21 版本。而对于运营业务集群,在追求相对稳定的基础上,还跟进了一些新版本特性,采用了 1.23 版本。同时在运营业务集群会先行实践一些新版本的特性积累经验,以便为将来升级内容生产业务集群打好基础。当然,无论是哪个集群,每次进行相应的升级和维护之前,都会创建一个临时的测试集群,以进行相关操作的测试和验证。

这里以 1.23 版本的 K8s 集群为例,介绍下部署的环境。
资源清单:
| 节点名称 | 配置 | 角色 | 系统 |
|---|---|---|---|
| k8s-master1 | 4C 8G 200G | 控制平面节点、etcd | Debian 11 |
| k8s-master | 4C 8G 200G | 控制平面节点、etcd | Debian 11 |
| k8s-master3 | 4C 8G 200G | 控制平面节点、etcd | Debian 11 |
| k8s-node1 | 16C 32G 200G | 工作节点 | Debian 11 |
| k8s-node2 | 16C 32G 200G | 工作节点 | Debian 11 |
| k8s-node3 | 16C 32G 200G | 工作节点 | Debian 11 |
| k8s-node4 | 16C 32G 200G | 工作节点 | Debian 11 |
| k8s-node5 | 16C 32G 200G | 工作节点 | Debian 11 |
| k8s-harbor | 4C 8G 500G | 镜像仓库 | Debian 11 |
| gitlab | 8C 16G 200G | 代码仓库 | Debian 11 |
| gitrunner | 8C 8G 200G | CI/CD | Debian 11 |
| k8s-lb1 | 4C 8G 100G | 负载均衡、DNS | Debian 11 |
| k8s-lb2 | 4C 8G 100G | 负载均衡、DNS | Debian 11 |
| proxy1 | 8C 16G 100G | 业务访问反向代理 | Debian 11 |
| proxy2 | 8C 16G 100G | 业务访问反向代理 | Debian 11 |
全部服务器均采用本地虚拟化平台的虚机方式提供。
为了实现 K8s 集群对外业务的访问,使用了两台 OpenResty 服务器,并通过反向代理模式将流量分发到 K8s 集群中的各个工作节点的 Ingress NodePort 端口。为了保证高可用性对 OpenResty 服务器进行了双活部署。同时使用 OpenResty 实现了配置的热更新、限流和安全防护功能。此外,还在 OpenResty 上统一了全局的 SSL 证书管理,以简化在 K8s 集群中分散部署 SSL 证书带来的管理复杂度。通过这些措施,能够更加高效地管理 Kubernetes 集群对外的业务访问。
为了实现 K8s 集群管理的高可用性,使用 Keepalived 和 HAProxy 部署了 1 个高可用负载均衡服务,用来实现后端 3 台 master 节点 API server 的对外统一暴露。此外,也搭建了一套 dnsmasq 用于提供各个节点的 DNS 解析服务,以便于解析一些内部服务的域名。这样,可以确保 Kubernetes 集群的 API server 能够持续提供服务,并且内部服务的域名能够得到正确的解析。
根据业务需求,需将较多传统的虚机业务迁移到容器化环境下,因此对 K8s 集群的存储方案进行了深入了解。目标是充分利用现有的硬件基础,同时尽可能简化架构并降低运维成本。因此,在底层存储方面,使用现有专业的硬件 NAS 存储和基于 vSphere 的 Cloud Native Storage(CNS),以应对不同的数据持久化场景。

为了解决多个 Deployment 同时读写的应用的存储问题,采用了基于 nfs-subdir-external-provisioner 的 storageclass 存储类,或直接在 Pod 内挂载 nfs volumes 的形式。然而,我们也意识到 NFS 存储在某些应用场景下可能不兼容并存在性能问题。因此,针对只需要 ReadWriteOnce 访问类型且对性能要求较高的数据持久化场景,例如数据库和缓存,采用了虚拟化环境自带的 vSphere 的 CNS 来实现 storageclass 存储类。这极大地简化了存储解决方案的复杂度。

作为广电宣传应用对整个平台稳定性的要求较高,在日常的运维中对可观测性关注度较高,最初采用了 Prometheus-operator 套件和 Grafana 进行集群资源监控,同时使用 Netdata 进行配合。对于应用日志方面,则采用了 Loki、Promtail 和 Grafana 进行处理。但在应用中发现,这个方案在集群内应用管理方面的结合性不够强,存在一些使用上的割裂。在体验了 KubeSphere 提供的整体监控和日志方案后,果断决定切换到 KubeSphere 上。这样做解决了之前各个系统之间的割裂问题,实现了集群+应用的管理、监控和日志的一体化。

在 Devops 方面,采用了 GitLab CI/CD 的方案。研发只需要提交代码并打上 tag,GitLab 会自动生成相应的 jobs。然后,通过 GitLab Runner 运行相应的脚本,实现打包、镜像推送等操作,并通过特定的 tag 名称触发 API 修改线上应用的镜像 tag,从而实现自动部署。
相较于以前的 Kubernetes 集群管理方式,使用 KubeSphere 后我们实现了:
在应用 KubeSphere 后,不再需要手动安装和配置 Kubernetes 集群,因为 KubeSphere 提供了 KubeKey 工具实现了一键式的部署和升级功能,这使得可以快速创建和管理集群。此外,KubeSphere 还提供了基于 Helm 和 Operator 的应用管理,可以更加方便地部署和管理应用。
在实际应用业务中,需要同时管理多个 Kubernetes 集群。在应用 KubeSphere 后,可以将多个 Kubernetes 集群统一管理,从而更加方便地进行操作和监控。此外,KubeSphere 还提供了集群间的应用镜像复制和调度,使得可以在多个集群之间灵活地部署应用。
在业务中需要对不同的用户和团队进行访问控制管理和资源分配。在应用 KubeSphere 后,可以通过创建租户来实现对企业空间的访问控制和资源分配,从而更加灵活地管理业务。
在之前,需要分别使用不同的日志和监控工具后台来管理集群和应用。在应用 KubeSphere 后,我们可以使用 KubeSphere 提供的统一日志和监控平台来管理集群和应用,可以更加方便地查看和分析数据。
在我们的业务中,应用治理是非常重要的一部分。在应用 KubeSphere 后,可以使用 KubeSphere 提供的应用治理组件,例如灰度发布和流量管理,来更加方便地管理应用。这样,可以降低应用治理的使用成本,提高效率。
结合广电应用实际,在 KubeSphere 应用方面,有以下后期计划:
目前使用 KubeSphere 的过程中,发现与其他产品相比,KubeSphere 更注重于应用场景化和简化的管理后台路线,这对于新人来说更加友好。但是一些有基础的人员在接触初期阶段可能会感到后台一些配置项与 Kubernetes 资源对应上存在一些不知所措,操作繁琐。另外,发现一些 Kubernetes 资源的配置目前还无法在后台完全控制,需要通过手动编辑 YAML 来实现。因此,希望在未来的版本中能够改进这些问题。
本文由博客一文多发平台 OpenWrite 发布!
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵
其实做自媒体的成本并不高,入门只需要一部手机即可!在手机上找视频素材、使用手机剪辑视频、最后使用手机发布视频作品获得收益!方法并不难,今天这期内容就来给粉丝们分享一种小方法,每天稳定收益100-300,抓紧点赞收藏!1、找素材(1)使用手机拍摄自己喜欢的经典段落,使用程序把文案内容提取出来(2)也可以在豆瓣、知乎、微博等网站中找一些自己需要的文案素材(3)把文案进行润色修改,可以加入一些自己的观点(4)视频素材可以使用软件中自带的素材,也可以在素材网站中下载完整版的素材2、文案配音(1)把复制好的文案直接导入小程序中(2)调整音色、音调后一键合成音频即可(3)可以选择自己朗读配音,需要花一点时
我认为我的问题最好用一个例子来描述。假设我有一个名为“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
参见下面的示例,我想最好使用第二种方法,但第一种也可以。哪种方法最好,使用另一种的后果是什么?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)如果我想为成千上万的用户存储此类信息,它就无法工作。推荐的方法是什么?我希望能够在这些服务之上构建一个界面,因此每次用户进行交易时都必须输入凭据是不可行的。
目录SpringBootStarter是什么?以前传统的做法使用SpringBootStarter之后starter的理念:starter的实现: 创建SpringBootStarter步骤在idea新建一个starter项目、直接执行下一步即可生成项目。 在xml中加入如下配置文件:创建proterties类来保存配置信息创建业务类:创建AutoConfiguration测试如下:SpringBootStarter是什么? SpringBootStarter是在SpringBoot组件中被提出来的一种概念、简化了很多烦琐的配置、通过引入各种SpringBootStarter包可以快速搭建出一
我正在使用Devise在Rails应用程序中,并希望通过API公开一些模型数据,但应该像应用程序一样限制对API的访问。$curlhttp://myapp.com/api/v1/sales/7.json{"error":"Youneedtosigninorsignupbeforecontinuing."}很明显。在这种情况下是否有访问API的最佳实践?我更喜欢一步验证+获取数据,但这只是为了让客户的工作更轻松。他们将使用JQuery在客户端提取数据。感谢您提供任何信息!凡妮莎 最佳答案 我建议您按照以下帖子中的选项2:使用APIke
我正在开发一个Rails2.3.1网站。在整个网站中,我需要一个用于在各种页面(主页、创建帖子页面、帖子列表页面、评论列表页面等)上创建帖子的表单——只要说这个表单需要在由各种Controller)。这些页面中的每一个都显示在相应的Controller/操作中检索到的各种其他信息。例如,主页列出了最新的10篇文章、从数据库中提取的内容等。因此,我已将帖子创建表单移动到它自己的部分中,并将该部分包含在所有必要的页面中。请注意,部分POST中的表单到/questions(路由到PostsController::create——这是默认的Rails行为)。我遇到的问题是当Posts表单没有正