client-go 的 QPS 和 Burst 限速

1. 什么是 QPS 和 Burst ?

在 kubernetes client-go 中,QPS 和 Burst 是用于控制客户端与 Kubernetes API 交互速率的两个关键参数:

QPS (Queries Per Second)

定义:表示每秒允许发送的请求数量,即限速器的平滑速率。

用途:用来控制客户端与 API Server 的持续请求速率。

场景:适用于需要长时间维持均匀的 API 调用的情况。

Burst

定义:表示瞬时允许发送的最大请求数量,即限速器的突发容量。

用途:允许在短时间内发送的请求数量上限,适用于突发性调用场景。

场景:例如,客户端初始化时,需要快速获取大量资源。

2. 实验验证

可以通过编写代码,发送大量 API 请求来验证 QPS 和 Burst 的行为。以下是一个实验示例:

go 复制代码
package main

import (
	"context"
	"flag"
	"fmt"
	"log"
	"sync"
	"time"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/tools/clientcmd"
)

func main() {
	// 加载 kubeconfig
	kubeconfig := flag.String("kubeconfig", "~/.kube/config", "Path to kubeconfig file")
	flag.Parse()
	config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
	if err != nil {
		log.Fatalf("Failed to load kubeconfig: %v", err)
	}

	// 设置 QPS 和 Burst
	config.QPS = 5.0  // 每秒 5 个请求,也是默认设置
	config.Burst = 10 // 突发允许 10 个请求,也是默认设置

	// 创建客户端
	clientset, err := kubernetes.NewForConfig(config)
	if err != nil {
		log.Fatalf("Failed to create clientset: %v", err)
	}

	// 统计开始时间
	startTime := time.Now()

	// 使用 WaitGroup 追踪请求完成
	var wg sync.WaitGroup
	totalRequests := 50
	wg.Add(totalRequests)

	// 发送大量请求
	for i := 0; i < totalRequests; i++ {
		go func(i int) {
			defer wg.Done()
			_, err := clientset.CoreV1().Pods("").List(context.TODO(), metav1.ListOptions{})
			if err != nil {
				log.Printf("Request %d failed: %v", i, err)
			} else {
				log.Printf("Request %d succeeded", i)
			}
		}(i)
	}

	wg.Wait()
	fmt.Printf("Total time taken: %v\n", time.Since(startTime))
}

配置 QPS 和 Burst:

设置 QPS = 5,表示每秒最多发送 5 个请求。

设置 Burst = 10,允许在瞬时突发时最多发送 10 个请求。

当发生客户端限流时,会出现类似如下输出:

sh 复制代码
2025/01/10 15:01:50 Request 32 succeeded
I0110 15:01:50.468917    3083 request.go:729] Waited for 1.19372275s due to client-side throttling, not priority and fairness, request: GET:https://127.0.0.1:63092/api/v1/pods
2025/01/10 15:01:50 Request 33 succeeded

当发生客户端限流时,请求排队,实际完成时间会被延长。

实验结果:

当设置 QPS = 5,Burst = 10 时,请求全部成功,完成耗时 8s

当设置 QPS = 1,Burst = 2 时,请求全部成功,完成耗时 48s

调整建议

如果需要高频请求,可适当增大 QPS 和 Burst,避免客户端过度限流。

同时,合理设置参数,可以避免客户端过高的并发负载影响集群稳定性。

源码机制

client-go 使用令牌桶进行速率限制,桶容量为 burst 大小,按照每秒生成 QPS 个令牌的速率产生令牌(不会实际启动协程生成令牌,而是根据时钟计算),只有拿到令牌才能请求 kube-apiserver,如下图所示:

reference: client-go QPS、Burst和令牌桶

相关推荐
liux352817 分钟前
k8s之Ingress讲解
云原生·容器·kubernetes
小刘爱喇石( ˝ᗢ̈˝ )4 小时前
玛卡巴卡的k8s知识点问答题(六)
云原生·容器·kubernetes
rider1894 小时前
【1】搭建k8s集群系列(二进制部署)之系统初始化
云原生·容器·kubernetes
小刘爱喇石( ˝ᗢ̈˝ )6 小时前
玛卡巴卡的k8s知识点问答题(七)
云原生·容器·kubernetes
小哈里7 小时前
【运维】云计算的发展历程,云原生时代的运维理念&工具技术栈,高可用系统的云运维 —— 以K8S集群调度算法与命令为例
运维·云原生·kubernetes·云计算·架构设计
{⌐■_■}7 小时前
【Kubernetes】如何使用 kubeadm 搭建 Kubernetes 集群?还有哪些部署工具?
云原生·容器·kubernetes
云上艺旅10 小时前
K8S学习之基础六十九:Rancher创建svc资源
学习·云原生·容器·kubernetes·rancher
可观测性用观测云1 天前
Kubernetes APIServer 可观测最佳实践
kubernetes
碣石潇湘无限路1 天前
【云原生】Kubernetes CEL 速查表
容器·贪心算法·kubernetes
企鹅侠客1 天前
Prometheus operator怎么添加targets和告警规则
运维·云原生·kubernetes·prometheus·pod