Notice: Constant WP_DEBUG already defined in /var/www/html/wordpress/wp-content/plugins/changyan/sohuchangyan.php on line 12

Notice: Constant WP_DEBUG_LOG already defined in /var/www/html/wordpress/wp-content/plugins/changyan/sohuchangyan.php on line 13

Notice: Constant WP_DEBUG_DISPLAY already defined in /var/www/html/wordpress/wp-content/plugins/changyan/sohuchangyan.php on line 14
【转载】在Kubernetes上部署近1000个OpenStack节点的经验分享 – zoues

LOADING

Follow me

【转载】在Kubernetes上部署近1000个OpenStack节点的经验分享
四月 24, 2017|DockerPaaS

【转载】在Kubernetes上部署近1000个OpenStack节点的经验分享

【转载】在Kubernetes上部署近1000个OpenStack节点的经验分享


配置

我们一开始使用了 175 个物理服务器,其中 3 个用于 Kubernetes 控制服务(API 服务器,ETCD,Kubernetes 调度器等),剩余的每个节点各有 5 个虚拟机作为 Kubernetes minion 节点。

每台物理服务器的规格如下:

   HP ProLiant DL380 Gen9

   CPU – 2x Intel(R) Xeon(R) CPU E5-2680 v3 @ 2.50GHz

   内存 – 264G

   存储 – 3.0T on RAID on HP Smart Array P840 Controller, HDD – 12 x HP EH0600JDYTL

    网络 – 2x Intel Corporation Ethernet 10G 2P X710

运行的 OpenStack 集群(就 Kubernetes 而言)包括:

1.  OpenStack 控制服务运行在超过 6 个节点的 150 个 pod 中

2.  剩余节点有接近 4500个 pod,每个 minion 节点有5 个 pod




02



一个 Prometheus 的主要问题

在实验中,我们使用Prometheus 工具来监测资源的消耗,核心系统、Kubernetes、OpenStack 服务的负载。当使用 Prometheus 时有个问题引起我们注意:删除 Prometheus 存储的旧数据会明显提高 Prometheus API 的速度,但是这样旧群集的信息也被删除了,使得后期无法处理数据了。所以在每次测试时都要详细的记录观察到的问题,以及每次调试都要足够充分。

值得庆幸的是,我们做了详细的记录,另外我们决定将 Prometheus 数据备份到它支持的时间序列数据库中来防止这种情况,如 InfluxDB、Cassandra、OpenTSDB。默认情况下,Prometheus 对使用实时监控、报警系统进行了优化,Prometheus 开发团队也官方推荐只保留 15 天的监控数据,以保证系统工作响应速度。通过设置备份,我们可以从备份中获取数据来进行后期处理。

03

我们测试中遇到的问题


3.1 Kube-apiserver 巨大的负载


  • 现象

      最初,我们把所有节点(包括 Kubernetes 控制平面)都运行在虚拟环境中,但负载是太高以至于不能正常工作,所以他们被转移了物理服务器上。尽管如此,在我们迁移到物理服务器后,Kubernetes 集群中运行的 API 服务器仍占用了 2000% 的 CPU(接近总计算节点性能的 45%)。

  • 根本原因

      所有不在 Kubernetes 主节点上的服务(kubelet、kube-proxy 在所有的 minion 节点上)都通过本地的 Nginx 代理来访问 API 服务。大多数的请求在初始化连接后(设置的超时时间为 5 至10分钟)都是空闲的。而 Nginx 配置中超过 3 秒的空闲连接都会被切断,这导致所有客户端进行重新连接,甚至更糟糕的会重新启动被中止的 SSL 会话。在服务端,Kube API 服务因此消耗了 2000% 的 CPU资源,使得其他请求响应非常慢。


  • 解决方法

      在 nginx.conf 中设置 proxy_timeout 参数为 10分钟,使得 Nginx 切断 SSL 连接前有足够多的时间等待连接本身超时。修改之后,一个 API 服务只消耗了 100% 的 CPU(总计算节点性能的2%),另一个 API 服务消耗了 200% 的 CPU(总计算节点性能的 4%),平均响应时间为 200-400毫秒。

  • 上游问题状态:已修复

      Kargo 部署时设置 proxy_timeout 为 10分钟:问题 已修复代码 由 Fuel CCP 团队提交。


