大型项目的云原生迁移方案整理
Contents
项目前期的迁移工作是我在负责, 后续因为合规问题没有办法处理美国的环境, 就由其他同事继续操作完成, 这篇博客就记录下我们迁移时遇到的问题以及一些解决方案. 希望能帮助读者在多云环境下的云原生方案的提供一个思路. 我默认读者有过Docker以及Kubernetes使用经验, 以及使用它们部署过一些应用.
项目时间线
- 22年09月: 我入职时 老板告诉我有一项工作是将我们的项目从Mesos集群迁移到Kubernetes集群
- 23年04月: 开始梳理所有的报警规则, 整理日志以及其他数据上报的链路
- 23年06月: 迁移前的计划与筹备, 并且尝试从零搭建服务
- 23年10月: 全球第一个区域迁移成功, 后续并行迁移多个区域
- 24年01月: 海外地区除美国外全部迁移成功, 我休了很久的年假, 直到春节假期结束, 非常开心
- 24年03月: 迁移工作由其他同事接手, 开始美国区域的迁移
- 24年07月: 美国部分完成迁移, 海外的所有环境均迁移至Kubernetes集群
前置工作
下面这些内容其实很虚, 但又十分必要. 必要性在于, 你要告诉老板, 告诉同事, 告诉合作部门. 整个迁移的成功率在90%以上, 而且遇到了问题能够有拖底的解决方案.
梳理现有环境
要梳理的内容主要包括: 监控报警, 迁移范围
我们一般将报警按照是否有Player Impact进行区分, 为了整个迁移过程要保证用户无感. 报警梳理这部分工作我做了挺久的, 主要是确认数据源, 数据上报链路, 有些时候直接去看后端代码, 确认下具体的报警逻辑.
Demo环境搭建以及验证
这部分直接决定着我们迁移方案的选择. 虽然合作方提供了Helm Chart, 但是在具体落地时, 需要事先将可能的坑踩一遍, 才能有把握去做好方案以及应对措施.
部门协调
这部分的工作不止是为了给老板做汇报, 也是为了让合作方伙伴更加信任我们, 要让对方也觉得这个工作是有把握的.
需要给出迁移的大致时间线, 并且做好风险评估以及回滚方案.
比如, 我们的系统有区分大版本和热更, 3个月一个大版本. 那么我们在规划时间线的时候, 就要考虑大版本的时间线, 最好在两个大版本之间完成, 避免在发大版本的时候出现事故.
问题与解决方案
这里记录一些我们曾经遇到的问题, 时间过去很久, 我就凭借记忆讲讲.
流水线改造
我们原有的流水线是基于BK GUI搭建的, 每次修改都需要在页面上点点点, 而且版本控制也不好用. 基于此, 我们整套流水线改用Jenkins来实现了.
我之前写了一篇使用Groovy进行编程: 执行流程控制技巧与心得, 里面用到的并发以及重试技术基本就是整个流水线的核心了.
到目前为止, 流水线稳定运行了一年, 运行基本十分稳定且未出现重构功能这样的大改动.
我应该会再写一篇在Jenkins中如何做好流水线的单元测试以及项目规划的博客.
有状态的节点
虽然我们的业务在迁移前就已经使用了Mesos将其跑在了容器里, 但是在机器上还有几个目录是当前机器的容器都要共享的.
为此, 我们使用了两个DaemonSet
来同步机器上的这些目录文件, 但是依然存在着风险.
后来, 同事提出了一个解决方案, 新创建的Node
会带有taint
记号, 假如我们没有手动操作过这个Node
,
它就不会被投入使用. 这个问题我们至今也未完全解决, 带来的问题就是自动扩缩容迟迟没法落地.
给我带来了足够的教训, 业务一开始就不能有对有状态节点的依赖. 说人话就是, 自己把云硬盘或是volume挂进去, 别用机器上的文件夹.
AWS CNI与多网卡问题
在美国的一些服务器, 会绑定一个单独的加速IP来降低玩家的游戏延迟, 本意是为了提升用户体验. 但是同事发现在EKS集群中我们自己添加的网卡会被vpc-cni自动删掉. 他们当时没什么思路, 我说那我去读读看vpc-cni的代码吧,
被删掉的原因我找ChatGPT分析了一下代码
https://chatgpt.com/share/8e96aedc-b297-4f97-b765-267d108229f9
然后又看到了这个字段, 可以令vpc-cni
忽略我们的网卡.
1 | // eniNoManageTagKey is the tag that may be set on an ENI to indicate ipamd |
https://docs.aws.amazon.com/eks/latest/userguide/pod-multiple-network-interfaces.html https://docs.aws.amazon.com/whitepapers/latest/ec2-networking-for-telecom/multus-container-network-interface-cni.html
1 | // https://github.com/aws/amazon-vpc-cni-k8s/blob/06828cee09446fd9e501984727ed807254385cb8/pkg/ipamd/ipamd.go#L1348 |
当然可以说是我们文档读的还不够多, 不过, 能有机会简单看看基础组件的代码, 把问题解决掉, 还是很开心的.
混合云服务
我们使用的云服务业务中, 由于政策原因, 有一部分是非AWS以及腾讯云的, 我们仅仅租赁了几台物理机, 并通过专线进行组网. 针对这部分机器, 也需要添加到腾讯云的TKE中, 才能完成整体K8S的升级. 这里借助了腾讯云的注册节点. 只是网络方面稍稍不同, 我们直接用hostNetwork的方式规避了问题.
https://www.tencentcloud.com/zh/document/product/457/60282
一些思考
Terraform与IaC
我们使用Terraform是为了什么, 我觉得在使用它之前就要想清楚.
有个概念叫SSoT
(Single Source of Truth
), 对应在我们系统架构中, 它的含义是,
我们们的当前的机器是什么功能, 他们分别有什么样的任务.
在没有Terraform之前, 这部分数据可能会存储在CMDB
中, 这也是一种SSoT
, 但是CMDB
的维护是需要人工的,
也就是说, 从我们修改了一个机器的属性, 到它最后反映到CMDB
中是有一个流程的.
Terraform的存在简化了这一流程, 当我们对基建作出了改动的时候, Terraform的state就是一个SSoT
,
原有的CMDB
就可以退变成仅仅是一个展示平台.
这里我推荐使用 Teragrunt+Atlantis 的方式, 真正的将基建的修改与审批流程相结合. 从技术人员的角度讲, 这个流程太美了.
云原生问题的一些思考
Cloud Native 还是 Cloud Provider Native
在迁移结束之后, 我收到了一个任务是将原有的一部分逻辑迁移到Jenkins流水线中, 这个逻辑是到某台机器中执行一些脚本. 不知道读者能想到有哪些方案, 我直接列出来这几种, 相信肯定有你想过的:
- 使用ssh登录到机器, 执行对应的脚本, 最简单, 但是扩展性低, 而且我们机器上基本都取消ssh的服务了
- 使用AWS或是腾讯云提供的SSM/TAT服务, 调用云厂商提供的脚本执行API
- 我已经有了Kubernetes集群, 那么我可以新建一个pod, 在Jenkins执行
kubectl exec -ti xxxx run.sh
exec中时, 会保留stdoud和stderr的日志, 相当于使用Jenkins来做执行日志的保留
最后我选择了第三种, 也说服了老板, 现在它也还在这么跑着. 这是我的考虑:
- 需要区分好什么是云原生以及云厂商原生, 当我们使用了厂商提供的特有API的时候, 我们就应该问自己, 这是必要的吗?
- 需要区分业务的需求, 比如, 什么需求是来自业务的, 什么需求是来自基建的, 我们值不值得为这个需求写一层多云厂商的兼容?
全球化协作
在一个全球化的团队里其实是很幸福的. 我能想到2点,
- 你可以不太需要担心PageDuty(oncall)的问题, 美国的同事可以在我们凌晨的时候来处理问题.
- 对于美东的同事, 我们和他们正好相差12小时, 相当于CN的白天我来处理, 工作结果留好言. CN的夜晚由他们继续来做, 工作效率非常高
凌晨喊人oncall是不人道的, 运维全球化一定是趋势.
整理和总结
其实7月份我就想写这个博客了, 近期终于有时间来整理下思路. 实际的问题解决起来还是很有成就感的, 但是一定要做好记录哈哈. 不然就真的只能在写博客的时候苦苦搜寻记忆了.
Image by Freepik