Cloudpods容器化经验分享
Cloudpods是一个开源的多云混合云管理平台。Cloudpods首先是一个私有云云平台,具备将计算节点使用开源QEMU/KVM虚拟化技术虚拟出虚拟机,实现私有云的功能。其次,Cloudpods能够纳管其他的云平台,包括主流私有云和公有云,实现云管的功能。Cloudpods的目标是帮助用户基于本地基础设置以及已有云基础设置,构建一个统一融合的云上之云,达到降低复杂度,提高管理效率的效果。Cloudpods从3.0开始全面拥抱Kubernetes,基于Kubernetes部署运行云平台的服务组件,采用Kubernetes Operator,基于Kubernetes集群自动化部署服务,实现了云平台的服务的容器化分布式部署。本文总结了Cloudpods在过去3年云平台底层容器化改造的经验。目前,将Kubernetes作为IAAS平台的底层服务管理平台是一个趋势,例如OpenStack的Kolla项目,VMware的Tanzu,以及基于Kubernetes的虚拟化方案KubeVirt。Cloudpods顺应此趋势,早在2019年下半年开始基于Kubernetes构建Cloudpods的服务组件基础设施。理论上,Cloudpods站在了巨人的肩膀上。有了Kubernetes的加持,我们基于Operator管理CRD(Custom Resource Definition)机制做到了更优雅的服务自动化部署,符合IaC(Infrastructure as code)实践的服务升级和回滚,服务的自动高可用部署等等。但在实际效果上,我们基于Kubernetes,获得了一些便利,但也遇到了不少未曾预料到的问题。本文介绍自从2019年3.0容器化改造以来,因为引入Kubernetes遇到的问题,我们的一些解决方案,以及将来的规划。1、容器化带来了哪些好处
1)方便对分布于多个节点上的服务的管理
管理员可以在控制节点统一地查看运行在各个节点的服务状态,查看日志,启停和发布回滚服务,甚至exec进入服务容器排查问题。同时我们引入Loki收集所有容器的日志,可以统一地查看各个服务的日志。对分布式集群的运维和排障都变得相对简单。采用Kubernetes之后,直接登录各个节点排障的机会大大降低了。
2)集群配置变更更方便及可控
整个集群的状态可以保存为一个OnecloudCluster yaml文件。可以方便地变更集群的配置,包括集群的版本,实现版本的升级和回退,以及集群服务的开启和关闭,镜像版本等关键参数的变更等。更进一步地,可以通过git进行配置yaml的版本控制,做到变更的历史记录审计,并且可以随时恢复到任意指定的配置。
3)便于适配不同的CPU架构和操作系统
Kubernetes作为一层中间层,从一定程度上屏蔽了底层的差异。采用Kubernetes后,对CPU和操作系统的适配大概分为三部分工作:
1. Kubernetes对CPU和操作系统的适配;
2. 不同CPU架构下服务容器镜像的构建;
3. Kubernetes之外的组件的适配,例如平台依赖的rpm包等。基于Kubernetes自身强大的生态,基本都有现成的解决方案,只需要做相应的集成工作。只需通过docker buildx工具生成异构CPU架构的镜像。因此,整个适配工作复杂度大大降低了。
4)部署的便利性增加
引入Kubernetes之后,整个部署流程分为几个阶段:
Kubernetes的部署,这个步骤通过基于kubeadm改造的ocadm实现。
Cloudpods服务容器的部署,这个步骤通过ocadm在容器内部署operator,通过operator实现相应configmaps,deployments和daemonsets等资源的创建,进而自动创建服务集群。
Kubernetes之外依赖组件的安装部署。这个步骤通过ocboot,集成ansible实现。每个阶段都是基于成熟的开源方案扩展实现,可靠性高。同时,各个组件分工明确,模块化清晰,易于维护和扩展。
5)可复用Kubernetes本身自带的强大功能
如coredns可以自定义域名,甚至可以做泛域名解析。Ingress自带反向代理的功能。service+deployment提供的多副本冗余机制。daemonset提供的在新添加节点自动拉起服务的能力。对服务的资源限制(CPU,内存,进程号等)。这些都使得云平台服务功能特性的实现变得更加容易。2、容器化遇到了哪些问题,如何解决
下面总结一些遇到的问题。这些问题是我们在采用Kubernetes管理和运行云平台组件中陆续发现的。有些已经彻底解决,但很大一部分还只是部分解决,彻底解决的方案还在持续摸索中。
1)容器内运行系统级服务
Cloudpods在计算节点运行的服务都是系统级的服务,如计算节点的核心服务hostagent,需具备几个特权:
需启动系统的daemon服务进程,如qemu虚拟机进程,vswitchd等系统进程,这些进程由hostagent启动,但需独立于hostagent运行;
需访问计算节点的任意目录文件。
在容器化之前,这些服务由systemd管理,以root身份运行。这些特权都自然具备。容器化后,服务需运行在容器内。虽然可以通过配置给与容器系统级的root权限,但是一些特权操作在容器内依然无法执行。
首先,容器内无法启动系统级daemon服务进程。如果通过容器内的程序启动进程,则该进程只能运行在容器内的PID空间(pid namespace),只能跟随容器的生命周期启停。为了解决这个问题,我们将系统服务的二进制程序安装在计算节点的底层操作系统,并且开发了一个命令执行代理executor-server。该代理安装在底层操作系统,并作为一个系统服务运行。容器内的hostagent通过该代理执行系统级命令,例如启动这些daemon服务,设置内核参数等,从而获得了执行系统级命令的特权。
其次,每个容器具有自己独立的文件系统命名空间(mount namespace)。为了允许容器内服务访问计算节点底层系统的特定路径文件,需要将该路径显式地挂载到容器的文件系统命名空间。例如,虚拟机的配置文件和本地磁盘文件都存储在/opt/cloud/workspace目录下。容器内的hostagent在虚拟机准备和配置阶段需要能够访问这个目录的文件,同时,启动虚拟机后,在底层操作系统运行的虚拟机qemu进程也需要能够访问对应的文件。并且,由于上述命令执行代理的机制,为了简化和保持向后兼容的目的,需要确保尽量以一致的路径在容器内和容器外访问这些文件。为此,我们将一些特定的系统目录以同样的路径挂载到hostagent的容器内,例如系统设备文件路径/dev,云平台的配置文件路径/etc/yunion,虚拟机系统文件路径/opt/cloud/workspace等。然而,这个机制还无法解决容器内服务访问底层系统任意路径的问题。例如,用户可以将底层系统的任意目录设置为虚拟机磁盘的存储目录,但是该目录其实并未通过容器的spec挂载到hostagent容器内,从而导致hostagent在容器内无法访问该目录。为了解决这个问题,我们对hostagent进行了改造。当hostagent检测到用户添加了新的本地目录作为虚拟磁盘文件的存储路径,会自动地执行底层系统命令,将该路径挂载到底层操作系统的/opt/cloud/workspace目录下。因该目录已经挂载到hostagent容器内,这样hostagent就可以在容器内访问这个目录下的文件。
总之,相比将一个普通应用程序容器化,将系统级的服务程序从systemd托管变为在Kubernetes容器中运行,不是仅仅简单地打一个容器镜像,其实还需要做一系列比较复杂和繁杂的改造工作。
2)日志持久化
容器化之前,服务日志会记录到journald中,并被持久化到/var/log/messages。按照CentOS的默认策略,保留最近一段时间的日志。遇到问题的时候,可以到对应服务器查找到对应的日志,排查错误原因。但是,不方便的地方是需要登录到服务运行的节点查看日志。在一个事故涉及多个节点的时候,就需要同时登录多个节点进行日志排查。
容器化之后,可以方便地在一个地方,通过kubectl log命令查看指定容器的日志,不需要登录到服务运行的节点。
然而,如果没有做特殊设置,K8s里的容器的日志都是不持久保存的,并且只保留当前正在运行的容器的最近一段时间的日志。而容器往往非常动态,很容易删除。这就导致遇到问题需要排查已经被删除的容器时候,容易遇到找不到对应的日志。这就使得追溯问题变得比较困难。
我们的解决方案是从3.7开始,会默认在k8s集群里部署Loki套件来收集容器的日志,日志最后存在minio的S3 Bucket 里面。这样做能够持久化容器的日志。解决上述问题。但是,保存Loki日志有一定的系统负载,并且需要较大容量的存储空间。在集群容量紧张的情况下成为平台的额外负担,可能造成平台的不稳定。
3)节点Eviction机制
Kubernetes有驱逐机制(Evict)。当节点的资源余量不足时,例如磁盘剩余空间低于阈值或剩余内存低于阈值(默认根分区磁盘空间低于85%,空闲内存低于500M)等,会触发Kubernetes的节点驱逐机制,将该节点设置为不可调度,上面的所有容器都设置为Evict状态,停止运行。
该机制对于无状态应用可以动态地规避有问题的节点,是一个好的特性。然而,在云平台的场景中,甚至对于普遍的有状态服务场景中,Eviction机制导致节点可用性变得非常动态,进而降低了整体的稳定性。例如,由于用户上传一个大的镜像,导致控制节点根分区利用率超过Eviction的阈值85%,云平台的所有控制服务就会被立即驱除,导致云平台控制平面完全不可用。用户在虚拟机磁盘写入大量数据导致宿主机磁盘空间利用率超过阈值,也会引起计算节点上所有服务被驱逐,进而导致这台计算节点上所有的虚拟机失联,无法控制。可以看到,虽然触发Eviction机制的问题存在造成服务问题的可能,但是这些问题对服务的影响是延后的,逐步生效的。Eviction机制则使得这些潜在风险对服务的影响提前了,并立即发生,起到了放大的作用。
为了避免Eviction机制生效,云平台在计算节点的agent启动的时候,会自动检测该节点的Eviction阈值,并设置为计算节点的资源申请上限。云平台在调度主机的时候,会考虑到Eviction的阈值,避免资源分配触发Eviction。这个机制能从一定程度规避Eviction的出现,但云平台只能管理由云平台分配的资源,还是存不在云平台管理范围内的存储和内存分配导致Eviction的情况。因此需要计算节点一定程度的内存和存储的over-provisioning。
目前,Eviction的存在也有一定的积极作用,那就是让节点资源的不足以云平台罢工的方式提出警示。由于云平台的冗余设计,云平台的暂时罢工并不会影响虚拟机的运行,因此影响程度还比较可控。无论如何,以云平台可用性的牺牲来达到资源不足的警示,代价还是有点大。这样的警示可以其他更柔和的方式来实现。随着云平台自身管理资源容量能力的完善,Eviction机制应该可以去除。
4)容器内进程泄露
Cloudpods服务主要为go开发的应用程序,容器镜像采用alpine基础镜像最小化构建,仅包含服务的二进制和alpine基础镜像,服务进程作为容器的启动进程(1号进程)运行。我们的服务程序没有为作为1号进程做专门的优化,因此不具备systemd/init等正常操作系统1号进程具备的进程管理能力,例如处理孤儿进程,回收zombie进程等。然而,一些服务存在fork子进程的场景,例如kubeserver调用服务的时候会fork ssh执行远程命令,cloudmon则会执行采集监控数据的子进程。当这些子进程遇到异常退出时,由于我们的服务进程不具备主动回收子进程的功能,导致系统里积压了了大量退出异常未回收的子进程,导致进程泄露。这些子进程占用操作系统进程号,当达到系统最大进程数时,会出现系统CPU和内存非常空闲,但是无法进一步fork新的进程的情况,导致系统服务异常。
为了避免容器内进程泄露问题,我们在Cloudpods服务框架里加入了回收子进程的逻辑,并且添加到每个服务进程中,这样在子进程异常退出后,我们的服务进程会回收子进程资源,从而避免了这个问题。同时也配置了kubelet的 最大进程数的限制参数,限制一个pod里面最多能有1024个进程。
5)高可用不一定高可用
我们基于Kubernetes实现了控制节点的3节点高可用,基本思路是使用3个节点部署高可用的Kubernetes的控制服务,包括apiserver, scheduler, controller, etcd等。Kubernetes服务通过VIP访问。采用keepalived实现VIP在三个控制节点上的自动漂移。这此高可用Kubernetes集群之上,部署云平台控制服务,实现云平台控制平面的高可用。预期效果是将3个控制节点中的任意节点宕机后,主要服务不受影响,如果有影响,需能够在短时间内自动恢复。
然而,初期测试发现采用默认参数部署的 Kubernetes 高可用自动恢复的时间高达15分钟,不符合预期。经过调研发现,可以通过给各个组件设置相关的参数来减少恢复时间(https://github.com/yunionio/ocadm/pull/39/files)。经过参数调整,可以让Kubernetes集群高可用切换时间缩短到1分钟以内。
6)服务的启动顺序
Kubernetes无法指定pod启动的顺序,同时也要求部署在K8s里的服务不要对其他服务的启动先后顺序有依赖。云平台服务在采用Kubernetes部署管理之前是采用systemd管理,systemd可以明确定义服务之间的启动顺序。这导致服务之间有比较明显的先后次序依赖。比如,keystone服务就要求最先启动,其他所有服务都依赖keystone服务提供初始化服务账号的认证。容器化改造后,由于这个依赖,导致在keystone容器启动之前的服务无法正常运行。定位到该问题后,我们将服务因为启动顺序导致的错误升级为致命错误。这样,该服务程序遇到依赖服务未启动导致的问题就异常退出。进而,通过Kubernetes自动重启拉起服务进程。通过这样的改造消除了其他服务对keystone的启动顺序依赖。然而,我们无法找到有效手段识别出所有依赖启动顺序而出现的错误,因此这样的服务无顺序改造还在持续。
7) 证书失效问题
Kubernetes集群节点之间的相互认证和通信依赖PKI秘钥体系。如果节点的PKI证书过期,则该节点kubelet无法正常和ApiServer通信,进而导致节点状态被设置为NotReady,进而出现前述的容器驱逐导致节点不可用的严重问题。刚开始,我们部署的k8s集群还是采用kubeadm默认的1年有效期的证书,当时还未顾及到证书到期的问题。到2020年底,开始陆续出现多个集群莫名服务不可用的情况,才注意到证书过期的问题。针对这个问题,我们刚开始采用cronjob安装自动更新证书脚本的方案,并且在客户巡检中,专门检查证书过期问题,以提前发现问题。后来到了2021年3.8版本,采用了更糙快猛的方法,直接修改了kubeadm的证书签发代码,一次性签发99年证书,从而彻底解决了Kubernetes的证书过期问题。
8) iptables修改
Kubernetes部署后,kubelet、kube-proxy以及我们采用的calico等都依赖iptables,会接管节点的iptables规则,在kubelet启动之后,对iptables规则的修改会被重置,并且会刷新iptables规则。如何持久化对iptables规则的修改成为问题。目前,针对节点的防火墙规则可以采用calico的网络策略来实现,可参考文章https://www.cloudpods.org/zh/blog/2021/09/25/calico-customized-node-firewall/。但更复杂iptables规则,还没找到有效办法。 3、未来规划
1)升级Kubernetes版本
目前,云平台底座kubernetes的版本是1.15.12,该版本已经不再被Kubernetes官方支持。目前存在的比较明显的问题是和较新的采用cgroup v2的操作系统不兼容,导致无法设置服务的资源limit。后续考虑升级底层Kubernetes到更新版本,以期获得更新的功能特性支持。
2)采用K3S等更轻量版本
目前云平台依赖底层Kubernetes的功能特性不多,同时Kubernetes本身也要消耗一定的节点资源,后面也计划考虑采用k3s等更轻量的Kubernetes版本,进一步降低Kubernetes的使用成本。
3)移除计算节点对iptables的依赖
计算节点网络主要依赖openvswitch实现虚拟机的通信,iptables主要是给kubelet,kube-proxy和cailico-node等k8s服务组件使用,而计算节点上的服务组件主要是用来管理QEMU/KVM虚拟机的host-agent等服务,这些服务本身具备基于ovs的网络管理能,不依赖k8s的网络,完全可以只依赖host网络即可正常工作。因此,其实可以去掉计算节点的kubeproxy,calico等组件,去除对iptables的修改,这样简化组件依赖,进一步提高系统的可靠性。
4)完全禁用Eviction机制
Eviction机制在虚拟化云平台或有状态服务场景中,会起到故障放大的作用。在充分掌控对节点资源耗尽预警的前提下,应考虑彻底禁用Eviction机制。
5) 多数据中心架构的支持
目前云平台所有节点都运行在一个Kubernetes集群内。而云平台本身是可以支持多数据中心部署的。但是跨数据中心部署单个kubernetes集群不是最佳实践。比较理想的架构是单个kubernetes集群部署在一个数据中心内。因此,应该允许云平台跨多个K8s集群部署。例如每个数据中心一个Kubernetes集群,其中一个集群部署完整的云平台,其他Kubernetes集群以从可用区的角色加入主集群。每个Kubernetes集群之上只运行管理一个数据中心所需的云平台组件。进而构成一个多数据中心的云平台架构。
GitHub: https://github.com/yunionio/cloudpods
阅读原文:Cloudpods容器化经验分享
iPhone14Pro提前上手发现大变化截图会显示挖孔日前,一名网友在抖音上直播提前拆封激活iPhone14Pro引起了巨大的关注。除了提前展示了真机外观之外,还通过安兔兔跑了分,展示了许多新一代全新的功能,包括灵动岛。值得注意的是,
关注角色往造车领域靠拢?雷军卸任小米电子软件公司董事长文懂车帝原创彩丽美懂车帝原创行业日前,懂车帝从天眼查获悉,北京小米电子软件技术有限公司发生工商变更,本次变更中,雷军卸任该公司董事长。此外,林斌卸任该公司董事,洪锋卸任法定代表人董
原神最难6命的角色是?氪金也不一定能6命原神已经出了一年多了,大家应该都已经抽到自己喜欢的角色了吧,玩了这么久肯定也有很多满命角色了。今天小编就带大家了解一下原神最难6命的几个角色吧。凯亚,凯子哥大家都有,但是满命的有几
新版本麻雀虽小五脏俱全,CF手游又有新角色登场了新人物背景麻雀虽小但是五脏俱全,今天为大家展现的是一款新的角色名为麻雀,这款人物的背景是通信兵出身的特工们组成的谍报部队,简单来说就是拥有高级电子信息技术的特种部队,在各种任务中都
中超山东泰山平武汉三镇9月14日,山东泰山队球员刘洋(右)在比赛中进球后。新华社记者朱峥摄当日,在山东济南举行的2022赛季中国足球协会超级联赛第18轮比赛中,山东泰山队主场以1比1战平武汉三镇队。9月
53岁王菲拍性感广告!穿抹胸裙躺地上曲线妙曼,眼神风情气场强大近日,有品牌晒出由王家卫执导王菲主演的广告大片,时隔多年两人合作,引发网友热议。在视频中,王菲共有两组造型,展现了别样的风格。第一组黑色系,王菲身穿黑色抹胸礼服,流光溢彩之间,举手
如何能买到性价比高的黄金项链?了解下面这几点就能实现女人的魅力大部分都是由自信气质和外在的装扮互相结合的。对于女生来说,佩戴好看的黄金项链不仅能提升气质,还能提升女生的自信。那你知道10克的黄金项链多少钱一个吗?你知道如何在今天买到
00!皇马拒绝翻车,11分钟解决战斗,魔笛创57年纪录北京时间9月15日凌晨,欧冠小组赛继续进行,卫冕冠军皇马坐镇伯纳乌,迎来德甲劲旅RB莱比锡的挑战,这是两队首次在欧冠比赛当中相遇。上半场恩昆库连续错失机会,下半场巴尔韦德打破僵局,
如何预防心律失常的发作,专家给出三个方法对于心律失常的患者来说,药物治疗是最基本的治疗方法,所以心律失常发作时可以吃药来缓解自身的病情,避免出现心跳过快的现象,否则就有可能会对自身的生命造成一定影响。同时,在日常生活中,
卡塔尔世界杯的冠军巴西或者阿根廷2022,巴西就是冠军!!!!巴西对于南美球队在本届世界杯的表现,我是非常看好的,无论是阿根廷或是巴西,剩下的乌拉圭和厄瓜多尔不太看重。非常看好的原因,在于我坚定地相信阿根廷和巴西
感恩生命里,所有温暖的相遇世上所有的相遇,都有它的意义。有人说,世间的一切都是遇见,就像冷遇见了暖,有了雨春遇见了冬,有了岁月天遇见了地,有了永恒人遇见人,就有了故事。人生在世,没有平白无故的遇见,我们要感
为什么越来越多人使用苹果手机免责声明本文部分文字与图片资源来自于网络,转载此文是出于传递更多信息之目的,若侵权,请立即通知我们,我们会第一时间予以删除,并同时向您表示歉意!为什么那么多人使用苹果手机呢,据统计
AI绘画,艺术的消亡还是生产力的变革?AI绘画的话题讨论热度在前段时间不断攀升,而在这场讨论中,人们普遍的关注点在于,AI绘画未来究竟是会推动艺术的发展,还是会危及艺术创作的地位。本篇文章里,作者便针对AI绘画等相关问
Coinbase支持针对SEC的RippleCoinbase正在支持另一家加密公司,增加了加密行业对SEC的更大压力。开发瑞波支付协议的公司RippleLabs一直在与美国证券交易委员会(SEC)提起的高调诉讼作斗争,这已经
曝新iPadProUSBC线缆缩水,iPhone13让路新机跌至白菜价近日,苹果发布了2022版的iPadPro,附带了新的USBC编织充电线,但这种充电线与此前附带的USBC充电线相比有一定的缩小。经过测试,这款全新的USBC充电线采用与雷丝相同的
全球知名的十大搜索引擎,你知道多少?1。Google全球第一搜索引擎2。Bing微软旗下的搜索引擎,谷歌最好的替代品3。Yahoo!最早的Yahoo!是一家网址导航网站,但随后推出的搜索引擎也获得了不小的市场份额,月
2022科技公司薪酬排行榜,来了levels。fyi最新全球软件工程师薪酬报告新鲜出炉了,这份报告搜集遍布全球1500多个城市,超过100000名员工的薪资福利等级等方面的数据。大众所期待的FLAG四大科技巨头中
羊了个羊背后公司清仓式分红,实控人获利3亿,还不用交个税羊了个羊本来已经渐渐淡出人们的视线了,但是跟羊了个羊有所关联的某公司的一则利润分配方案,又引起了人们的热议。具体怎么回事呢?一起来看看吧!厦门吉比特网络技术股份有限公司(下文简称吉
能够认识你,真好作者茅山云机子。突然间想起汪国真的诗选已经躺在书架上落满了灰尘,太久的时间疏于整理,心血来潮翻来书本,映入眼帘的是这样一首小诗,能够认识你,真好。不知多少次,暗中祷告,只为了心中的
做人坚强,风雨过后是彩虹在生活中,我们看到小草覆盖着大地,但它是如此之短,以至于人们可以践踏它。看到花绚烂美丽,却又娇弱,谁都可以采,唯有一棵树能挺立于天地之间,让人赞叹不已。有的树日晒风吹,无法控制雨水
财联社时评总规模超30万亿的地方债务,兑付风险如何有效保障?日前,财政部发布的关于支持深圳探索创新财政政策体系与管理体制的实施意见,再度提及探索建立政府偿债备付金制度,防范地方政府专项债券兑
名单公示中!东湖高新区拟给这些高校企业发奖金10月31日,东湖高新区发通知,公示该区科技成果转化和技术转移专项奖励资金,有400多家高校院所企业拟获奖。东湖高新区网站信息显示,经高校院所和企业申报形式审查专家审核实地走访复核