Kubernetes Stateful Sets - отображение существующих идентификаторов в постоянные / сохраняющие состояние модули - PullRequest
0 голосов
/ 22 февраля 2020

Заранее спасибо всем, кто помогает.

Здравствуйте, у меня есть несколько уникальных проблем, довольно длинных для объяснения, но я думаю, что если мы решим их, мы сможем расширить варианты использования Kubernetes. Я думаю, что знаю, как ее решить, но я не уверен, поддерживает ли Kubernetes Stateful Sets это решение. Позвольте мне уточнить суть проблемы, саму проблему, а затем некоторые из моих примеров решений, и, возможно, кто-то может помочь заполнить пробелы.

Пространство доменов :

  • У меня есть набор учетных записей (внешних для kubernetes) {Account_A, Account_B, Account_ C, et c.}
  • Учетные записи могут быть активными или неактивными в любое время (Важно: в NO ОСОБЫЙ ЗАКАЗ).
  • Если эта функция активирована, развертывается модуль, обслуживающий эту учетную запись и сохраняющий постоянный том со всем рабочим пространством / данными этих учетных записей. С этой учетной записью взаимодействует ее уникальный идентификатор модуля и IP.
  • Если этот параметр отключен, модуль удаляется, но данные сохраняются, поэтому при следующей активации он будет связан с тем же постоянным томом. -claim и, следовательно, иметь доступ к своим предыдущим данным.
  • При повторной активации модуль повторно развертывается, используя предыдущее утверждение постоянного тома, чтобы возобновить работу с данными предыдущих сеансов

Очевидно, что, глядя на доступные инструменты / объекты Kubernetes, набор состояний с поддержкой безголового обслуживания - идеальный способ приблизиться к этому. Он поддерживает уникальные модули, которым назначены уникальные IP-адреса, и поддерживает постоянные тома. Он также поддерживает динамическое выделение постоянных томов через

Проблема:

Как уже упоминалось в домене, учетные записи могут быть активны в любом порядке, но блоки с установленным состоянием порядковый номер, означающий, что pod_1 должен быть активным, чтобы pod_2 был активным, а pod_3 - активным и т. д. c. Мы не можем иметь pod_1 активным и pod_3 активным, в то время как pod_2 неактивен. Это означает, что если я включу Account_A, то Account_ C, будет создан модуль с именем pod_1, а затем будет создан модуль с именем pod_2.

Теперь вы можете сказать, что это не проблема. Мы просто держим карту, которая отображает каждую учетную запись на относительный номер_под_для. Например, Account_A -> pod_1 и Account_ C -> pod_2

Почему это проблема? Потому что при указании volumeClaimTemplate в множестве состояний постоянные заявки-объемы используют имя модуля в качестве идентификатора при создании. Это означает, что только модуль с одинаковым именем может получить доступ к одним и тем же данным. Данные (объемы) связаны на основе имени модуля, а не учетной записи. Это создает разрыв между учетными записями и их постоянными томами. Любой модуль с именем pod_2 всегда будет иметь те же данные, что и pod_2, независимо от того, какая учетная запись была «привязана» к pod_2.

Позвольте мне далее проиллюстрировать это на примере:

1. Account_A=disabled, Account_B=disabled, Account_C=disabled (Start state, all accs disabled)
2. Account_A=enabled, Account_B=enabled, Account_C=enabled -> (All accounts are enabled)
    pod_1 is created (with volume_1) and mapped to Account_A
    pod_2 is created (with volume_2) and mapped to Account_B
    pod_3 is created (with volume_3) and mapped to Account_C
3. Account_A=disabled, Account_B=disabled, Account_C=disabled (All Accounts are disabled)
    pod_1 is deleted, volume_1 persists
    pod_2 is deleted, volume_2 persists
    pod_3 is deleted, volume_3 persists
4. Account_A=enabled, Account_B=disabled, Account_C=enabled (re-enable A and C but leave B disabled)
    pod_1 is created (with volume_1) and mapped to Account_A (THIS IS FINE)
    pod_2 is created (with **volume_2**) and mapped to Account_C (THIS IS **NOT** FINE)

Вы видите проблему? Account_ C теперь использует хранилище данных, которое должно принадлежать Account_B (том_2 был создан и использован account_b, а не Account_ C), поскольку тома / утверждения сопоставляются по имени с именами модуля, а модули имеют быть порядковым, т. е. pod_1, затем pod_2.

Потенциальные решения

  1. Уметь поддерживать пользовательские неординарные имена для модулей в наборе состояний , (Самый простой и эффективный)

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

    (ps) Я знаю, что наборы состояний должны быть порядковыми для гарантий упорядочения, но вы можете отключить это с помощью "podManagementPolicy" : Parallel "

  2. Какой-нибудь способ сделать это с метками и селекторами вместо этого?

    Я довольно новичок в Kubernetes, и я все еще не до конца понимаю все движущиеся части. Может быть, есть какой-то способ использовать метки в томе VolumeClaimtemplate, чтобы привязать тома к томам с определенной меткой. т.е. Account_ C, сопоставленный с pod_2, может запросить volume_3, потому что volume_3 имеет метку с: account = Account_ C. Я сейчас смотрю на это. Если это помогает, мои постоянные тома динамически выделяются с помощью этого инструмента: https://github.com/kubernetes-incubator/external-storage/tree/master/nfs-client Может быть, я могу каким-то образом изменить его, чтобы он добавлял определенные метки к создаваемым им постоянным томам.

  3. Отключение наборов состояний и развертываний состояний и просто добавление модулей в кластер вручную

    Это не очень хорошее решение, поскольку, согласно документам, модули не должны существовать без набора состояний или развертывания в качестве родителя, и он также удаляет все встроенные функции постоянных томов и динамического предоставления томов c и т. д. c. Для меня в соглашателе не используются тома VolumeClaimTemplates, которые при развертывании создают или привязывают к существующему VolumeClaim. Если бы я мог как-то воссоздать это, это решение сработало бы.

  4. Создать пользовательский объект Kubernetes, чтобы сделать это для меня

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

  5. Необходимо установить постоянное хранилище из контейнера контейнера. Это последнее средство, поскольку оно полностью устраняет необходимость в kubernetes. Это также означает, что я должен отправить информацию о соединении в контейнер внутри модуля и открыть там целую банку червей с безопасностью и аутентификацией.

