我司早期使用巨石架构和瀑布模型进行应用构建,以应对建设之初的稳态业务需求。随着我司的发展,业务变得愈发敏捷和灵活。应对敏态需求,我司开发团队在架构上逐步采用TOGAF(即The Open Group Architecture Framework)价值链相关方法论进行业务解构,将传统汽车整车厂长业务链业务逐步切分为短业务模块。
所谓TOGAF,其基础是参考美国国防部的信息管理技术架构(TAFIM,即Technical Architecture for Information Management)。其通过一套不断迭代的过程模型,支持企业的最佳实践,并且使企业或组织据此可以设计、评估、并建立组织的正确架构。TOGAF的关键是使用一个有效可靠的架构开发方法(ADM,Architecture Development Method)来发展能够满足商务需求的企业架构。
我司做了第一件事,就是架构重定义。通过架构重定义,明确业务需求的真实方向。对于开发人员而言,往往只知道根据业务需求进行系统实现,但对于这个需求的初衷、所要达到的目标却未必清楚。当一个需求被提出,如果不明确目标和范围、以及相关利益相关者的诉求,在具体落地时就可能南辕北辙。
我们通过价值链区分了基本业务、管理业务和运营业务。比如4S店针对潜在客户的售前营销活动就属于基本业务,4S店用来预测本月销量的管理预测报表就属于管理业务,4S店维修技师为了了解维修案例所查询的维修案例知识库就属于运营业务。通过业务和受众的不同进行泳道聚合,并最终通过四色模型和U/C矩阵聚合成系统。
随着企业架构复杂度提高,各类应用部署和维护将随着架构复杂度的提高变得愈发复杂,由于生产变更而导致的准备和维护各种架构环境将花费大量时间,管理成本不断提高。对运维人员而言,伴随着高速的系统迭代,遗留系统升级和迁移将变为异常困难,维护总是需要小心翼翼的实施并反复验证确认。
因此,随着Docker的出现,标准化镜像和容器实例的无状态化正好解决了如上问题。通过“固化小集装箱”的构建和部署,使得运维人员只需要关注应用最小运行单元,而非可运行单元之下的细枝末节。
DevOps联合了开发阶段和部署阶段,从项目计划、项目开发、项目构建、项目测试到运维发布、部署,以及运营、监控,形成一个循环环路。对我司而言,DevOps转型主要经历了三个阶段:
平台基于某Kubernetes版本构建。由于Kubernetes本身基于ETCD节点的特性并不推荐多数据中心单集群架构,因业务涉及多数据中心场景,故在每个数据中心(节点)独立不是一套Kubernetes环境。最终构建了包含2套QA环境和3套PROD环境的多集群容器架构。这些集群物理和逻辑上均是独立的,作为资源池可通过未来CSP进行统一整合。
由于Kubernetes平台本身开源,其官方推荐的架构和部署方案这里就不再赘述,具体可参考https://kubernetes.io/docs/setup/pick-right-solution/。下面,我就我司期间的部署注意点及最佳实践作简要介绍。
平台Master节点构建了3个节点,通过网络LB实现HA。每个节点运行一个ETCD服务。需要注意的是,需要保证所有计算节点和所有Master节点之间的网络通信正常。具体可参考:https://kubernetes.io/docs/setup/independent/high-availability/。
关于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即可。
对于某些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/。
平台默认使用基于Overlay网络的Open vSwitch (OVS) SDN(software-defined networking)来实现Pod和容器之间的链路通讯问题。同时其也提供了第三方网络管理插件,用来连接Cisco Contiv (™)、Juniper Contrail (™)、Nokia Nuage (™)、Tigera Calico (™)或VMware NSX-T (™)等。由于我司项目期间正处于新老数据中心ACI迁移过程中,故短期并未采用Cisco Contiv,而是直接使用OVS来实现虚拟网络。
平台默认使用EFK(Elasticsearch、Fluentd和Kibana)来进行日志管理。我司由于本身已经构建了业务日志处理平台,故从方案集成上本项目同时支持了EFK的构建和企业日志平台的集成。前者部署于3个Infra节点上,基于存储持久化需求,接入了SAN。后者通过在每台计算节点上安装agent,增量读取journald的日志并上传企业日志平台。
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 条评论
2018-10-25 10:32
2018-10-23 16:42