编辑推荐: |
本文来源壹佰案例微信公众号,本文主要介绍通过k8s运维微服务系统的实践,包括微服务架构调整、k8s部署架构、持续集成自动化、运维策略应用、k8s
POD调优五个方面。 |
|
微服务架构调整
微服务架构调整,迈向12因素应用,包括以下十个方面:
1.代码与配置分离,一份代码多个分支、多分配置。对应因素1。
2.配置文件管理服务间的依赖关系。对应因素2。
3.服务无状态。对应因素6。真正实施过程中中虽然整体功能微服务化,但有些服务由于做的时候不注意,或多或少会引入状态的存在,这时要把状态去掉。
4.通过Rest API提供服务。对应因素7。
5.去单点。对应因素8。
6.统一日志,JSON格式,输出到控制台。对应因素11。
7.单一进程。这是Docker的推荐。
8.API向前兼容,支持滚动升级。为了实现在k8s里面滚动升级的需求,无状态的服务在升级过程中都有一个短暂的新老版本并存的时期,这时流量可能进入老版本,也可能进入新版本,通过对每个API进行改造,新老版本是兼容的。
9.提供监控探针接口,支持故障节点的自动隔离。每个POD里都增加了一些探针项,这样服务器下支持哪些节点都可以灵活控制。这里存在一些泄露问题,会把它控制住,会自动隔离直到内存状态恢复正常。
10.线程池优化。我们需要引入一个手动干预的线程池来解决框架自带的线程池。
k8s高可用部署架构
k8s里主要是3台节点,横向扩展有多个,节点上同时担任两个职责。一个k8s本身有三个组件,我们把存储层跟它分享,这样就组成了一个高可用的节点。我们在节点上安装kubelet、proxy、Docker和flannel,大部分的应用业务在Nodes上,这是后台的k8s的结构。
为了支持流量访问,我们设置了多个入口。上图左边是EIP,这样方便CI/CD环境、编译集群和开发环境,能够灵活访问开发集群的服务。
另外NAT是6443,实际上最后导航到Service的也是6443,还有业务的正常访问流量,所有的暴露都是通过它来访问,同时这也是访问里面容器的一个方式。
第二部分是产品的容器化结构。我们根据产品线,在k8s的使用上通过机制将每个产品线放到里面做一个命名空间的隔离。实际的比上图展示的更多一些,这里举两个例子。比如手机平台前端通过一个流量到Nodes,web平台基于浏览器云那部分通过GPS访问web对应的服务,这部分挂在用户、产品、搜索,都是web平台的应用,我们把它们放到设计平台命名空间。
如果把每个服务放大化我们可以看到如图右侧,所有的部分都是由一个Serves来组成,这样所有的暴露都是以Serves来暴露的。
持续集成自动化
自动化发布测试流程
整体的自动化发布测试流程分为五个阶段:开发、编译、预发布、测试、部署。
1.开发阶段是由开发工程师来完成。
2.编译是持续集成,生成一个镜像包,传递到镜像仓库里。
3.预发布阶段我们做了一个预部署的发布环境,发布的容器包跟生产环境的容器包是一模一样的,但第三步先把生产的镜像在预部署的环境部署一遍,对它进行自动化测试,如果成功就进入第四步测试阶段,如果不成功就停止在第三步预发布阶段。
4.测试阶段和预发布阶段的镜像完全一致,这样确保内容一样,避免差异性的存在。
发布过程自动通知
接下来说说自动发布流程的通知机制。
整个发布流程是自动的,但所有步骤都在监控范围内,里面定义四大步:一个是成功,一个是编译、预发布、失败、部署。
对于发布的通知格式也做了定义,第一个字段是成功还是失败、介绍哪个阶段,整个通知系统对接到邮件系统和Slack。测试阶段如果失败会提示测试失败,真实操作中我们会用红色做标记。如果测试成功,之后是部署,实际操作中只有预发布和测试阶段会出现失败的可能,这个可能性比较大,所以如果到了部署阶段,基本上成功率就比较高了。
自动化测试架构
用什么方式能够确保我们发布的镜像能够做准确的测试?看看我们的自动化测试架构。
如图所示,整个测试体系在k8s里面,分为预部署、生产区和测试区,跟隔离生产线一样,我们把测试区和预部署隔离出来,最右边是正常的生产区。一个新版本发布之后,会触发预部署。
假设现在发布一个服务,通过第一步会更新预部署区的服务,它的版本号会升级,但里面有一个部署的特点是预部署区的接入服务,所有流量都会导向生产区的服务。这样一来,当接入服务发生变化,对于接入服务运行的整个自动化测试中所面临的服务的变动项只有接入服务,因为它的下游跟生产一模一样,是没有变化的。
第二步、第三步如果成功的话我们就会发布出去,对于测试还有一个比较大的问题:结果怎么保证?怎么跟CI/CD系统集成?结果保存上我们选择部署一个结果保存的容器,把ES保存在这里,同时CI/CD系统会读取ES的数据来判断这个测试有没有通过,如果通过则进行发布,如果没有通过就不往下继续。
其他所有服务的设计在预部署区,每个服务的设计都是采用类似的结构,比如发布预部署服务,直接调用生产区的搜索服务,而不是预部署区的搜索服务。
镜像编译打包机制
在存储上我们把代码和镜像分离,配置区有配置的ABCD,也是灵活创建的。在打包过程中我们定义选择的分支和配置会做分支、代码和配置的合并,最后生成一个相应的容器镜像,发布到镜像仓库里面去。这样解决了面临多套环境的问题,还可以临时解决生产环境的问题,我们会临时拉出分支,新的分支直接可以对接上线。
跨国部署的镜像分发
现在我们的web云3D在国内部署一份,在美国部署一份,分别服务国内和国际用户,CI/CD的集群在北京的机房里,这样就面临着同一个代码做异地部署的问题。
中国区我们在把镜像上传到阿里云的仓库,生产环境直接从阿里云划到二区,然后拉取镜像就可以了。最大的挑战是在美国,我们的服务器集群在美东区部署,我们有四个项目,一个在新加坡、一个在韩国、一个在日本、还有一个在美西,这都是在美东和中国之间的距离。
做技术选型的时候,我们对这四个区做了一些连续测试,测试两个阶段:
一个是从我们的机房里往四个区分发容器包,测试他们的网络、上传速度和稳定性;
另一个是下载测试,在美东区分别从四个镜像里拉取镜像包,同时观察网络延迟及网络抖动的现象。
测试发现:新加坡的稳定性明显优于其他三个地区,它的效率属于中间水平,150兆左右的数据包大概需要3分钟左右,所以我们最终选择了新加坡。
另外是配置,美东所有的发布代码配置都是来自上一页的镜像仓库,这时我们做到在上面通过选项来决定这个数据包发到哪个镜像仓库,然后部署的时候去不同镜像仓库里拉取这个镜像包。这个更改只需要一个指令,不需要代码层做特殊处理。
基础设施配合
Splunk日志集成方案
我们现在的日志处理系统是Splunk,开发或测试人员通过Splunk来分析日志。我们做过两个方案:
方案1,把日志写到控制台,这时容器是用Docker确认的,把日志写到上面,我们在每个机器上写了一个东西监控磁盘文件。
方案2,APP写日志到控制台,这和方案1是一致的,但容器改了,今年4月份,Splunk发布了它的Splunk
Server,且真实的信息能够传递到Splunk上面去。这样先把Splunk升级,然后在Splunk上配置HEEC,从效果来看能够把APP的日志放到Splunk上。
最初的时候两个方案都是可行的,后来两个方案分别运行到一定时间之后,我们发现了方案2的问题。因为任何一个系统都有不稳定性,包括Splunk
Server,它不稳定的时候会在Docker里出现大量的提示报错,同时机器不可用,我们检测到Docker的内存占用机器内存的50%左右,而正常情况下Docker进程所占的内存是兆级别,不是特别多。
错误信息力量充斥着对于阈值的信息处理,这种场景下我们切换到方案1,等它恢复之后再切换回去,这些阈值落到磁盘上,可以把磁盘的日志再重新发布到Server。
经过对比我们发现方案1对于k8s集群的稳定性更好,方案2对于运行期的集群会出现大量消耗内存的问题。如果启动POD时发现POD本身启动不起来,它会提示初始化不成功连不到Splunk服务器,这个POD启动不了,对于业务的应用影响非常严重,所以切换方案1。我们k8s的高可用性及稳定性和Splunk是解耦的,避免日志丢失和重复。
监控报警方案
我们从三个维度去监控:
1.基础监控,借助于灾备机制,对机器层及上面运行的Docker进程进行监控。
2.Web监控,以应用的角度监控主要的登录服务、产品服务能不能正常工作。
3.容器监控。
在报警上我们现在主要是基于灾备报警,能够把基础监控和Web监控用报警报出来。
安全
所有的访问都是通过安全来进行的。
1.证书,通过自有的证书。
2.k8s Service Account,主要是隔离,给每个不同的服务、不同的部门做一个权限的控制。
3.HTTPS,主要指Web流量,访问k8s的时候全部通过HTTPS来访问。
k8s POD调优
k8s 资源配置实践主要包括以下六个方面:
1.使用deployment管理POD。
2.通过service暴露服务。
3.通过升级策略实现滚动升级和扩降容时流量不丢失。
4.通过资源限额遏制资源过度消耗和资源故障传递。
5.通过探针自动隔离故障POD。
6.停止容器时保护最后流量。
|