diff --git a/kubernetes/k8s-intro/pom.xml b/kubernetes/k8s-intro/pom.xml
index 26d6a872d4..4a5bb09711 100644
--- a/kubernetes/k8s-intro/pom.xml
+++ b/kubernetes/k8s-intro/pom.xml
@@ -16,6 +16,12 @@
client-java
11.0.0
+
+
+ ch.qos.logback
+ logback-classic
+ 1.2.3
+
diff --git a/kubernetes/k8s-intro/src/main/java/com/baeldung/kubernetes/intro/ApiInvoker.java b/kubernetes/k8s-intro/src/main/java/com/baeldung/kubernetes/intro/ApiInvoker.java
new file mode 100644
index 0000000000..fbc2662170
--- /dev/null
+++ b/kubernetes/k8s-intro/src/main/java/com/baeldung/kubernetes/intro/ApiInvoker.java
@@ -0,0 +1,11 @@
+package com.baeldung.kubernetes.intro;
+
+import io.kubernetes.client.openapi.ApiCallback;
+import io.kubernetes.client.openapi.ApiException;
+import io.kubernetes.client.openapi.apis.CoreV1Api;
+import okhttp3.Call;
+
+@FunctionalInterface
+public interface ApiInvoker {
+ Call apply(CoreV1Api api, ApiCallback callback) throws ApiException;
+}
diff --git a/kubernetes/k8s-intro/src/main/java/com/baeldung/kubernetes/intro/AsyncHelper.java b/kubernetes/k8s-intro/src/main/java/com/baeldung/kubernetes/intro/AsyncHelper.java
new file mode 100644
index 0000000000..d9c29dcb64
--- /dev/null
+++ b/kubernetes/k8s-intro/src/main/java/com/baeldung/kubernetes/intro/AsyncHelper.java
@@ -0,0 +1,74 @@
+package com.baeldung.kubernetes.intro;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Future;
+import java.util.function.BiFunction;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import io.kubernetes.client.openapi.ApiCallback;
+import io.kubernetes.client.openapi.ApiException;
+import io.kubernetes.client.openapi.apis.CoreV1Api;
+import okhttp3.Call;
+
+public class AsyncHelper implements ApiCallback {
+
+ private static final Logger log = LoggerFactory.getLogger(AsyncHelper.class);
+
+ private CoreV1Api api;
+ private CompletableFuture callResult;
+
+ private AsyncHelper(CoreV1Api api) {
+ this.api = api;
+ }
+
+ public static CompletableFuture doAsync(CoreV1Api api, ApiInvoker invoker) {
+
+ AsyncHelper p = new AsyncHelper<>(api);
+ return p.execute(invoker);
+ }
+
+ private CompletableFuture execute( ApiInvoker invoker) {
+
+ try {
+ callResult = new CompletableFuture<>();
+ log.info("[I38] Calling API...");
+ final Call call = invoker.apply(api,this);
+ log.info("[I41] API Succesfully invoked: method={}, url={}",
+ call.request().method(),
+ call.request().url());
+ return callResult;
+ }
+ catch(ApiException aex) {
+ callResult.completeExceptionally(aex);
+ return callResult;
+ }
+ }
+
+ @Override
+ public void onFailure(ApiException e, int statusCode, Map> responseHeaders) {
+ log.error("[E53] onFailure",e);
+ callResult.completeExceptionally(e);
+ }
+
+ @Override
+ public void onSuccess(R result, int statusCode, Map> responseHeaders) {
+ log.error("[E61] onSuccess: statusCode={}",statusCode);
+ callResult.complete(result);
+ }
+
+ @Override
+ public void onUploadProgress(long bytesWritten, long contentLength, boolean done) {
+ log.info("[E61] onUploadProgress: bytesWritten={}, contentLength={}, done={}",bytesWritten,contentLength,done);
+ }
+
+ @Override
+ public void onDownloadProgress(long bytesRead, long contentLength, boolean done) {
+ log.info("[E75] onDownloadProgress: bytesRead={}, contentLength={}, done={}",bytesRead,contentLength,done);
+ }
+}
+
diff --git a/kubernetes/k8s-intro/src/main/java/com/baeldung/kubernetes/intro/ListNodesAsync.java b/kubernetes/k8s-intro/src/main/java/com/baeldung/kubernetes/intro/ListNodesAsync.java
new file mode 100644
index 0000000000..acd4512196
--- /dev/null
+++ b/kubernetes/k8s-intro/src/main/java/com/baeldung/kubernetes/intro/ListNodesAsync.java
@@ -0,0 +1,50 @@
+/**
+ *
+ */
+package com.baeldung.kubernetes.intro;
+
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import io.kubernetes.client.openapi.ApiClient;
+import io.kubernetes.client.openapi.apis.CoreV1Api;
+import io.kubernetes.client.openapi.models.V1NodeList;
+import io.kubernetes.client.util.Config;
+
+/**
+ * @author Philippe
+ *
+ */
+public class ListNodesAsync {
+
+ private static Logger log = LoggerFactory.getLogger(ListNodesAsync.class);
+ /**
+ * @param args
+ */
+ public static void main(String[] args) throws Exception {
+
+ // Initial setup
+ ApiClient client = Config.defaultClient();
+ CoreV1Api api = new CoreV1Api(client);
+
+ // Start async call
+ CompletableFuture p = AsyncHelper.doAsync(api,(capi,cb) ->
+ capi.listNodeAsync(null, null, null, null, null, null, null, null, 10, false, cb)
+ );
+
+ p.thenAcceptAsync((nodeList) -> {
+ log.info("[I40] Processing results...");
+ nodeList.getItems()
+ .stream()
+ .forEach((node) -> System.out.println(node.getMetadata()));
+ });
+
+ log.info("[I46] Waiting results...");
+ p.get(10, TimeUnit.SECONDS);
+ }
+
+}
diff --git a/kubernetes/k8s-intro/src/main/java/com/baeldung/kubernetes/intro/ListPodsPaged.java b/kubernetes/k8s-intro/src/main/java/com/baeldung/kubernetes/intro/ListPodsPaged.java
new file mode 100644
index 0000000000..1c160ae607
--- /dev/null
+++ b/kubernetes/k8s-intro/src/main/java/com/baeldung/kubernetes/intro/ListPodsPaged.java
@@ -0,0 +1,46 @@
+/**
+ *
+ */
+package com.baeldung.kubernetes.intro;
+
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import io.kubernetes.client.openapi.ApiClient;
+import io.kubernetes.client.openapi.apis.CoreV1Api;
+import io.kubernetes.client.openapi.models.V1NodeList;
+import io.kubernetes.client.openapi.models.V1PodList;
+import io.kubernetes.client.util.Config;
+
+/**
+ * @author Philippe
+ *
+ */
+public class ListPodsPaged {
+
+ private static final Logger log = LoggerFactory.getLogger(ListPodsPaged.class);
+
+ /**
+ * @param args
+ */
+ public static void main(String[] args) throws Exception {
+
+ ApiClient client = Config.defaultClient();
+ CoreV1Api api = new CoreV1Api(client);
+ String continuationToken = null;
+ int limit = 2; // Just for illustration purposes. Real world values would range from ~100 to ~1000/page
+ Long remaining = null;
+ do {
+ log.info("==========================================================================");
+ log.info("Retrieving data: continuationToken={}, remaining={}", continuationToken,remaining);
+ V1PodList items = api.listPodForAllNamespaces(null, continuationToken, null, null, limit, null, null, null, 10, false);
+ continuationToken = items.getMetadata().getContinue();
+ remaining = items.getMetadata().getRemainingItemCount();
+ items.getItems()
+ .stream()
+ .forEach((node) -> System.out.println(node.getMetadata()));
+ } while( continuationToken != null );
+ }
+
+}
diff --git a/kubernetes/k8s-intro/src/test/java/com/baeldung/kubernetes/intro/ListNodesAsyncLiveTest.java b/kubernetes/k8s-intro/src/test/java/com/baeldung/kubernetes/intro/ListNodesAsyncLiveTest.java
new file mode 100644
index 0000000000..af32df8224
--- /dev/null
+++ b/kubernetes/k8s-intro/src/test/java/com/baeldung/kubernetes/intro/ListNodesAsyncLiveTest.java
@@ -0,0 +1,10 @@
+package com.baeldung.kubernetes.intro;
+
+import org.junit.jupiter.api.Test;
+
+class ListNodesAsyncLiveTest {
+ @Test
+ void whenListNodes_thenSuccess() throws Exception {
+ ListNodesAsync.main(new String[] {});
+ }
+}
diff --git a/kubernetes/k8s-intro/src/test/java/com/baeldung/kubernetes/intro/ListPodsPagedLiveTest.java b/kubernetes/k8s-intro/src/test/java/com/baeldung/kubernetes/intro/ListPodsPagedLiveTest.java
new file mode 100644
index 0000000000..6fb3c5b32d
--- /dev/null
+++ b/kubernetes/k8s-intro/src/test/java/com/baeldung/kubernetes/intro/ListPodsPagedLiveTest.java
@@ -0,0 +1,10 @@
+package com.baeldung.kubernetes.intro;
+
+import org.junit.jupiter.api.Test;
+
+class ListPodsPagedLiveTest {
+ @Test
+ void whenListPodsPage_thenSuccess() throws Exception {
+ ListPodsPaged.main(new String[] {});
+ }
+}
diff --git a/kubernetes/k8s-intro/src/test/resources/logback.xml b/kubernetes/k8s-intro/src/test/resources/logback.xml
new file mode 100644
index 0000000000..479545e643
--- /dev/null
+++ b/kubernetes/k8s-intro/src/test/resources/logback.xml
@@ -0,0 +1,11 @@
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+