K8S集群优化之修复ServiceEndpoint更新的延迟

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
简介: 几个月前,我在更新 Kubernetes 集群中的 Deployment 时发现了一个很奇怪的连接超时现象,在更新 Deployment 之后的 30 秒到两分钟左右,所有与以该 Deployment作为服务后端的 Service 的连接都会超时或失败。

几个月前,我在更新 Kubernetes 集群中的 Deployment 时发现了一个很奇怪的连接超时现象,在更新 Deployment 之后的 30 秒到两分钟左右,所有与以该 Deployment作为服务后端的 Service 的连接都会超时或失败。同时我还注意到其他应用在这段时间内也会出现莫名其妙的延迟现象。

一开始我怀疑是应用没有优雅删除导致的,但当我在更新 Deployment 的过程中(删除旧的 Pod,启动新的 Pod)通过 curl 来测试该应用的健康检查(liveness)和就绪检查(readiness)Endpoints 时,很快就排除了这个可能性。

我开始怀疑人生,开始怀疑我的职业选择,几个小时之后我忽然想起来 Service 并不是直接与 Deployment关联的,而是按照标签对一组提供相同功能的 Pods的抽象,并为它们提供一个统一的入口。更重要的是,Service 是由一组 Endpoint 组成的,只要Service中的一组Pod发生变更,Endpoint就会被更新。

想到这里,就可以继续排查问题了。下面在更新 Deployment的过程中通过 watch 命令来观察有问题的 Service 的 Endpoint。

$ watch kubectl describe endpoints [endpoint name]
然后我就发现了罪魁祸首,在旧 Pod被移除的 30 秒到几分钟左右的时间段内,这些被删除的Pod的 IP:Port 仍然出现在Endpoint 的就绪列表中,同时新启动的 Pod的IP:Port也没有被添加到 Endpoint中。终于发现了连接失败的根源,但是为什么会出现这种状况呢?仍然无解。

又经历了几天折腾之后,我又有了新点子,那就是调试负责更新Endpoint 的组件:kube-controller-manager,最后终于在kube-controller-manager 的日志输出中发现了如下可疑的信息:

I0412 22:59:59.914517 1 request.go:638] Throttling request took 2.489742918s, request: GET:https://10.3.0.1:443/api/v1/namespaces/[some namespace]/endpoints/[some endpoints]"
但还是感觉哪里不对劲,明明延迟了几分钟,为什么这里显示的只有两秒?

在阅读了kube-controller-manager的源码后,我发现了问题所在。Kube-controller-manager的主要职责是通过内部的众多 Controller将集群的当前状态调整到期望状态,其中 Endpoint Controller用于监控Pod 的生命周期事件并根据这些事件更新 Endpoint。

Endpoint Controller 内部运行了一组 workers来处理这些事件并更新Endpoint,如果有足够多的对 Endpoint发起的请求被阻塞,那么所有的 workers 都会忙于等待被阻塞的请求,这时候新事件只能被添加到队列中排队等待,如果该队列很长,就会花很长时间来更新 Endpoint。

为了解决这个问题,首先我通过调整kube-controller-manager 的 参数--concurrent-endpoints-syncs来增加Endpoint Controller的workers,但收效甚微。

再次仔细阅读源码后,我找到了两个可以可以扭转战局的参数:--kube-api-qps 和--kube-api-burst。kube-controller-manager可以通过这两个参数来限制任何 Controller(包括 Endpoint Controller)对 kube-apiserver发起的请求的速率。

这两个参数的默认值是20,但当集群中的主机数量非常多时,默认值显然不满足集群运行的工作负载。经过不断调试之后,我将参数 --kube-api-qps的值设置为 300,将 --kube-api-burst的值设置为 325,上面的日志信息便消失了,同时添加或移除Pod 时Endpoint也能够立即更新。