3.2 KubeDNS 默认设置不能处理大型集群的负载

  • 现象

      当部署这么大的 OpenStack 集群,KubeDNS 由于负载过高而失去响应。我们从 kubedns pod 的 dnsmasq 容器中的日志里发现了出错的原因:

Maximum number of concurrent DNS queries reached.

      此外,dnsmasq 容器有时也会因为内存限制而重新启动。


  • 根本原因

      首先,kubedns 在这个架构中似乎即使没有负载也常常出错。在实验过程中,我们观察到,即使在一个没有 pod(但足够大) 的 Kubernetes 群集中 kubedns 容器也经常重新启动。重新启动是因为心跳检测失败而引起的,在日志中我们还没观察有价值的信息。

      其次,dnsmasq 理论上是让 kubedns 负载降低的,但这么大负载的情况下它需要重新调优才能正常工作。


  • 解决方法

      解决这个问题需要几个层次的步骤:

      1.  放宽 dnsmasq 容器的限制:他们承担了大部分的负载。

      2.  给 kubedns 冗余控制器添加更多的副本(我们左后使用了 6 个副本,因为它解决了问题 – 更大的集群它可能需要更多的副本)。

      3.  增加 dnsmasq 的并发处理数量(我们使用 dnsmasq 手册中推荐的 –dns-forward-max=1000)

      4.  增加 dnsmasq 缓存的大小:它设置了 10000 个缓存条目的限制。

      5.  修复 kubedns 来更合理地处理这种情况。


  • 上游问题状态:部分修复

       针对#1和#2 的问题 Kubernetes 团队使得 Kargo 可以修改参数配置:问题 代码

       其他问题 – 还未开始修复。

3.3 Kubernetes 调度器需要部署到单独的节点上

  • 现象

      在 Kubernetes 上部署大规模的 OpenStack 集群,Kubernetes 的调度器、控制器、管理器和 API 服务负载都很高,对 CPU 资源的抢夺也很严重。调度器是最繁忙的,所以我们需要把它部署在单独的节点上。

  • 解决方法

      我们把 Kubernetes 调度器手动移动到单独的节点;手动杀死其他调度,以防止它们转移到其它节点上。

  • 上游问题状态:已报告

      在Kargo 中的问题

3.4 Kubernetes 调度器处理 pod antiaffinity 非常低效


  • 现象

      每次使用 pod antiaffinity 规则调度 pod 时,调度器都要花费很长的时间。每个 pod 的调度时间大约为2-3秒,这使得部署 900 个节点的 OpenStack 集群需要非常长的时间(仅调度大约需要 3 小 时)。OpenStack 的部署必须使用 antiaffinity 规则,以防止单个 Kubernetes minion 节点启动多个 OpenStack 计算服务。

  • 根本原因

      根据分析结果,大部分的时间都花在创造新的选择器来匹配现有的pod,这会触发验证操作。基本上,我们有 O(N^2) 不必要的验证步骤(其中 n = pod 的数目),即使我们只有 5 个部署步骤需要调度。

  • 解决方法

      在这种情况下,我们需要优化调度的时间,使得其调度一个 pod最多需要 300 毫秒。这样调度还是很慢(调度一个 900 个节点的OpenStack 集群需要 30 分钟),但它至少合理。该解决方案降低了耗时的操作到 O(N) 的时间,这比之前的好,但仍取决于 pod的数目而不是部署的数目,因此还有很大的改进空间。

  • 上游问题状态:已修复

      这部分优化已经合并到主仓库(代码 ),以及移植到了 1.5 分支,并在 1.5.2 发布(代码 )。

