1. 소개

이 예제에서는 Java용 Kubernetes API를 계속 탐색합니다 . 이번에는 두 가지 기능인 페이징 및 비동기 호출 에 중점을 둘 것입니다 .

2. 페이징

간단히 말해서 페이징 을 사용하면 청크(페이지)의 큰 결과 집합을 반복할 수 있으므로 이 메서드의 이름이 붙여졌습니다. Kubernetes Java API 컨텍스트에서 이 기능은 리소스 List을 반환하는 모든 메서드에서 사용할 수 있습니다 . 이러한 메서드에는 결과를 반복하는 데 사용할 수 있는 두 개의 선택적 매개 변수가 항상 포함됩니다.

  • limit : 단일 API 호출에서 반환되는 최대 항목 수
  • continue반환된 결과 세트의 시작점을 서버에 알리는 연속 토큰

이러한 매개변수를 사용하여 서버에 너무 많은 부담을 주지 않고 임의 개수의 항목을 반복할 수 있습니다. 더 좋은 점은 결과를 저장하기 위해 클라이언트 측에 필요한 메모리의 양도 제한되어 있다는 것입니다.

이제 이러한 매개변수를 사용하여 이 방법을 사용하여 클러스터에서 사용 가능한 모든 포드 List을 가져오는 방법을 살펴보겠습니다.

ApiClient client = Config.defaultClient();
CoreV1Api api = new CoreV1Api(client);
String continuationToken = null;
do {
    V1PodList items = api.listPodForAllNamespaces(
      null,
      continuationToken, 
      null,
      null, 
      2, 
      null, 
      null,
      null,
      10,
      false);
    continuationToken = items.getMetadata().getContinue();
    items.getItems()
      .stream()
      .forEach((node) -> System.out.println(node.getMetadata()));
} while (continuationToken != null);

여기서  listPodForAllNamespaces() API 호출에 대한 두 번째 매개변수에는 연속 토큰이 포함되고 다섯 번째 매개변수는 제한  매개변수입니다. 한도 는 일반적으로 고정된 값이지만  계속  하려면 약간의 추가 노력이 필요합니다.

첫 번째 호출의 경우 페이지 요청 시퀀스의 첫 번째 호출임을 서버에 알리는 null 을 보냅니다  . 응답을 받으면 해당 List 메타데이터 필드에서 사용할 다음 계속 값에 대한 새 값을 가져옵니다.

더 이상 사용할 수 있는 결과가 없으면 이 값은 null 이 되므로 이 사실을 사용하여 반복 루프의 종료 조건을 정의합니다.

2.1. 페이지 매김 문제

페이징 메커니즘은 매우 간단하지만 염두에 두어야 할 몇 가지 세부 사항이 있습니다.

  • 현재 API는 서버측 정렬을 지원하지 않습니다. 현재 정렬에 대한 스토리지 수준 지원이 부족하다는 점을 감안할 때 이는 곧 변경되지 않을 것입니다.
  • continue 를 제외한 모든 호출 매개변수 는 호출 간에 동일해야 합니다.
  • 계속 값 은  불투명 핸들로 처리되어야 합니다. 우리는 그 가치에 대해 어떤 가정도 해서는 안 됩니다.
  • 반복은 단방향 입니다. 이전에 받은 계속  토큰 을 사용하여 결과 집합으로 돌아갈 수 없습니다. 
  • 반환된 List 메타데이터에 남아 있는 항목 수 필드가 포함되어 있지만 해당 값은 신뢰할 수 없으며 모든 구현에서 지원되지 않습니다.

2.2. 데이터 일관성 나열

Kubernetes 클러스터는 매우 동적인 환경이므로 페이지가 매겨진 호출 시퀀스와 연결된 결과 집합이 클라이언트에서 읽는 동안 수정될 가능성이 있습니다 . 이 경우 Kubernetes API는 어떻게 작동합니까?

쿠버네티스 문서 에 설명된 대로 List API는  resourceVersionMatch 와 함께 포함할 특정 버전을 선택하는 방법을 정의하는 resourceVersion 매개변수를 지원합니다. 그러나 페이징된 결과 집합의 경우 동작은 항상 동일합니다. "계속 토큰, 정확함".

