#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 методы / поля, вы можете их игнорировать.