--kube-api-qps 和--kube-api-burst参数的值越大,kube-apiserver 和etcd 的负载就越高。在我的集群中,通过适当地增加一些负载来解决这个问题是很值得的。

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
21天前
|
Kubernetes Cloud Native 云计算
云原生之旅:Kubernetes 集群的搭建与实践
【8月更文挑战第67天】在云原生技术日益成为IT行业焦点的今天,掌握Kubernetes已成为每个软件工程师必备的技能。本文将通过浅显易懂的语言和实际代码示例,引导你从零开始搭建一个Kubernetes集群,并探索其核心概念。无论你是初学者还是希望巩固知识的开发者,这篇文章都将为你打开一扇通往云原生世界的大门。
90 17
|
13天前
|
Kubernetes 应用服务中间件 nginx
搭建Kubernetes v1.31.1服务器集群,采用Calico网络技术
在阿里云服务器上部署k8s集群,一、3台k8s服务器,1个Master节点,2个工作节点,采用Calico网络技术。二、部署nginx服务到k8s集群,并验证nginx服务运行状态。
113 1
|
18天前
|
Kubernetes Cloud Native 微服务
微服务实践之使用 kube-vip 搭建高可用 Kubernetes 集群
微服务实践之使用 kube-vip 搭建高可用 Kubernetes 集群
59 1
|
18天前
|
负载均衡 应用服务中间件 nginx
基于Ubuntu-22.04安装K8s-v1.28.2实验(二)使用kube-vip实现集群VIP访问
基于Ubuntu-22.04安装K8s-v1.28.2实验(二)使用kube-vip实现集群VIP访问
36 1
|
23天前
|
Kubernetes Cloud Native Ubuntu
云原生之旅:Kubernetes集群搭建与应用部署
【8月更文挑战第65天】本文将带你进入云原生的世界,通过一步步指导如何在本地环境中搭建Kubernetes集群,并部署一个简单的应用。我们将使用Minikube和Docker作为工具,探索云原生技术的魅力所在。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的信息和实践技巧。
|
27天前
|
存储 Kubernetes 关系型数据库
阿里云ACK备份中心,K8s集群业务应用数据的一站式灾备方案
阿里云ACK备份中心,K8s集群业务应用数据的一站式灾备方案
|
9天前
|
Kubernetes Ubuntu Linux
Centos7 搭建 kubernetes集群
本文介绍了如何搭建一个三节点的Kubernetes集群,包括一个主节点和两个工作节点。各节点运行CentOS 7系统,最低配置为2核CPU、2GB内存和15GB硬盘。详细步骤包括环境配置、安装Docker、关闭防火墙和SELinux、禁用交换分区、安装kubeadm、kubelet、kubectl,以及初始化Kubernetes集群和安装网络插件Calico或Flannel。
|
15天前
|
Kubernetes Cloud Native 流计算
Flink-12 Flink Java 3分钟上手 Kubernetes云原生下的Flink集群 Rancher Stateful Set yaml详细 扩容缩容部署 Docker容器编排
Flink-12 Flink Java 3分钟上手 Kubernetes云原生下的Flink集群 Rancher Stateful Set yaml详细 扩容缩容部署 Docker容器编排
58 0
|
16天前
|
弹性计算 Kubernetes Linux
如何使用minikube搭建k8s集群
如何使用minikube搭建k8s集群
|
20天前
|
Kubernetes 应用服务中间件 nginx
k8s学习--k8s集群使用容器镜像仓库Harbor
本文介绍了在CentOS 7.9环境下部署Harbor容器镜像仓库,并将其集成到Kubernetes集群的过程。环境中包含一台Master节点和两台Node节点,均已部署好K8s集群。首先详细讲述了在Harbor节点上安装Docker和docker-compose,接着通过下载Harbor离线安装包并配置相关参数完成Harbor的部署。随后介绍了如何通过secret和serviceaccount两种方式让Kubernetes集群使用Harbor作为镜像仓库,包括创建secret、配置节点、上传镜像以及创建Pod等步骤。最后验证了Pod能否成功从Harbor拉取镜像运行。