Kubernetes 资源版本太旧
Kubernetes too old resource version
我正在开发一个为不同的 k8s 资源创建监视的操作员。我时不时地在日志中看到以下异常,应用程序就停止了。是什么导致了这个问题,我该如何解决?
io.fabric8.kubernetes.client.KubernetesClientException: too old resource version: 29309228 (33284573)
at kubernetes.client@4.6.4/io.fabric8.kubernetes.client.dsl.internal.WatchConnectionManager.onMessage(WatchConnectionManager.java:263)
at okhttp3.internal.ws.RealWebSocket.onReadMessage(RealWebSocket.java:323)
at okhttp3.internal.ws.WebSocketReader.readMessageFrame(WebSocketReader.java:219)
at okhttp3.internal.ws.WebSocketReader.processNextFrame(WebSocketReader.java:105)
at okhttp3.internal.ws.RealWebSocket.loopReader(RealWebSocket.java:274)
at okhttp3.internal.ws.RealWebSocket.onResponse(RealWebSocket.java:214)
at okhttp3.RealCall$AsyncCall.execute(RealCall.java:203)
at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.base/java.lang.Thread.run(Unknown Source)
我来自 Fabric8 Kubernetes 客户端团队。我认为在 watch 一段时间后给出 410 是 Kubernetes 的标准行为。处理它通常是客户的责任。在手表的上下文中,当您要求查看太旧的 resourceVersion
的更改时,它会 return HTTP_GONE
- 即当它无法再告诉您自那以后发生了什么变化时版本,因为太多的东西已经改变了。在这种情况下,您需要重新开始,不指定 resourceVersion
,在这种情况下,手表会向您发送您正在观看的事物的当前状态,然后从该点发送更新。
Fabric8不处理普通手表。但它在 SharedInformer
API 中处理它,请参阅 ReflectorWatcher。我建议在编写运算符时使用 informer API,因为它比普通的 list 和 watch 更好。这是使用 SharedInformer
API:
的简单示例
try (KubernetesClient client = new DefaultKubernetesClient()) {
SharedInformerFactory sharedInformerFactory = client.informers();
SharedIndexInformer<Pod> podInformer = sharedInformerFactory.sharedIndexInformerFor(Pod.class, PodList.class, 30 * 1000L);
podInformer.addEventHandler(new ResourceEventHandler<Pod>() {
@Override
public void onAdd(Pod pod) {
// Handle Creation
}
@Override
public void onUpdate(Pod oldPod, Pod newPod) {
// Handle update
}
@Override
public void onDelete(Pod pod, boolean deletedFinalStateUnknown) {
// Handle deletion
}
});
sharedInformerFactory.startAllRegisteredInformers();
}
您可以在此处找到使用 Fabric8 SharedInformer API 的简单运算符的完整演示:PodSet Operator In Java
这个解决方法对我有用,我希望它能帮助其他人
每次,我的 pod 都会遇到这个“资源太旧”的错误,它会停止并自行重启。
我发现如果我手动创建资源(以防它是 CRD——甚至是虚拟的)
几乎没有“资源太旧”的异常,因此操作员已启动 运行 并正在收听。
所以,我做了什么:
- 目前正在发生此特定错误:
一种。系统错误(这将重新启动 pod)
b.文本异常 "too old resource version"
- 在平台上创建了新的虚拟 CRD 对象(在 pod 重启之前)
一种。以编程方式 (fabric8),检查虚拟 CRD 是否存在。如果是这样,请将其删除。
b.以编程方式 (fabric8),使用
再次创建虚拟 CRD
- 然后 pod 自行重启(此重启也发生在我的代码更改之前,这不是因为我的代码)
- 当 pod 启动时,它会从虚拟 CRD 中创建秘密。
从那时起,几乎没有重新启动,操作员已启动 运行 并正在收听。
只是不要忘记向操作员的服务帐户授予创建和删除这些资源的权限。
我正在开发一个为不同的 k8s 资源创建监视的操作员。我时不时地在日志中看到以下异常,应用程序就停止了。是什么导致了这个问题,我该如何解决?
io.fabric8.kubernetes.client.KubernetesClientException: too old resource version: 29309228 (33284573)
at kubernetes.client@4.6.4/io.fabric8.kubernetes.client.dsl.internal.WatchConnectionManager.onMessage(WatchConnectionManager.java:263)
at okhttp3.internal.ws.RealWebSocket.onReadMessage(RealWebSocket.java:323)
at okhttp3.internal.ws.WebSocketReader.readMessageFrame(WebSocketReader.java:219)
at okhttp3.internal.ws.WebSocketReader.processNextFrame(WebSocketReader.java:105)
at okhttp3.internal.ws.RealWebSocket.loopReader(RealWebSocket.java:274)
at okhttp3.internal.ws.RealWebSocket.onResponse(RealWebSocket.java:214)
at okhttp3.RealCall$AsyncCall.execute(RealCall.java:203)
at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.base/java.lang.Thread.run(Unknown Source)
我来自 Fabric8 Kubernetes 客户端团队。我认为在 watch 一段时间后给出 410 是 Kubernetes 的标准行为。处理它通常是客户的责任。在手表的上下文中,当您要求查看太旧的 resourceVersion
的更改时,它会 return HTTP_GONE
- 即当它无法再告诉您自那以后发生了什么变化时版本,因为太多的东西已经改变了。在这种情况下,您需要重新开始,不指定 resourceVersion
,在这种情况下,手表会向您发送您正在观看的事物的当前状态,然后从该点发送更新。
Fabric8不处理普通手表。但它在 SharedInformer
API 中处理它,请参阅 ReflectorWatcher。我建议在编写运算符时使用 informer API,因为它比普通的 list 和 watch 更好。这是使用 SharedInformer
API:
try (KubernetesClient client = new DefaultKubernetesClient()) {
SharedInformerFactory sharedInformerFactory = client.informers();
SharedIndexInformer<Pod> podInformer = sharedInformerFactory.sharedIndexInformerFor(Pod.class, PodList.class, 30 * 1000L);
podInformer.addEventHandler(new ResourceEventHandler<Pod>() {
@Override
public void onAdd(Pod pod) {
// Handle Creation
}
@Override
public void onUpdate(Pod oldPod, Pod newPod) {
// Handle update
}
@Override
public void onDelete(Pod pod, boolean deletedFinalStateUnknown) {
// Handle deletion
}
});
sharedInformerFactory.startAllRegisteredInformers();
}
您可以在此处找到使用 Fabric8 SharedInformer API 的简单运算符的完整演示:PodSet Operator In Java
这个解决方法对我有用,我希望它能帮助其他人 每次,我的 pod 都会遇到这个“资源太旧”的错误,它会停止并自行重启。 我发现如果我手动创建资源(以防它是 CRD——甚至是虚拟的) 几乎没有“资源太旧”的异常,因此操作员已启动 运行 并正在收听。 所以,我做了什么:
- 目前正在发生此特定错误: 一种。系统错误(这将重新启动 pod) b.文本异常 "too old resource version"
- 在平台上创建了新的虚拟 CRD 对象(在 pod 重启之前) 一种。以编程方式 (fabric8),检查虚拟 CRD 是否存在。如果是这样,请将其删除。 b.以编程方式 (fabric8),使用 再次创建虚拟 CRD
- 然后 pod 自行重启(此重启也发生在我的代码更改之前,这不是因为我的代码)
- 当 pod 启动时,它会从虚拟 CRD 中创建秘密。
从那时起,几乎没有重新启动,操作员已启动 运行 并正在收听。 只是不要忘记向操作员的服务帐户授予创建和删除这些资源的权限。