K8s 实践经验 (k8s in action)
文章简介:总结最近几年使用 k8s 的经验
背景
- ToB 项目
- 离线安装运行环境
- 容器化
- 多组件编排
基于这个背景下,公司选择使用 k8s。
rke
选择使用 rancher/rke 这个 k8s 发行版,docker/ansible 等依赖离线化处理,支持 ubuntu 20.04/ centos 7.9。
基于 kustomize 的部署
kustomize 提供了 template free 的 k8s manifest yaml 生成工具,可以简单的为 base/prod/staging 等不同的生产环境打 patch 定制不同的环境。当前会使用 helm chart 生成 yaml 文件供 helm charts 使用。此时所有的部署相关文件是在统一的一个仓库 deploy 中维护的。这种模式下每个项目都会有自己的 deploy.sh 文件,用于持续部署 patch 项目的 image。如果某个项目的部署模式变化了,要同时修改 deploy 这个仓库。两项目耦合严重。
基于 helm charts 以 app 为单位的部署
为了解决 deploy 项目与 app 项目耦合严重的问题,将deploy 中 app 的 configmap/service/deployment 等资源移动到 app 仓库中,此时 deploy 只需要引用 app 仓库的版本号/分支即可。
longhorn + nacos 系统极不稳定来源
在第一次生产验证过程中,k8s 的分布式文件存储使用了 longhorn。使用过程中会频繁的 IO error, longhorn 官方甚至列出了非常多的已知问题。在生产使用过程中会比较频繁的出现文件系统 readonly/读写延迟过高,nacos 服务规律性不可用、重启 nacos 5-10分钟,导致依赖此服务的其他所有服务长时间不可用。由于 poc 为单机版本,考虑使用本地的文件系统替换分布式文件系统。
第一次生产 POC 阶段不可复现升级过程
由于产品是 ToB 项目,产品产出物为离线安装包。在客户离线网络下安装后,会频繁的更新某个服务的镜像。急需一个稳定可复现的升级过程,方便现场离线升级,而不是每次我们产出文字版本、有歧义的升级过程文档。
古怪的 helm upgrade
第一版本升级包有一个比较神奇 helm 升级过程
|
|
app 的 values 经过重构后,很容易出现 values结构变化,变化的化,需要如此人工写新的升级逻辑
|
|
导致升级维护困难
改进后的 helm upgrade
使用 IaC 的思路,将所有的基础设施都在仓库中维护,将所有 values.yaml 也要放到升级包中,而不是 charts 放到仓库,values 使用生产中的
|
|
为了保证 values.yaml 部分值需要依赖生产环境,values.yaml 是一种 template 比如 golang 的 template,使用新的工具基于当前生产环境中的 deploy-env configmap 生成, 其他所有部分都放到 gitlab 中维护。
|
|
最终所有的升级打包过程会变成:
- 从 gitlab 中下载所有的 charts
- charts + values 渲染出 k8s manifest yaml, 从其中提取出 docker img,并下载下来
最终所有的升级过程变成:
- skopeo copy file docker://host/xxx
- 遍历所有 apps,渲染 values.yaml.tmpl, helm upgrade
选择更简单的架构,k3s 改造
rke 的 k8s 发行版依赖 docker,docker 需要自己安装。当前的实现中需要使用发行版中的 docker 依赖树。客户场景需要支持很多不同中 linux 发行版,适配不同的发行版成本搞。搭上 k3s 的顺风车,单文件启动兼容 k8s 的服务,其余组件已经容器化,安装过程简化了很多适配 linux 发行版的过程。
k8s 集群回归
- 集群部署
- 文件系统采用本地存储,要求应用层面的副本机制保证服务数据不丢: rancher/local-path-provisioner
总结
- 小集群(<=50节点)k3s 真的很香,80% 企业的服务都是少于 50节点的(未实际统计,凭当前简单的企业集群数量估算)
- 分布式文件系统真的太理想化了,当前测试发现 longhorn 尽量不要在生产使用,除非他真的适合你的场景
- IaC 在运维场景为我们省去了太多后期维护的麻烦事,能用就用,不能用也要想方设法使用