edwin1986
作者edwin1986·2018-10-23 15:58
系统架构师·上汽通用汽车

某汽车主机厂容器最佳实践——实践历程

字数 5040阅读 5899评论 2赞 7

1.整体实践历程

1.1 架构重定义

我司早期使用巨石架构和瀑布模型进行应用构建,以应对建设之初的稳态业务需求。随着我司的发展,业务变得愈发敏捷和灵活。应对敏态需求,我司开发团队在架构上逐步采用TOGAF(即The Open Group Architecture Framework)价值链相关方法论进行业务解构,将传统汽车整车厂长业务链业务逐步切分为短业务模块。
所谓TOGAF,其基础是参考美国国防部的信息管理技术架构(TAFIM,即Technical Architecture for Information Management)。其通过一套不断迭代的过程模型,支持企业的最佳实践,并且使企业或组织据此可以设计、评估、并建立组织的正确架构。TOGAF的关键是使用一个有效可靠的架构开发方法(ADM,Architecture Development Method)来发展能够满足商务需求的企业架构。
我司做了第一件事,就是架构重定义。通过架构重定义,明确业务需求的真实方向。对于开发人员而言,往往只知道根据业务需求进行系统实现,但对于这个需求的初衷、所要达到的目标却未必清楚。当一个需求被提出,如果不明确目标和范围、以及相关利益相关者的诉求,在具体落地时就可能南辕北辙。
我们通过价值链区分了基本业务、管理业务和运营业务。比如4S店针对潜在客户的售前营销活动就属于基本业务,4S店用来预测本月销量的管理预测报表就属于管理业务,4S店维修技师为了了解维修案例所查询的维修案例知识库就属于运营业务。通过业务和受众的不同进行泳道聚合,并最终通过四色模型和U/C矩阵聚合成系统。
tv1j5a96vqsy

tv1j5a96vqsy

接下来,我们做了不同开发团队技术堆栈的对齐。降低运营成本。我司目前使用Java为主的开发堆栈。具体堆栈主要用于支撑无状态应用服务为主,包括HTML5、Angular及Primeng等前端主流框架及配套自定义开发组件。在后端服务层上,主要以Spring为主,配合Jersey等MVC实现及相关自开发组件。
gr6vx0hrhntd
gr6vx0hrhntd

从技术堆栈上看,我司已经实现了无状态应用。但随着业务的模块化和微服务化,逐步开始呈现出如下的特点:

  • (微)服务化
  • API接口
  • 多种开发语言
  • 多种数据库技术
  • 异步式消息接口
  • 云平台
  • 大数据平台
  • 移动应用

随着企业架构复杂度提高,各类应用部署和维护将随着架构复杂度的提高变得愈发复杂,由于生产变更而导致的准备和维护各种架构环境将花费大量时间,管理成本不断提高。对运维人员而言,伴随着高速的系统迭代,遗留系统升级和迁移将变为异常困难,维护总是需要小心翼翼的实施并反复验证确认。
因此,随着Docker的出现,标准化镜像和容器实例的无状态化正好解决了如上问题。通过“固化小集装箱”的构建和部署,使得运维人员只需要关注应用最小运行单元,而非可运行单元之下的细枝末节。

1.2 DevOps及流水线落地

DevOps联合了开发阶段和部署阶段,从项目计划、项目开发、项目构建、项目测试到运维发布、部署,以及运营、监控,形成一个循环环路。对我司而言,DevOps转型主要经历了三个阶段:
ree68fsna9gb

ree68fsna9gb

