Поддержка нескольких версий API-интерфейсов Kuberentes в программе Go

#go #kubernetes #polymorphism

#Вперед #kubernetes #полиморфизм

Вопрос:

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

Kubernetes написан на Go и предоставляет пакеты Go, такие как k8s.io/api/extensions/v1beta1 и k8s.io/api/networking/v1beta1 . Ресурсы Kubernetes, например Ingress, сначала выпускаются в одной группе API (расширения), а по мере их совершенствования перемещаются в другую группу API (сеть), а также могут менять версии (например, переходить с v1beta1 простого на обычный v1 ). Kubernetes также обеспечивает k8s.io/client-go взаимодействие с кластером Kubernetes.

Я опытный объектно-ориентированный (и другие типы) программист, но довольно новичок в Go и совершенно не знаком с пакетами Kubernetes. Чего я хочу достичь, так это архитектуры программы, которая позволяет мне писать код один раз и заставлять его работать с любой версией ресурса Kubernetes, по крайней мере, до тех пор, пока ресурс содержит все функции, которые меня интересуют. В типичной объектно-ориентированной среде я бы создал базовый Ingress класс и получил все эти различные версии, производные от него, и упаковал операции, чтобы я мог просто работать Ingress везде. Я считаю, что Go предполагает, что люди используют другой подход, и в любом случае возникают сложности из-за аспекта клиент / сервер.

Клиент / сервер и API

Моя программа Go является клиентом сервера Kubernetes. Различные версии сервера будут поддерживать различные версии API Kubernetes и, следовательно, различные версии входного ресурса. Итак, моя первая проблема заключается в том, что мне нужно сделать что-то подобное, чтобы получить список всех входов:

 ingressesExt, err := il.kubeClient.ExtensionsV1beta1().Ingresses(namespace).List(metav1.ListOptions{})
ingressesNet, err := il.kubeClient.NetworkingV1beta1().Ingresses(namespace).List(metav1.ListOptions{})
  

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

Преобразование типов

Мне также нужно найти какой-то способ объединения ingressesExt и ingressesNet в единый полезный список, с прицелом на удобство обслуживания / расширяемость теперь, когда Ingress перешел на NetworkingV1.

Утилиты Kubernetes

Я вижу, что Kubernetes предоставляет множество автоматически сгенерированных кодов и утилит, но я не нашел много документации о том, как их использовать. Например, Ingress имеет такие функции, как

  • DeepCopy
  • Маршал
  • XXX_DiscardUnknown
  • XXX_Merge
  • XXX_Unmarshal

Может быть, я могу использовать их для преобразования типов? Каким-то образом объединить маршалирование, отмену маршалирования, удаление и слияние, чтобы взять данные из одной версии и импортировать их в другую?

Вопросы

Надеюсь, вы видите проблему и понимаете, чего я пытаюсь достичь.

  • Существуют ли пакеты от Kubernetes или других авторов с открытым исходным кодом, которые добились определенного прогресса в унификации API, как мне нужно?
  • Предназначены ли какие-либо из автоматически сгенерированных функций Kubernetes для общего использования (в отличие от внутреннего использования) и полезны ли они для моей задачи? Я не нашел документации ни для одного, кроме DeepCopy.
  • Каков «путь перехода» к абстрагированию различий между различными версиями объекта Ingress, чтобы я мог написать остальной код для работы с любой версией? Имейте в виду, что мне может потребоваться выполнить еще один вызов API для дальнейшей обработки, и в этом случае мне нужно будет знать конкретный тип объекта и выбрать правильный вызов API. Для меня не очевидно, что client-go обеспечивает какую-либо поддержку для такого автоматического выбора вызовов API.

Комментарии:

1. Методы DeepCopy Marshal и — XXX_ это автоматически сгенерированные gRPC методы / поля, вы можете их игнорировать.