이는 반환된 리소스 버전이 페이지가 매겨진 List 호출이 시작되었을 때 사용 가능한 버전과 일치함을 의미합니다. 이 접근 방식은 일관성을 제공하지만 나중에 수정된 결과는 포함하지 않습니다. 예를 들어 대규모 클러스터의 모든 포드에 대한 반복 작업을 완료할 때쯤에는 일부 포드가 이미 종료되었을 수 있습니다.

3. 비동기 호출

지금까지 쿠버네티스 API를 동기 방식으로 사용했는데, 이는 간단한 프로그램에는 괜찮지만 리소스 사용 관점에서는 별로 효율적이지 않습니다. 클러스터에서 응답을 받아 처리할 때까지 호출 스레드를 차단하기 때문입니다. 이 동작은 예를 들어 GUI 스레드에서 이러한 호출을 시작하는 경우 애플리케이션의 응답성을 심하게 손상시킵니다.

다행스럽게도 라이브러리는 호출자에게 즉시 컨트롤을 반환하는 콜백 기반의 비동기 모드를 지원합니다 .

CoreV1Api 클래스를 검사하면 각 동기식 xxx() 메서드에 대해 xxxAsync()  변형도 있음을 알 수 있습니다. 예를 들어 listPodForAllNamespaces() 에 대한 비동기 메서드 listPodForAllNamespacesAsync  () 입니다. 콜백 구현을 위한 추가 매개변수가 추가된 인수는 동일합니다.

3.1. 콜백 세부 정보

콜백 매개변수 개체는 네 가지 메서드만 포함 하는 일반 인터페이스 ApiCallback<T> 를 구현해야 합니다.

  • onSuccess: 호출이 성공한 경우에만 호출됩니다. 첫 번째 인수 유형은 동기 버전에서 반환되는 것과 동일합니다.
  • onFailure:  서버를 호출하는 중 오류가 발생했거나 회신에 오류 코드가 포함되어 호출되었습니다.
  • onUploadProgress : 업로드 중에 호출됩니다. 이 콜백을 사용하여 긴 작업 중에 사용자에게 피드백을 제공할 수 있습니다.
  • onDownloadProgressonUploadProgress 와 동일 하지만 다운로드용

비동기 호출도 일반 결과를 반환하지 않습니다. 대신 진행 중인 호출에 대한 핸들로 작동 하는 OkHttp (Kubernetes API에서 사용하는 기본 REST 클라이언트) 호출 인스턴스를 반환합니다. 이 개체를 사용하여 완료 상태를 폴링하거나 원하는 경우 완료 전에 취소할 수 있습니다.

3.2. 비동기 호출 예

상상할 수 있듯이 모든 곳에서 콜백을 구현하려면 많은 상용구 코드가 필요합니다. 이를 방지하기 위해 이 작업을 약간 단순화 하는 호출 도우미 를 사용합니다.

// Start async call
CompletableFuture<V1NodeList> p = AsyncHelper.doAsync(api,(capi,cb) ->
  capi.listNodeAsync(null, null, null, null, null, null, null, null, 10, false, cb)
);
p.thenAcceptAsync((nodeList) -> {
    nodeList.getItems()
      .stream()
      .forEach((node) -> System.out.println(node.getMetadata()));
});
// ... do something useful while we wait for results

여기서 도우미는 비동기 호출 호출을 래핑하고 이를 보다 표준 적인 CompletableFuture 에 적용합니다 . 이를 통해 Reactor 프로젝트 와 같은 다른 라이브러리와 함께 사용할 수 있습니다 . 이 예에서는 모든 메타데이터를 표준 출력에 인쇄하는 완료 단계를 추가했습니다.

늘 그렇듯이 선물을 다룰 때 발생할 수 있는 동시성 문제를 인식해야 합니다. 이 코드의 온라인 버전에는 이 간단한 코드의 경우에도 최소한 세 개의 스레드가 사용되었음을 명확하게 보여주는 몇 가지 디버깅 로그가 포함되어 있습니다.

  • 비동기 호출을 시작 하는 메인 스레드
  • 실제 HTTP 호출을 만드는 데 사용되는 OkHttp의 스레드
  • 결과가 처리되는 완료 스레드

4. 결론

이 기사에서는 Kubernetes Java API로 페이징 및 비동기 호출을 사용하는 방법을 살펴보았습니다.

늘 그렇듯이 예제의 전체 소스 코드는  GitHub 에서 찾을 수 있습니다 .

Generic footer banner