摘要:容器化,最初只是一个愿景。在这一想法正式提上日程之后,我们是如何一步一步走过去的?踩过哪些坑,又有何种经验,这篇文章或许能给后来者一点启发。
为什么要做容器化部署,这就不得不提到集团业务的快速发展。
2020年年初,已经持续开发多年的集团业务后台部署,呈现出的现状是——各种微服务及离线任务数量庞大,通过传统虚拟机方式部署,日常维护占用了运维和开发大量精力。得益于前期.net core迁移,当时已有一大半的应用迁移到了.net core,通过jenkins部署在linux服务器,其余的应用通过jenkins部署在windows服务器。由于操作系统不同、业务隔离等因素,硬件资源使用率不一,造成极大浪费。另外业务处于快速发展阶段,各种微服务持续增加,每当有新的微服务上线,需要运维和开发反复沟通,不仅效率低下,也极易出错。
容器化最初只是一个愿景,由于没有专门的团队进行调研和维护,同时作为业务团队还有工作任务要做,因此我们要考虑如何快速的搭建容器平台,尽量避免走自研这条路;同时考虑到团队成员基本没有容器化的经验,如何屏蔽kubernets过高的学习门槛,也是一个巨大的挑战。在经历了一年的容器化之旅后,分享下我们这一年所踩过的坑和获得的经验。
集群方案
在容器化初期,整个业务线还有大量的.net framework项目没有迁移到.net core,最初的想法是,通过windows/linux混合集群进行部署;但因为我们的终极目标是全部转到.net core,并且混合集群有一些限制,也更难维护,最终我们还是采用了多集群的方案,windows集群和linux集群独立,集群间通过外部的Nginx通信。
.Net容器化
按照最初制定的规则,容器化尽量不修改业务代码;.net core的容器化,还是相当顺利的,遇到一些小问题也有很多解决方案;.net framework的容器化相对而言,会困难一些,特别是遇到问题后,根本找不到解决方案,只能凭经验来解决;基于以上的原因,在容器化的同时,我们也将更多的应用迁移到了.net core,到容器化结束,windows kubernets集群仅保留了少量周边应用。如果可能,建议各位尽可能把.net framework迁移到.net core,尽量使用linux kubernets集群。顺便吐槽一下windows镜像,居然达到了10G,不忍直视。
Service mesh
在调研阶段,针对service mesh也进行了大量的尝试,不得不承认,service mesh是一种更彻底的微服务方案,无代码的入侵的sidecar模式,框架的灵活度更高。不过尝试了istio之后,最后还是放弃了这种方案,主要基于以下几点:
1. 稳定性和可靠性有待大公司验证;
2. 更加复杂,难以定位问题;
3. 相对k8s的原生方案,更加难以理解,团队成员没有这方面经验。
容器平台
由于整个团队对于容器化的经验基本为零,所以我们需要借助一些容器化管理平台进行kubernets的管理。通过对rancher、openshift、kubesphere等容器化平台的调研,根据社区活跃度和成熟度,最终选择了rancher,并基于rancher的流水线做了CICD,摒弃了先前人工维护的jenkins方案。
微服务
早期我们采用了consul+traefik作为服务发现和负载均衡,迁移到k8s,是否保留原方案,我们也进行了讨论。由于我们是多集群方式,集群内ip跨越集群无法通信,使用consul+traefik这种方式,无法屏蔽集群间的差异性,最终我们还是放弃了原方案,采用k8s的服务发现机制。暴露集群内服务统一采用ingress,集群间通信使用集群外的负载均衡进行转发。
存储
在容器化之前,团队针对不同的业务场景,使用了多种存储协议samba、ftp、nfs等;容器化趋于尾声之际,为了简化应用使用存储的方式,集群内引入动态pv/pvc,老的应用逐步换成pvc的方式。
监控
集群监控得益于rancher的强大功能,并没有浪费我们太多时间,采用rancher自带的Prometheus+Grafana方案;在容器化之前,通过ELK采集负载均衡(nginx/traefik)的日志,能很方便的进行微服务间的链路跟踪,容器化之后,由于微服务之间通过k8s自带的service进行通信,微服务间的调用变的难以监控,适时引入了skywalking做微服务的链路跟踪。应用日志继续使用ELK方案,并对日志进行异常监控。
迁移
为了保证能平滑的进行容器化迁移,制定了一些规则:
1. 容器化尽量不修改业务代码;
2. 逐个迁移,先迁移一些周边项目。
实际迁移时,针对不同级别的项目,采用不同的流程:
1. 针对周边应用,采用蓝绿发布,保留集群外应用,同时在集群内上线新版本,逐步将流量切到集群内;
2. 针对一些重要模块,采用灰度发布的方式,逐步将流量切换到集群内;
3. 针对一些特别核心的模块,使用镜像流量和灰度发布相结合的方式。
经过前期调研和培训之后,在不耽误现有开发进度的基础上,团队保持着渐进式迁移的节奏,历时半年,完成了整个容器化的工作。
收获
1. 采用CI/CD使整个发布流程更加流畅,可靠性也更高,并且极大的减少了团队间的无效沟通;
2. 通过docker容器,开发的交付物更加标准化,也增强了透明度和责任制;
3. 每个业务模块可以根据自身的负载进行扩容缩容;
4. 通过namespace进行业务隔离,服务器资源得到了充分利用;
5. 得益于k8s完善的容错机制,出现硬件及网络故障能快速恢复。
结语
迁移至kubernets后,线上已稳定运行一年,团队成员也对容器化有了很深入的了解。尽管迁移过程历尽周折,但是面对长期维护的项目,不仅要活在当下,也要展望未来。