3.5 Kube API 服务默认速率限制非常低

  • 现象

      即使 Kube API 服务器可以承载更多的负载,不同的服务仍收到“429 Rate Limit Exceeded” 的 HTTP 错误。这个问题是在调度器 BUG 中发现(见下文)。

  • 解决方法

      通过 –max-requests-inflight 选项来修改 Kube API 服务的最大连接速率。它默认为 400,但在我们的情况下,它设为 2000 比较合理。Kargo部署工具应该可以配置这个数字,因为部署更大规模的集群这个数字需要更大。

  • 上游问题状态:已报告

       在 Kargo 中的问题


3.6 Kubernetes 调度器不能正确调度

  • 现象

      当创建大量 pod(在我们的例子中大约为 4500 个),并且 Kube API 服务返回了 429 错误(见上文),调度会安排同一部署中的几个 pod 到一个节点上,这违反了它们的 pod antiaffinity 规则。

  • 根本原因

      见下面的代码拉取请求。

  • 上游问题状态:已提交代码

      来自 Mirantis 团队的修复:代码拉取请求 (已合并,Kubernetes 1.6 的一部分)。

3.7 Docker 有时无法响应 

  • 现象

      多个节点的 Docker 都会偶尔停止响应,这导致 kubelet 日志中有超时错误。发生这种情况时,受影响的 minion 节点上的 pod 不能被创建和删除。尽管 Docker 1.11 以来很多问题都被修复了,我们还在观察这些现象。


  • 解决方法

       Docker 的日志没有包含有价值的信息,所以我们不得不在受影响的节点上重新启动 Docker 服务。(在实验中,我们使用的是 Docker 1.12.3,但我们在 Docker 1.13rc 版中也观察到了类似的现象。)


3.8 OpenStack 服务不处理 PXC 伪死锁


  • 现象

      并行运行时,大量的资源都创建失败了,原因是 DBError:Percona Xtradb Cluster 发现了死锁,事务需要重新开始。


  • 根本原因

      oslo.db 负责处理从数据库收到的错误,并传给相应的类处理。这样,如果发生类似的错误,数据库事务可以重新开始。但是 Percona 的给出的错误 oslo.db 没有正确处理。我们解决了这个问题之后,仍然经历了类似的错误,因为 Nova 代码中不是所有的数据库事务都能正确的重新启动。

  • 上游问题状态:已修复

      该问题 由 Roman Podolyaka 修复CR,并backports 回了 Newton 版。它修复了 Percona 的死锁错误检测,但在 Nova 中至少还有一个地方仍然需要修复。

3.9 live_migration_uri 的配置导致热迁移失败


  • 现象

      配置了 live_migration_uri 后,因为一个计算节点上的 libvirt 不能连接另一个计算节点上的,而导致热迁移失败。

  • 根本原因

      我们没有在 live_migration_uri 模板中指定使用 IP 地址,从而它试图用第一个网络接口的地址,而这是 PXE 网络的,不是 libvirt 监听的私有网络。live_migration_inbound_addr 可以解决这个问题,但因为上游 Nova 的一个问题我们不能使用。


  • 上游问题状态:已修复

      一个 Nova 的错误 已经被修复 移植回 了Newton 版。之后我们 切换 到使用 live_migration_inbound_addr。

UMCloud(上海优铭云计算有限公司)是一家中方控股的合资云计算公司,两大股东分别是中国顶尖的中立公有云服务商UCloud和全球排名第一的OpenStack云计算服务商Mirantis。公司成立于2016年,专注于私有云产品方案与服务、存储产品、Mirantis OpenStack培训等业务。 在Kubernetes上部署近1000个OpenStack节点的经验分享

       了解更多资讯  关注官方微信

no comments
Share