K8s JavaClient watch Pod检测状态变更、和Read timed out异常

watch

k8s很多命令都有watch机制,持续检测状态变化,如pod列表,如果pod状态发生变化,就会输出

kubectl get pod -w   或者--watch

JAVA Cient watch podList

官网介绍:https://kubernetes.io/zh/docs/reference/using-api/api-concepts/#standard-api-terminology

K8sJavaClient官方github有一个watch namespace的例子,https://github.com/kubernetes-client/java/blob/master/examples/examples-release-11/src/main/java/io/kubernetes/client/examples/WatchExample.java

我们改成watchpod列表。watch 命名空间为default、标签为userId=user1Id的pod,将listNamespacedPodCall方法的watch参数设置为true

    @BeforeAll
    public static void connectK8s() throws IOException {
        String kubeConfigPath = "config";
        //加载k8s, config
        client = ClientBuilder.kubeconfig(KubeConfig.loadKubeConfig(new FileReader(kubeConfigPath))).build();
        //设置http的读取超时时间,设置为0永远不超时,但不安全,如果watch的时间大于此时间,则会socket read timeout异常
        client.setReadTimeout(20000);
        Configuration.setDefaultApiClient(client);
    }


@Test
    public void watchPod() throws ApiException, InterruptedException, IOException {
        System.out.println("重新访问");
        CoreV1Api api = new CoreV1Api();
        Call call = api.listNamespacedPodCall("default", null, null, null, null,
                    "userId=user1Id",
                null, null, null, true, new ApiCallback() {
                    public void onFailure(ApiException e, int statusCode, Map responseHeaders) {
                        System.out.println("fail");
                    }

                    public void onSuccess(Object result, int statusCode, Map responseHeaders) {
                        System.out.println("sucess" + statusCode + result);
                    }

                    public void onUploadProgress(long bytesWritten, long contentLength, boolean done) {
                        System.out.println("upload");
                    }

                    public void onDownloadProgress(long bytesRead, long contentLength, boolean done) {
                        System.out.println("download");
                    }
                });

        Watch<V1Pod> watch = Watch.createWatch(
                client,
                call,
                new TypeToken<Watch.Response<V1Pod>>() {
                }.getType());

        try {
            for (Watch.Response<V1Pod> item : watch) {
                System.out.printf("%s : %s : %s%n", item.object.getMetadata().getName(), item.type, item.object.getStatus().getPhase());
            }
        } finally {
            watch.close();
           
        }
}

SocketTimeoutException: Read timed out

按官方例子,大概10s后会报出超时异常。

在官方github的Issues中找到答案,这方面中文资料少,要多看官方文档,有问题在github的Issues找也是很好的办法。https://github.com/kubernetes-client/java/issues/287

原因是watch是一直持续,时间超出了httpclient默认的时间。k8sjavaclient发起http调用默认使用的是OkHttpClient,所以在OkHttpClient设置超时时间即可。listNamespacedPodCall方法的timeout参数要小于okhttpclient的超时参数。

    @BeforeAll
    public static void connectK8s() throws IOException {
        String kubeConfigPath = "config";
        //加载k8s, config
        client = ClientBuilder.kubeconfig(KubeConfig.loadKubeConfig(new FileReader(kubeConfigPath))).build();
        //设置http的读取超时时间,设置为0永远不超时,但不安全,如果watch的时间大于此时间,则会socket read timeout异常
        client.setReadTimeout(20000);
        Configuration.setDefaultApiClient(client);
    }

如果设置为0,没有读取超时限制,但k8sgit上的管理员不建议这么做,他认为网络不稳定、建议在循环中watch。其实程序如果没及时关掉连接,导致k8s apiserver浪费很多连接、压力大,所以不应该watch时间太长,并且及时关闭掉watch连接。

猜你喜欢

转载自blog.csdn.net/u014203449/article/details/110917661