«1. Введение

В этом руководстве мы покажем, как использовать API Kubernetes из приложений Java, используя его официальную клиентскую библиотеку.

2. Зачем использовать Kubernetes API?

В настоящее время можно с уверенностью сказать, что Kubernetes стал стандартом де-факто для управления контейнерными приложениями. Он предлагает богатый API, который позволяет нам развертывать, масштабировать и отслеживать приложения и связанные с ними ресурсы, такие как хранилище, секреты и переменные среды. На самом деле, один из способов представить этот API — это распределенный аналог системных вызовов, доступных в обычной операционной системе.

Большую часть времени наши приложения могут игнорировать тот факт, что они работают в Kubernetes. Это хорошо, так как позволяет нам разрабатывать их локально и с помощью нескольких команд и заклинаний YAML быстро развертывать их на нескольких облачных провайдерах с небольшими изменениями.

Тем не менее, есть несколько интересных случаев использования, когда нам нужно обратиться к API Kubernetes для достижения определенных функций:

    Запустить внешнюю программу для выполнения какой-либо задачи, а затем получить статус ее завершения. сервис в ответ на запрос клиента. Создайте настраиваемую панель мониторинга для решения, работающего в нескольких кластерах Kubernetes, даже между облачными провайдерами. их довольно просто достичь.

Кроме того, поскольку Kubernetes API является открытой спецификацией, мы можем быть уверены, что наш код будет работать без каких-либо изменений в любой сертифицированной реализации.

3. Локальная среда разработки

Самое первое, что нам нужно сделать, прежде чем мы перейдем к созданию приложения, — это получить доступ к работающему кластеру Kubernetes. Хотя для этого мы можем использовать поставщика общедоступного облака, локальная среда обычно обеспечивает больший контроль над всеми аспектами ее настройки.

Есть несколько облегченных дистрибутивов, подходящих для этой задачи:

K3S Minikube Kind

    Фактические шаги установки выходят за рамки этой статьи, но какой бы вариант вы ни выбрали, просто убедитесь, что kubectl работает нормально, прежде чем начать любое развитие.

4. Зависимости Maven

Во-первых, давайте добавим зависимость Java API Kubernetes в pom.xml нашего проекта:

Последнюю версию client-java можно загрузить с Maven Central.

<dependency>
    <groupId>io.kubernetes</groupId>
    <artifactId>client-java</artifactId>
    <version>11.0.0</version>
</dependency>

5. Привет, Kubernetes

Теперь давайте создадим очень простое приложение Kubernetes, которое будет отображать список доступных узлов вместе с некоторой информацией о них.

Несмотря на свою простоту, это приложение иллюстрирует необходимые шаги, которые мы должны выполнить, чтобы подключиться к работающему кластеру и выполнить вызов API. Независимо от того, какой API мы используем в реальном приложении, эти шаги всегда будут одинаковыми.

5.1. Инициализация ApiClient

Класс ApiClient — один из самых важных классов в API, поскольку он содержит всю логику для выполнения вызова к серверу API Kubernetes. Рекомендуемый способ создания экземпляра этого класса — использование одного из доступных статических методов класса Config. В частности, проще всего это сделать с помощью метода defaultClient():

Использование этого метода гарантирует, что наш код будет работать как удаленно, так и внутри кластера. Кроме того, он автоматически выполнит те же шаги, что и утилита kubectl, чтобы найти файл конфигурации

ApiClient client = Config.defaultClient();

Файл конфигурации, определенный переменной среды KUBECONFIG $HOME/.kube/config Токен учетной записи службы в /var/run/secrets/kubernetes. io/serviceaccount Прямой доступ к http://localhost:8080

    Третий шаг — это тот, который позволяет нашему приложению работать внутри кластера как часть любого модуля, если соответствующая учетная запись службы доступна для Это.

Также обратите внимание, что если в файле конфигурации определено несколько контекстов, эта процедура выберет «текущий» контекст, определенный с помощью команды kubectl config set-context.

5.2. Создание заглушки API

«Получив экземпляр ApiClient, мы можем использовать его для создания заглушки для любого из доступных API. В нашем случае мы будем использовать класс CoreV1Api, который содержит метод, необходимый для получения списка доступных узлов:

Здесь мы используем уже существующий ApiClient для создания заглушки API.

CoreV1Api api = new CoreV1Api(client);