起步阶段:成本控制阶段:在这个阶段偏重控制项目风险,以进度控制为项目管理的首要目标。但漫长的项目或产品周期,使其无法及时获得用户反馈。大而全虽然感高大上,但无法保证所有功能的价值,一旦在UAT中发现问题,很大概率出现返工,往往导致用户不能及时获得自己真正想要的功能。在这个阶段,项目的内建质量通过SIT、UAT等人工测试手段以及上线期间的验证手段保证,上线往往需要半天至好几天的时间,其效率是较低的。
演进阶段:此时,我司通过文档标准化成熟度有所提升,通过了诸如CMMIIII等诸多认证。业务需求在BA、开发和测试之间以标准格式文档传递。在开发工具链上,通过CI工具完成自动化打包、QA部署工作,并通过部分自动化工具完成了某些场景的自动化测试,提高了SIT测试的效率。但与此同时在这个阶段,团队之间缺乏沟通,或多或少存在理解不一致问题。对于测试而言只到某个阶段才进入反馈问题。整理回归成本高。运维工单式操作存在等待浪费,手工操作且对应用的熟悉程度不高。
成熟阶段:这个阶段项目交付团队已经有一定成熟度,可以自行进行受控的开发、交付和运营。故在这个阶段侧重与为软件的发布创建一个可重复且可靠的过程,通过标准化、自动化、平台化和数据化的实现,构建统一的DevOps平台。在交付模型上由于应用交付一般涉及应用、脚本、配置文件、中间件、运行时和操作系统6大类。通过将这些对象的抽象标准化,可规范化应用的发布过程。对于每次部署的应用影响范围也一目了然,同时,通过该模型的构建,也便于应用容器化迁移。
kb3suff06tdf
kb3suff06tdf

归根结底,对于敏捷团队而言,需要解决如下几点诉求:

  • 提升敏捷开发能力。传统虚拟机部署方案复杂,需要标准化的部署方案加快部署速度和部署结果反馈。
  • 建立开发测试甚至生产环境一致性。 传统虚拟机部署需要自行定义环境和配置,这样导致开发、测试、生产环境一致性较差,需要通过规范化模板和容器镜像实现此要求。
  • 实现应用全生命周期自动化管理。传统虚拟机基础平台与应用存在较大GAP,这样导致应用的生命周期管理需要依赖外部方案。
  • 弹性伸缩、灰度发布等。 传统虚拟机横向扩充较为困难,难以快速实现弹性伸缩和灰度发布。

2.容器云整体架构

平台基于某Kubernetes版本构建。由于Kubernetes本身基于ETCD节点的特性并不推荐多数据中心单集群架构,因业务涉及多数据中心场景,故在每个数据中心(节点)独立不是一套Kubernetes环境。最终构建了包含2套QA环境和3套PROD环境的多集群容器架构。这些集群物理和逻辑上均是独立的,作为资源池可通过未来CSP进行统一整合。
qd04aov9c5fm

qd04aov9c5fm

  • 主节点:构建Master集群用于支持管理节点高可用。
  • 镜像仓库:构建Registry服务集群用于支持容器仓库服务高可用。
  • 配套设施:构建Infra集群节点用于支持EFK日志服务高可用。
  • 入口服务:由于需要同时支持内外网访问,平台还构建了Inner Route和Outer Route用于区分内外部流量。在DMZ设置了单独的反向代理,用于将外网请求转发至Outer Route。

具体架构参考下图所示:
w8sxd1yqorfu

w8sxd1yqorfu

具体BOM如下表所示:
318xy7z8hood
318xy7z8hood

3.容器云关键组件注意点

由于Kubernetes平台本身开源,其官方推荐的架构和部署方案这里就不再赘述,具体可参考https://kubernetes.io/docs/setup/pick-right-solution/。下面,我就我司期间的部署注意点及最佳实践作简要介绍。

3.1 Master及高可用

平台Master节点构建了3个节点,通过网络LB实现HA。每个节点运行一个ETCD服务。需要注意的是,需要保证所有计算节点和所有Master节点之间的网络通信正常。具体可参考:https://kubernetes.io/docs/setup/independent/high-availability/
yorereglee96

yorereglee96

3.2 Route及高可用

关于Route,与传统开源Kubernetes的Ingress不同,其是某基于Kubernetes二次开发平台自身的实现,用于外部访问容器集群内部Service,可支持HTTP(S)协议。
由于HTTP(S)应用对外发布需要经过Route,处于方便可以定义*.in/outapps.yourdomain.com的DNS泛解析记录,将其指向Route的VIP即可。这样,你可以直接在Route对象中定义任意满足该规则的域名,即可自动通过DNS访问到对应服务。当然你可以单独设置一个域名,将其DNS指向Route VIP,这也可以正常工作。
由于架构上区分了内网流量和外网流量,二者通过不同的Route集群实现。故需要在Route节点上进行标记,用于区分内网Route或外网Route。这样当涉及内/外网应用发布时,只需要在Route对象中定义Router=XXrouter即可。
mr3soaohd8vc

