【问题标题】:Kubernetes too old resource versionKubernetes 资源版本太旧
【发布时间】:2020-04-24 13:31:31
【问题描述】:

我正在开发一个为不同的 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$1.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$2.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)

【问题讨论】:

    标签: java kubernetes kubernetes-pod fabric8


    【解决方案1】:

    我来自 Fabric8 Kubernetes 客户端团队。我认为在观察一段时间后给出 410 是 Kubernetes 的标准行为。处理它通常是客户的责任。在手表的上下文中,当您要求查看太旧的 resourceVersion 的更改时,它将返回 HTTP_GONE - 即当它不再告诉您自该版本以来发生了什么变化时,因为太多的事情发生了变化.在这种情况下,您需要重新开始,不指定resourceVersion,在这种情况下,手表会向您发送您正在观看的事物的当前状态,然后从该点发送更新。

    Fabric8 不能用普通手表处理它。但它在SharedInformer API 中处理它,请参阅ReflectorWatcher。我建议在编写运算符时使用通知 API,因为它比普通的列表和监视更好。下面是一个使用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

    【讨论】:

    • 很好的例子。如何只观看 configMaps/secrets 呢?在 spring boot 这个句柄 org.springframework.cloud.kubernetes.config.reload.EventBasedConfigurationChangeDetector。问题是当资源太旧且状态为 GONE 时他们不处理这种情况,他们只是关闭观察者并且配置映射不再在应用程序中更新
    • 我认为如果你用 ConfigMap 替换 Pod 这应该可以工作
    • 不,它在 Spring Boot 应用程序中不起作用。我试过了:stackoverflow.com/questions/63719631/…。没有机制如何在 Spring Boot 应用程序中传播这个新对象
    【解决方案2】:

    这个解决方法对我有用,我希望它可以帮助其他人 每次,我的 pod 都会遇到这个“资源太旧”的错误,它会自行停止并重新启动。 我发现如果我手动创建资源(如果它是 CRD - 甚至是虚拟资源) 几乎没有“资源太旧”的例外情况,因此操作员已启动并运行并倾听。 所以,我做了什么:

    1. 目前正在发生此特定错误: 一种。系统错误(将重新启动 pod) 湾。文本“资源版本太旧”的异常
    2. 在平台上创建了新的虚拟 CRD 对象(在重新启动 pod 之前) 一种。以编程方式(fabric8)检查虚拟 CRD 是否存在。如果是这样,请将其删除。 湾。以编程方式 (fabric8),使用
    3. 再次创建虚拟 CRD
    4. 然后 pod 自行重启(这个重启也发生在我的代码更改之前,不是因为我的代码)
    5. 当 pod 启动时,它会从虚拟 CRD 中创建秘密。

    从那时起,几乎没有重新启动,操作员已启动并运行并监听。 只是不要忘记授予操作员的服务帐户创建和删除这些资源的权限。

    【讨论】:

      猜你喜欢
      • 2021-04-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-13
      • 1970-01-01
      • 1970-01-01
      • 2015-02-10
      • 1970-01-01
      相关资源
      最近更新 更多