«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.
«