mr3soaohd8vc

0odlmnmz5f6ve
0odlmnmz5f6ve

3.3 NodePort及HostPort

对于某些TCP协议的应用需要外部访问,Kubernetes支持 NodePort和HostPort方式暴露服务/应用实例端口。
NodePort可参考:https://kubernetes.io/docs/concepts/services-networking/service/#nodeport。 另外,平台默认使用30000-32767作为NodePort备选端口,一旦使用了NodePort,容器计算集群中所有宿主机的该端口都会被占用,对其的访问也会被转发至对应Service。
其可以通过外部管理手段进行端口管理及预分配,避免端口冲突导致的应用部署失败。另外,根据NodePort的实现方式,其能保证在宿主机服务可用的情况下将流量转发给远端的某个Pod,但如果其本身不可用,流量将Block在该服务器上。因此,对于其的HA需要通过多台服务器LB实现(留意session粘连的问题)。
HostPort可支持将容器直接绑定到宿主机某个主机端口上,以便外部访问。当然其本身也与NodePort类似需要进行端口管理和架构高可用设计(只是其端口只占用本宿主机,而非整个集群)。
另外由于平台是通过 security context constraints (SCC) 来控制 pod 的权限,与Kubernetes的(cluster)rolebinding不同。如果在平台中运行有HostPort/HostPath资源依赖的容器需要单独授权。
另外根据Kubernetes官方的Best Practices,除非运行的应用和中间件有脱离容器网络外部直接访问的需求,不然不建议使用HostPort。具体参考:https://kubernetes.io/docs/concepts/configuration/overview/

3.4 网络

平台默认使用基于Overlay网络的Open vSwitch (OVS) SDN(software-defined networking)来实现Pod和容器之间的链路通讯问题。同时其也提供了第三方网络管理插件,用来连接Cisco Contiv (™)、Juniper Contrail (™)、Nokia Nuage (™)、Tigera Calico (™)或VMware NSX-T (™)等。由于我司项目期间正处于新老数据中心ACI迁移过程中,故短期并未采用Cisco Contiv,而是直接使用OVS来实现虚拟网络。

3.5 日志

平台默认使用EFK(Elasticsearch、Fluentd和Kibana)来进行日志管理。我司由于本身已经构建了业务日志处理平台,故从方案集成上本项目同时支持了EFK的构建和企业日志平台的集成。前者部署于3个Infra节点上,基于存储持久化需求,接入了SAN。后者通过在每台计算节点上安装agent,增量读取journald的日志并上传企业日志平台。

4 最佳实践

1). 容器构建:最小化并基于提供的基础镜像进行构建。避免使用Root运行容器。具体可参考:https://kubernetes.io/blog/2016/08/security-best-practices-kubernetes-deployment/。事实上,平台应默认通过非root账号运行容器。
2). 容器调试:通过Console中的debug按钮及port-forward都是可行的方式。
3). 外部Registry及安全性。目前通过Habor构建Reigistry仓库,并提供基础镜像供开发团队进行容器打包和镜像上传。需要注意定期CVE扫描。
4). 项目安全性。基于NameSpace/Project进行隔离和独立授权。如果涉及CI/CD集成需求,可以通过service account和token授权进行独立授权。
5). CI/CD:同传统CI/CD类似,参考4。
6). 其他:对于反复性的实例部署,Template自定义和部署是非常方便的方式。

如果觉得我的文章对您有用,请点赞。您的支持将鼓励我继续创作!

7

添加新评论2 条评论

toaix1005toaix1005软件开发工程师PHT
2018-10-25 10:32
谢谢分享
大大觉迷大大觉迷网络工程师通钢
2018-10-23 16:42
先来学习一下,了解一下前沿技术。
Ctrl+Enter 发表

本文隶属于专栏

最佳实践
不同的领域,都有先行者,实践者,用他们的最佳实践来加速更多企业的建设项目落地。

作者其他文章

相关文章

相关问题

相关资料

X社区推广