Я буду обновлять все, что найду или подумаю из. Спасибо всем, кто помогает.

Ответы [ 2 ]

2 голосов
/ 22 февраля 2020

Мне кажется, что вы убеждены, что StatefulSets - это шаг в правильном направлении, но это не совсем так.

StatefulSets имеют ординальность по двум причинам:

  • Создание упорядоченного PersistentVolumeClaims
  • Возможность создания конечных точек FQDN для отдельных модулей (с использованием службы без заголовка)

В вашем случае ни одно из этих утверждений не соответствует действительности. Вам просто нужно стабильное хранилище для каждой учетной записи. Хотя вы думаете, что # 4 из ваших потенциальных решений наиболее универсален, это самый «родной» Kubernetes способ сделать это.

Решение

Вам нужно написать компонент, который управляет StatefulSet или даже развертывание для каждой учетной записи. Я говорю о развертывании, потому что вам не нужны стабильные сетевые идентификаторы для каждого модуля. Служба ClusterIP для каждой учетной записи будет достаточна для связи.

В мире Kubernetes эти компоненты называются контроллерами (без пользовательских объектов) и операторами (с пользовательскими объектами / управляющими приложениями).

Вы можете начать с просмотра operator-sdk и controller-runtime . Оператор SDK объединяет часто используемые функции поверх controller-runtime в качестве основы. Это также облегчает жизнь разработчиков благодаря включению kubebuilder , который используется для генерации кода API CRD и K8S для пользовательских объектов. Все, что вам нужно определить, это struct s для вашего пользовательского объекта и контроллера.

Взгляните на Operator SDK, вы обнаружите, что создание и управление пользовательскими объектами не так уж сложно.

Пользовательский поток на основе объекта для вашей проблемы

Вот как я представляю поток вашего оператора из того, что я понял в вашей записи.

  • Один Account объект отображается на один аккаунт. Каждый объект имеет уникальные метаданные, которые сопоставляют его с учетной записью. Он также должен иметь active: boolean в своей спецификации c.
  • Следить за пользовательскими Account объектами
  • Всякий раз, когда вам необходимо создать новую учетную запись, используйте API-интерфейсы Kubernetes для создайте новый объект Account (вызовет событие Add в контроллере), а затем ваш контроллер должен

    • создать / обновить PersistentVolumeClaim для учетной записи
    • создать / обновить Deployment с томом из созданного PVC, указанным в шаблоне Pod
    • Catch: события добавления также получаются для старых объектов при перезапуске контроллера. Поэтому необходимо выполнить действие «Создать или обновить».
  • Установите для поля active в пользовательском объекте значение false для деактивации учетной записи ( Изменить событие в контроллере), а затем ваш контроллер должен

    • Удалить развертывание, не затрагивая громкость вообще.
  • Установите для поля active значение true за повторную активацию аккаунта. (измените событие еще раз)
    • Создайте заново развертывание с тем же томом, который указан в шаблоне Pod
  • Удалите объект Account, чтобы очистить основные ресурсы.

Хотя все это может и не иметь смысла сразу, я все же рекомендую вам go с помощью документации и примеров оператора-sdk. ИМО, это был бы скачок в правильном направлении.

Ура!

0 голосов
/ 26 февраля 2020

После нескольких дней глубокого погружения в обучение операторов, ответ @ Ashu является лучшим решением проблемы и открывает Kubernetes для решения практически любого сценария, который может потребоваться.

Ниже приведены наиболее полезные ресурсы для обучения операторов на начало 2020 года:

youtube.com / watch? v = 8_DaCcRMp5I learn.openshift.com/operatorframework/go-operator-podset https://itnext.io/a-practical-kubernetes-operator-using-ansible-an-example-d3a9d3674d5b

Я настоятельно рекомендую полностью изучить оба этих ресурса (и кодирование вместе с ними), прежде чем пытаться создать своего собственного оператора. Кроме того, если вы «новее» до golang, определенно go с помощью подхода ansible, ДАЖЕ ЕСЛИ вы хотите создать свой собственный оператор golang. Подход Ansible более интуитивен, и концепции очень быстро «щелкают» при игре с этим.

Что касается Golang против Ansible

Golang: чуть больше контроль, но гораздо сложнее, нудно и нюанс

Ansible: очень интуитивно понятный, решает операторы высокоуровневым способом kubernetes, модульный / многоразовый

Также # слабый канал операторов kubernetes является бесценный

...