我想做什么
我正在尝试进行部署并监视k8s事件,直到使用k8s节点api(监视)准备好部署:https://github.com/kubernetes-client/javascript/blob/master/examples/typescript/watch/watch-example.ts
我的问题
我已经阅读了这一部分:https://kubernetes.io/docs/reference/using-api/api-concepts/#watch-书签一遍又一遍,但我仍然无法理解,从客户端的角度:
- 这个功能试图解决什么问题
- 我应该什么时候使用它
- 我可以不使用它而不错过活动吗
- 我该如何使用它
- 收到书签事件时该怎么办
我将尝试从客户的角度回答您的问题:
此功能试图解决什么问题?
其目的是减少对资源类型发出监视请求的客户端对kube-apiserver的负载。书签旨在让客户端知道服务器已经向客户端发送了所有事件,直到Bookmark事件中指定的resourceVersion
。这是为了确保如果客户端的监视失败或通道关闭(超时后),客户端可以从Bookmark事件中最后返回的resourceVersion
恢复监视。在没有像Added、Modified、Deleted这样的真正变化事件的情况下,它更像是一个检查点事件。
客户端可能已经在缓存作为常规Added、Modified、Deleted事件的一部分接收到的resourceVersion,但请考虑这样一种情况,即您正在观看的资源在过去30分钟内没有更新,并且您缓存的resourceVersion
为"0";100〃;。
在没有书签事件的情况下,您将尝试从";100〃;,但是服务器可以返回"0";410消失";表明它没有那个版本或者太旧了。在这种情况下,客户端必须执行List以获取最新的resourceVersion并从那里启动监视,或者通过不指定resourceVersion从最新开始监视,这对服务器来说处理成本更高。
在书签事件存在的情况下,服务器可能会尝试向您发送带有resourceVersion"的书签事件;150〃;表明您已经处理了该版本,如果重新启动,您可以从此开始处理。文档中的这个人为的例子说明了这一点。您在rv="处启动您的观察程序;10245〃;,您处理一些事件直到rv="0";10596〃;然后服务器向您发送带有rv="的书签;12746〃;因此,在重新启动的情况下,您可以从此开始处理。
GET /api/v1/namespaces/test/pods?watch=1&resourceVersion=10245&allowWatchBookmarks=true
---
200 OK
Transfer-Encoding: chunked
Content-Type: application/json
{
"type": "ADDED",
"object": {"kind": "Pod", "apiVersion": "v1", "metadata": {"resourceVersion": "10596", ...}, ...}
}
...
{
"type": "BOOKMARK",
"object": {"kind": "Pod", "apiVersion": "v1", "metadata": {"resourceVersion": "12746"} }
}
我应该什么时候使用它
为了有效处理您正在观看的资源上的更改事件,处理书签似乎比不处理要好。不过,不能保证Bookmarks的交付——服务器可能不支持它(如果它运行的是旧版本的Kubernetes),或者可能根本不发送它们。
我可以不使用和不错过活动吗
是的,你完全可以这样做,但如果你使用书签,你错过事件的可能性会降低。还要记住,它不仅有利于客户端,也有利于kube apiserver,因为如果它具有";新鲜的";resourceVerion,在没有书签的情况下,它将不得不从etcd中进行一致的读取。我推荐这段视频来了解观看活动是如何在幕后工作的。
我该如何使用它
根据您起诉的客户端库,使用情况可能会有所不同,但在原始HTTP请求中,您可以指定以下查询参数:allowWatchBookmarks=true
GET /api/v1/namespaces/test/pods?watch=1&resourceVersion=10245&allowWatchBookmarks=true
如果你使用的是client go,有一个叫做Reflector的工具,这就是它请求书签的方式,也是它处理书签的方式
当我收到书签事件时该怎么办
从Bookmark事件中提取resourceVersion,并在您出于任何原因尝试重新启动观察程序时将其缓存。
这是关于列表监视的重新连接机制。u2028当"watch"连接断开时,它将重新连接,"resourceversion"是客户端需要告诉服务器(api服务器)的起点,然后服务器将从该点返回所有事件。
但通常情况下,客户端有过滤器,这意味着如果客户端不关心事件,客户端的"resourceverseion"不会改变(例如,kubelet只关心其节点中的资源)。默认情况下,etcd只保留5分钟的事件。
想想一个例子,一个kubelet有"resourceversion=5"的resourcepod,然后服务器端的"resourceversion"增加到100(由于这些变化:客户端不关心6-100,所以客户端的"resourceversion"仍然是5)。然后连接断开,重新连接开始,客户端告诉服务器它的"resourceversion"是5,但在服务器端,最旧的"resourceversion"是25,所以服务器不知道,因为这会导致客户端丢失事件,所以它必须返回错误:太旧的版本错误。然后客户端必须再次清理其缓存和列表监视,这将花费大量时间。
使用BookMark,客户端将收到通知(只有最新的"resourceversion",没有事件的详细信息),无论它是否关心事件何时引发,它都会确保客户端的"resourceversion"是新的。因此,它避免了使用新的List手表。
与没有书签相比,书签似乎可以将列表减少到3%。
它可以有效地恢复手表,因为您知道到目前为止您已经处理了所有事情。下次启动手表时,您可以将其用作启动版本,而不需要回复每个对象。
k8s将向您发送两件事,例如:
resourceVersion=100 (for ADDED event let's say)
resourceVersion=200 (for BOOKMARK event)
作为客户端,这意味着两件事。如果我们把它分成两部分,就会更容易理解:
resourceVersion=100
对于您当前正在观看的资源,是您关心的内容。例如,如果您正在观看Pods,则100
是一个Pod ADDED事件,因此您作为客户端将获得该事件。第二部分意味着在
101..200
间隔中,没有您作为客户端关心的事件。因此,在重新启动的情况下,从200开始是安全的:你要么消耗了该范围内的所有东西(例如100
),要么没有你关心的事件(101..200
)