Как эффективно и безопасно делиться множеством секретов в кластере Kubernetes? И, возможно, попутно изучите внутреннюю работу Kubernetes.
Рассмотрим следующую ситуацию: вы установили новый ElasticSearch в своем кластере Kubernetes, возможно, используя Elastic Cloud on Kubernetes (ECK).
Поскольку вы глубоко заботитесь о защите своей инфраструктуры, вы выпускаете сертификат для включения связи TLS между серверной частью приложения и API-интерфейсом ElasticSearch. Это то, что ECK делает для вас действительно хорошо, так что будем благодарны!
$ kubectl -n es get secrets -o name secret/default-token-pbvfd secret/es-remote-ca secret/http-ca-internal secret/es-http-certs-internal secret/es-http-certs-public secret/es-transport-ca-internal secret/es-transport-certs-public secret/es-elastic-user secret/es-internal-users secret/es-xpack-file-realm secret/es-transport-certificates secret/es-default-es-config
Этот es-http-certs-public
выглядит особенно многообещающим, и быстрый осмотр показывает, что он содержит CA и публичный сертификат нового экземпляра ES. Как только мы нашли то, что нам нужно, мы хотим использовать этот секрет в наших приложениях, развернутых в нескольких пространствах имен. Конечно, эти пространства имен отличаются от пространства имен es
выше, в котором живет ES.
Но нет! 😩 Секреты - это ресурсы с пространством имен, и поэтому на них можно ссылаться только из того же пространства имен. Так как же сделать этот секрет доступным в других пространствах имен?
Начиная с ленивого решения
Одна вещь, которую разделяет каждый технически подкованный человек, - это способность эффективно копировать / вставлять. Превратим это умение в прибыль. Мы назовем пространство имен, в котором находится наше приложение, app
, потому что у меня нет никакого вдохновения.
$ kubectl -n es get secrets es-http-certs-public -o yaml | kubectl apply -n app -f - error: the namespace from the provided object "es" does not match the namespace "app". You must pass '--namespace=es' to perform this operation.
Давай попробуем:
$ kubectl -n es get secrets es-http-certs-public -o yaml | sed '/namespace.*/d' | kubectl apply -n app -f - secret/es-http-certs-public created $ kubectl -n app get secret -o name secret/default-token-4vlrv secret/es-http-certs-public
Прохладный! Работает. Затем вы можете смонтировать этот секрет в своем модуле приложения для безопасного обсуждения с ES API. Тяжелая работа! Давай назовем это днем, но все же ...
Вы просыпаетесь на следующий день, и ваше приложение сообщает о сбое связи с ES API. Но до сих пор все работало нормально, верно? Вы быстро понимаете, что скопированный секрет исчез! 😱
$ kubectl -n app get secret -o name secret/default-token-4vlrv <It should be here! Please come back>
Kubernetes подводит меня!
Кто удалил этот секрет? Наверняка это новый шумный стажер, которого вы наняли на прошлой неделе 🤔 Вы просматриваете журналы аудита Kubernetes и, наконец, находите виновника: system:serviceaccount:kube-system:generic-garbage-collector
. Твоя тяжелая 5-минутная работа вчера ушла, она уничтожена жестоким сборщиком мусора!
Возможно, вам стоило внимательно прочитать документацию Kubernetes о концепции владения. Особенно в этой части:
Зависимые в пространстве имен могут указывать владельцев в области кластера или в пространстве имен. Владелец с пространством имен должен существовать в том же пространстве имен, что и зависимый. В противном случае ссылка на владельца рассматривается как отсутствующая, а зависимый подлежит удалению после проверки отсутствия всех владельцев.
Если бы мы взглянули на удаленный секрет, мы бы увидели, что у нашего скопированного секрета есть владелец, которым является ресурс ElasticSearch:
metadata: namespace: app ownerReferences: - apiVersion: elasticsearch.k8s.elastic.co/v1 blockOwnerDeletion: true controller: true kind: Elasticsearch name: es uid: c7c85fe4-ef48-4933-84aa-4c7dd0d86d79
Согласно документации, владелец ресурса должен существовать в том же пространстве имен или в области кластера, что здесь не так: владелец ElasticSearch
все еще живет, но в пространстве имен es
! Так что сборщик мусора по праву посчитал секрет бесхозным и удалил его.
Но почему его не удалили раньше? Или почему мне вообще разрешили творить такую мерзость? На самом деле это не должно было быть разрешено, и секрет был удален после перезапуска диспетчера контроллеров. Проблема исправлена в Kubernetes 1.20 через два года. Но немногие из нас используют передовую версию Kubernetes, особенно у провайдера общедоступного облака 👀
Вооружившись этими новыми знаниями, вы больше никогда не будете копировать собственный ресурс Kubernetes! Хорошо, но, может быть, мы все же сможем повторить попытку в последний раз и удалить блок ownerReference
? .. Конечно, это сработает, но должно быть лучшее решение.
Входит в отражатель
Reflector от Emberstack - небольшой, но удобный проект. Он написан на C #, но я перейду к нему из-за того, насколько хорошо он работает.
Reflector - это надстройка Kubernetes, предназначенная для отслеживания изменений ресурсов (секретов и конфигурационных карт) и отражения изменений зеркальных ресурсов в том же или другом пространстве имен.
Развертывание очень простое, одна простая команда Kubectl, и все готово. Теперь мы просто аннотируем наш секрет в пространстве имен es
:
$ kubectl -n es annotate secret es-http-certs-public reflector.v1.k8s.emberstack.com/reflection-auto-enabled=true secret/es-http-certs-public annotated $ kubectl -n es annotate secret es-http-certs-public reflector.v1.k8s.emberstack.com/reflection-allowed-namespaces=app secret/es-http-certs-public annotated
И вот, наш секрет снова в пространстве имен app
, ура! 🎉
$ kubectl -n app get secret -o name secret/default-token-4vlrv secret/quickstart-es-http-certs-public
Но на этот раз ownerReference
больше нет, поскольку Reflector знает, как правильно копировать. Более того, решение не ограничивается секретами, и вы также можете таким образом распространять карты конфигурации или сертификаты диспетчера сертификатов.
Заключение
Я твердо уверен, что чем проще решение, тем лучше, но эта поучительная история показывает, что это не всегда так.
Однако такого рода проблемы неожиданно заставляют вас многое узнать о внутренней работе Kubernetes и открыть для себя новые полезные инструменты для элегантного решения проблем. Оглядываясь назад, я благодарен за то, что мне пришлось решить столько проблем! 🤗
👋 Присоединяйтесь к FAUN сегодня и получайте похожие истории каждую неделю на свой почтовый ящик! ️ Получите еженедельную дозу обязательных к прочтению технических статей, новостей и руководств.
Подписывайтесь на нас в Twitter 🐦 и Facebook 👥 и Instagram 📷 и присоединяйтесь к нашим Facebook и Linkedin Группы 💬