Обратите внимание, что также доступен конструктор без аргументов, но в целом мы должны воздерживаться от его использования. Причиной отказа от его использования является тот факт, что внутри он будет использовать глобальный ApiClient, который должен быть предварительно установлен с помощью Configuration.setDefaultApiClient(). Это создает неявную зависимость от того, кто вызывает этот метод перед использованием заглушки, что, в свою очередь, может привести к ошибкам во время выполнения и проблемам обслуживания.

Лучшим подходом является использование любого фреймворка внедрения зависимостей для первоначального связывания, внедряя полученную заглушку везде, где это необходимо.

5.3. Вызов API Kubernetes

Наконец, давайте перейдем к фактическому вызову API, который возвращает доступные узлы. В заглушке CoreApiV1 есть метод, который делает именно это, так что это становится тривиальным:

В нашем примере мы передаем null для большинства параметров метода, поскольку они являются необязательными. Последние два параметра актуальны для всех вызовов listXXX, так как они определяют время ожидания вызова и является ли это вызовом Watch или нет. Проверка подписи метода показывает оставшиеся аргументы:

V1NodeList nodeList = api.listNode(null, null, null, null, null, null, null, null, 10, false);
nodeList.getItems()
  .stream()
  .forEach((node) -> System.out.println(node));

В этом кратком введении мы просто проигнорируем аргументы подкачки, просмотра и фильтрации. Возвращаемое значение в этом случае представляет собой POJO с Java-представлением возвращаемого документа. Для этого вызова API документ содержит список объектов V1Node с несколькими фрагментами информации о каждом узле. Вот типичный вывод, выдаваемый этим кодом на консоли:

public V1NodeList listNode(
  String pretty,
  Boolean allowWatchBookmarks,
  String _continue,
  String fieldSelector,
  String labelSelector,
  Integer limit,
  String resourceVersion,
  String resourceVersionMatch,
  Integer timeoutSeconds,
  Boolean watch) {
    // ... method implementation
}

Как мы видим, доступно довольно много информации. Для сравнения, это эквивалентный вывод kubectl с настройками по умолчанию:

class V1Node {
    metadata: class V1ObjectMeta {
        labels: {
            beta.kubernetes.io/arch=amd64,
            beta.kubernetes.io/instance-type=k3s,
            // ... other labels omitted
        }
        name: rancher-template
        resourceVersion: 29218
        selfLink: null
        uid: ac21e09b-e3be-49c3-9e3a-a9567b5c2836
    }
    // ... many fields omitted
    status: class V1NodeStatus {
        addresses: [class V1NodeAddress {
            address: 192.168.71.134
            type: InternalIP
        }, class V1NodeAddress {
            address: rancher-template
            type: Hostname
        }]
        allocatable: {
            cpu=Quantity{number=1, format=DECIMAL_SI},
            ephemeral-storage=Quantity{number=18945365592, format=DECIMAL_SI},
            hugepages-1Gi=Quantity{number=0, format=DECIMAL_SI},
            hugepages-2Mi=Quantity{number=0, format=DECIMAL_SI},
            memory=Quantity{number=8340054016, format=BINARY_SI}, 
            pods=Quantity{number=110, format=DECIMAL_SI}
        }
        capacity: {
            cpu=Quantity{number=1, format=DECIMAL_SI},
            ephemeral-storage=Quantity{number=19942490112, format=BINARY_SI}, 
            hugepages-1Gi=Quantity{number=0, format=DECIMAL_SI}, 
            hugepages-2Mi=Quantity{number=0, format=DECIMAL_SI}, 
            memory=Quantity{number=8340054016, format=BINARY_SI}, 
            pods=Quantity{number=110, format=DECIMAL_SI}}
        conditions: [
            // ... node conditions omitted
        ]
        nodeInfo: class V1NodeSystemInfo {
            architecture: amd64
            kernelVersion: 4.15.0-135-generic
            kubeProxyVersion: v1.20.2+k3s1
            kubeletVersion: v1.20.2+k3s1
            operatingSystem: linux
            osImage: Ubuntu 18.04.5 LTS
            // ... more fields omitted
        }
    }
}

6. Заключение

[email protected]:~# kubectl get nodes
NAME               STATUS   ROLES                  AGE   VERSION
rancher-template   Ready    control-plane,master   24h   v1.20.2+k3s1

В этой статье мы представили краткое введение в API Kubernetes для Java. В следующих статьях мы углубимся в этот API и рассмотрим некоторые его дополнительные функции:

Объяснить разницу между доступными вариантами вызовов API. Использование Watch для мониторинга событий кластера в реальном времени. Как использовать подкачку для эффективного извлечения большого тома. данных из кластера

    Как обычно, полный исходный код примеров можно найти на GitHub.

«