黄沙百战穿金甲,不破楼兰终不还。这篇文章主要讲述vivo大规模 Kubernetes 集群自动化运维实践相关的知识,希望能为你提供帮助。
作者:vivo 互联网服务器团队-Zhang Rong一、背景随着vivo业务迁移到K8s的增长,我们需要将K8s部署到多个数据中心。如何高效、可靠的在数据中心管理多个大规模的K8s集群是我们面临的关键挑战。kubernetes的节点需要对OS、Docker、etcd、K8s、CNI和网络插件的安装和配置,维护这些依赖关系繁琐又容易出错。以前集群的部署和扩缩容主要通过ansible编排任务,黑屏化操作、配置集群的inventory和vars执行ansible playbook。集群运维的主要困难点如下:
- 需要人工黑屏化集群运维操作,存在操作失误和集群配置差异。
- 部署脚本工具没有具体的版本控制,不利于集群的升级和配置变更。
- 部署脚本上线需要花费大量的时间验证,没有具体的测试用例和CI验证。
- ansible任务没有拆分为模块化安装,应该化整为零。具体到K8s、etcd、addons的等角色的模块化管理,可以单独执行ansible任务。
- 主要是通过二进制部署,需要自己维护一套集群管理体系。部署流程繁琐,效率较低。
- 组件的参数管理比较混乱,通过命令行指定参数。K8s的组件最多有100以上的参数配置。每个大版本的迭代都在变化。
二、集群部署实践2.1 集群部署介绍主要基于ansible定义的OS、Docker、etcd、k8s和addons等集群部署任务。主要流程如下:
1.Bootstrap OS上面看到是集群一键部署关键流程。当在多个数据中心部署完K8s集群后,比如集群组件的安全漏洞、新功能的上线、组件的升级等对线上集群进行变更时,需要小心谨慎的去处理。我们做到了化整为零,对单个模块去处理。避免全量的去执行ansible脚本,增加维护的难度。针对如Docker、etcd、K8s、network-plugin和addons的模块化管理和运维,需提供单独的ansible脚本入口,更加精细的运维操作,覆盖到集群大部分的生命周期管理。同时kubernetes-operator的api设计的时候可以方便选择对应操作yml去执行操作。集群部署优化操作如下:
2.Preinstall step
3.Install Docker
4.Install etcd
5.Install Kubernetes Master
6.Install Kubernetes node
7.Configure network plugin
8.Install Addons
9.Postinstall setup
(1)K8s的组件参数管理通过ConmponentConfig\\??[1??\\]提供的API去标识配置文件。
- 【可维护性】当组件参数超过50个以上时配置变得难以管理。
- 【可升级性】对于升级,版本化配置的参数更容易管理。因为社区一个大版本的参数没有变化。
- 【可编程性】可以对组件(JSON/YAML)对象的模板进行修补。如果你启用动态kubelet配置选项,修改参数会自动生效,不需要重启服务。
- 【可配置性】许多类型的配置不能表示为key-value形式。
- 使用kubeadm对K8s集群的生命周期管理,减少自身维护集群的成本。
- 使用kubeadm的证书管理,如证书上传到secret里减少证书在主机拷贝的时间消耗和重新生成证书功能等。
- 使用kubeadm的kubeconfig生成admin kubeconfig文件。
- kubeadm其它功能如image管理、配置中心upload-config、自动给控制节点打标签和污点等。
- 安装coredns和kube-proxy addons。
- 使用ansible自带模块处理部署逻辑。
- 避免使用hostvars。
- 避免使用delegate_to。
- 启用–limit 模式。
- 等等。
(1)语法测试:
(2)集群部署测试:
- ansible-lint
- shellcheck
- yamllint
- syntax-check
- pep8
(3)性能和功能测试:
- 部署集群
- 扩缩容控制节点、计算节点、etcd
- 升级集群
- etcd、Docker、K8s和addons参数变更等
这里利用了GitLab、gitlab-runner\\??[2??\\]等开源软件构建了CI流程。
- 检查kube-apiserver是否正常工作
- 检查节点之间网络是否正常
- 检查计算节点是否正常
- K8s e2e测试
- K8s conformance 测试
- 其他测试
详细的部署步骤如下:
- 在K8s集群部署gitlab-runner,并对接GitLab仓库。
- 在K8s集群部署Containerized-Data-Importer (CDI)\\??[4??\\]组件,用于创建pvc的存储虚拟机的映像文件。
- 在K8s集群部署kubevirt,用于创建虚拟机。
- 在代码仓库编写gitlab-ci.yaml\\??[5??\\], 规划集群测试矩阵。
文章图片
如上图所示,当开发人员在GitLab提交PR时会触发一系列操作。这里主要展示了创建虚拟机和集群部署。其实在我们的集群还部署了语法检查和性能测试gitlab-runner,通过这些gitlab-runner创建CI的job去执行CI流程。具体CI流程如下:
1.开发人员提交PR。
2.触发CI自动进行ansible语法检查。
3.执行ansible脚本去创建namespace,pvc和kubevirt的虚拟机模板,最终虚拟机在K8s上运行。这里主要用到ansible的K8s模块\\??[6??\\]去管理这些资源的创建和销毁。
4.调用ansible脚本去部署K8s集群。
5.集群部署完进行功能验证和性能测试等。
6.销毁kubevirt、pvc等资源。即删除虚拟机,释放资源。
文章图片
如上图所示,当开发人员提交多个PR时,会在K8s集群中创建多个job,每个job都会执行上述的CI测试,互相不会产生影响。这种主要使用kubevirt的能力,实现了K8s on K8s的架构。kubevirt主要能力如下:
- 提供标准的K8s API,通过ansible的K8s模块就可以管理这些资源的生命周期。
- 复用了K8s的调度能力,对资源进行了管控。
- 复用了K8s的网络能力,以namespace隔离,每个集群网络互相不影响。
- kubernetes controller
- 部署或者管理一个应用,如数据库、etcd等
- 用户自定义的应用生命周期管理
3.2 Kubernetes-Operator CR 介绍
- 部署
- 升级
- 扩缩容
- 备份
- 自我修复
- 等等
文章图片
kubernetes-operator的使用很多自定义的CR资源和控制器,这里简单的介绍功能和作用。
【ClusterDeployment】: 管理员配置的唯一的CR,其中MachineSet、Machine和Cluster它的子资源或者关联资源。ClusterDeployment是所有的配置参数入口,定义了如etcd、K8s、lb、集群版本、网路和addons等所有配置。
【MachineSet】:集群角色的集合包括控制节点、计算节点和etcd的配置和执行状态。
【Machine】:每台机器的具体信息,包括所属的角色、节点本身信息和执行的状态。
【Cluster】:和ClusterDeployment对应,它的status定义为subresource,减少
clusterDeployment的触发压力。主要用于存储ansible执行器执行脚本的状态。
【ansible执行器】:主要包括K8s自身的job、configMap、Secret和自研的job控制器。其中job主要用来执行ansible的脚本,因为K8s的job的状态有成功和失败,这样job 控制器很好观察到ansible执行的成功或者失败,同时也可以通过job对应pod日志去查看ansible的执行详细流程。configmap主要用于存储ansible执行时依赖的inventory和变量,挂在到job上。secret主要存储登陆主机的密钥,也是挂载到job上。
【扩展控制器】:主要用于扩展集群管理的功能的附加控制器,在部署kubernetes-operator我们做了定制,可以选择自己需要的扩展控制器。比如addons控制器主要负责addon插件的安装和管理。clusterinstall主要生成ansible执行器。remoteMachineSet用于多集群管理,同步元数据集群和业务集群的machine状态。还有其它的如对接公有云、dns、lb等控制器。
3.3 Kubernetes-Operator 架构
文章图片
vivo的应用分布在数据中心的多个K8s集群上,提供了具有集中式多云管理、统一调度、高可用性、故障恢复等关键特性。主要搭建了一个元数据集群的pass平台去管理多个业务K8s集群。在众多关键组件中,其中kubernetes-operator就部署在元数据集群中,同时单独运行了machine控制器去管理物理资源。下面举例部分场景如下:
场景一:
当大量应用迁移到kubernets上,管理员评估需要扩容集群。首先需要审批物理资源并通过pass平台生成对应machine的CR资源,此时的物理机处于备机池里,machine CR的状态为空闲状态。当管理员创建ClusterDeploment时所属的MachineSet会去关联空闲状态的machine,拿到空闲的machine资源,我们就可以观测到当前需要操作机器的IP地址生成对应的inventory和变量,并创建configmap并挂载给job。执行扩容的ansible脚本,如果job成功执行完会去更新machine的状态为deployed。同时跨集群同步node的控制器会检查当前的扩容的node是否为ready,如果为ready,会更新当前的machine为Ready状态,才完成整个扩容流程。场景二:
当其中一个业务集群出现故障,无法提供服务,触发故障恢复流程,走统一资源调度。同时业务的策略是分配在多个业务集群,同时配置了一个备用集群,并没有在备用集群上分配实例,备用集群并不实际存在。3.4 Kubernetes-Operator 执行流程
有如下2种情况:
1.其它的业务集群可以承载故障集群的业务,kubernetes-operator不需要执行任何操作。
2.如果其他业务集群不能承载故障集群的业务。容器平台开始预估资源,调用kubernetes-operator创建集群,即创建clusterDeployment从备机池里选择物理机器,观测到当前需要操作机器的IP地址生成对应的inventory和变量,创建configmap并挂载给job。执行集群安装的ansible脚本, 集群正常部署完成后开始业务的迁移。
文章图片
- 集群管理员或者容器平台触发创建ClusterDeployment的CR,去定义当前集群的操作。
- ClusterDeployment控制器感知到变化进入控制器。
- 开始创建machineSet和关联machine 资源。
- ClusterInstall 控制器感知ClusterDeployment和Machineset的变化,开始统计machine资源,创建configmap和job,参数指定操作的ansible yml入口,执行扩缩容、升级和安装等操作。
- 调度器感知到job创建的pod资源,进行调度。
- 调度器调用K8s客户端更新pod的binding资源。
- kubelet感知到pod的调度结果,创建pod开始执行ansible playbook。
- job controller感知job的执行状态,更新ClusterDeployment状态。一般策略下job controller会去清理configmap和job资源。
- NodeHealthy感知K8s的node是否为ready,并同步machine的状态。
- addons 控制器感知集群是否ready,如果为ready去执行相关的addons插件的安装和升级。
推荐阅读
- 流水线中如何获取代码库分支信息
- H3CERG2系列路由器端口映射(虚拟服务器)
- kubernetes下的Nginx加Tomcat三部曲之二(细说开发)
- 银行卡API接口的功能与作用
- 关于数据一致性的理论
- 如何做一个泡泡龙游戏
- C语言实现井字棋
- 大厂的优惠券系统是如何设计的()
- Python 散列表查询_进入<哈希函数;为结界的世界