SPIFFE и SPIRE в Kubernetes: настройка динамической идентификации сервисов без статических секретов | AdminWiki

SPIFFE и SPIRE в Kubernetes: настройка динамической идентификации сервисов без статических секретов

28 августа 2026 9 мин. чтения
Содержание статьи

SPIFFE и SPIRE в Kubernetes: короткий ответ и область применения

SPIFFE (Secure Production Identity Framework for Everyone) задаёт формат идентификатора сервиса, SPIRE реализует этот стандарт в Kubernetes и вне кластера. Связка SPIFFE/SPIRE заменяет статические секреты динамическим документом SVID (SPIFFE Verifiable Identity Document). SPIRE Server выпускает SVID и управляет центром доверия, SPIRE Agent на каждом узле доставляет SVID приложению через UNIX-сокет Workload API. mTLS настраивается без хранения ключей в Kubernetes Secret.

Руководство даёт рабочий сценарий: устанавливаете SPIRE Server и Agent через Helm, настраиваете доверенный домен, регистрируете поды по ServiceAccount, получаете SVID в поде и настраиваете mTLS между двумя сервисами. Диагностика и требования для production разобраны в конце.

Что именно вы получите после развёртывания

  • SPIRE Server запущен в отдельном namespace spire и управляет корневым центром доверия.
  • SPIRE Agent запущен как DaemonSet на каждом узле и отдаёт SVID через Workload API.
  • Pod с ServiceAccount service-a получает SPIFFE ID вида spiffe://example.org/ns/default/sa/service-a без чтения статического секрета.
  • Два сервиса общаются по mTLS: каждый предъявляет SVID и проверяет SPIFFE ID оппонента.
  • Идентификаторы обновляются автоматически до истечения TTL без рестарта приложения.

Почему статические секреты проигрывают динамической идентификации

Статический секрет, например bearer-токен или сертификат в Secret, известен обеим сторонам и хранится дольше, чем безопасная сессия. Ротация одного секрета требует одновременного обновления всех потребителей. Рассинхрон вызывает отказы, утечка открывает доступ на неопределённый срок. По умолчанию каждый под Kubernetes получает ServiceAccount с токеном, который может обращаться к Kubernetes API. Этот токен нужно явно ограничить через automountServiceAccountToken и минимальные RBAC, иначе компрометация пода даёт доступ к кластеру.

SPIRE снимает эту проблему: SVID выпускается под зарегистрированную рабочую нагрузку, живёт коротко и привязан к SPIFFE ID. Приложение получает ключ в память и не читает Secret.

Чем SVID отличается от Kubernetes Secret

SVID выпускается с коротким TTL, обычно 1 час, содержит SPIFFE ID, подпись SPIRE Server и публичный ключ. Kubernetes Secret хранит произвольные данные в etcd, по умолчанию не ротируется и не привязан к живой идентичности процесса. SVID не кладётся в Secret и обновляется агентом до истечения срока.

Когда SPIRE действительно оправдан

  • Нужен межсервисный mTLS с проверкой SPIFFE ID.
  • Вы строите zero trust сеть, где доверие не зависит от IP или подсети.
  • Требуется единая идентичность сервисов в нескольких кластерах.
  • Нужно отказаться от долгоживущих статических токенов.

Если нужен только TLS внутри одного namespace, достаточно cert-manager. SPIRE добавляет ценность при проверке идентичности сервиса, а не просто при шифровании трафика.

Архитектура SPIRE: SPIRE Server, Agent и Workload API

SPIRE состоит из сервера, агентов на узлах и механизма регистрации рабочих нагрузок. Путь идентификатора выглядит так: registration entry описывает под, агент аттестует узел и под, сервер проверяет селекторы и выдаёт SVID агенту, агент доставляет SVID приложению через Workload API.

SPIRE Server: центр доверия и выдачи SVID

SPIRE Server управляет корневым CA, хранит registration entries и подписывает SVID. В production нужно выделять отдельный trust domain, защищать ключи сервера и настраивать резервное копирование CA.

SPIRE Agent и Workload API: точка интеграции на узле

SPIRE Agent размещается на каждом узле как DaemonSet. Агент кэширует SVID и предоставляет UNIX-сокет Workload API, обычно /run/spire/agent/public/api.sock. Приложение запрашивает SVID локально и не обращается к Kubernetes API напрямую.

Workload Registration: как SPIRE узнаёт о ваших подах

Регистрация выполняется через селекторы: k8s:ns, k8s:sa, k8s:pod-label. SPIRE сопоставляет поды с SPIFFE ID на основе этих селекторов. Workload Registrars автоматизируют создание registration entries при появлении новых ServiceAccount или подов.

Подготовка кластера и установка SPIRE через Helm

Перед установкой нужно освежить устройство кластера и объектов API. Если нужно повторить базовые сущности Kubernetes, смотрите Kubernetes: архитектура кластера и ключевые объекты API.

Требования к кластеру и выбор namespace

Минимальные требования: Kubernetes 1.26 и Helm 3.12. Для изоляции компонентов создайте namespace spire. DaemonSet агента займёт по одному поду на узел, серверу достаточно одного реплика в тестовой среде и трёх в production. Если управляемого кластера ещё нет, Kubernetes можно развернуть в Timeweb Cloud.

Минимальный values.yaml для SPIRE Server и Agent

Создайте values.yaml. Trust domain задаётся одинаковым для сервера и агента. Пример конфигурации:

spire-server:
  enabled: true
  replicaCount: 1
  trustDomain: example.org
spire-agent:
  enabled: true
  trustDomain: example.org
  server:
    address: spire-server.spire.svc.cluster.local
    port: 8081
  socketPath: /run/spire/agent/public/api.sock
  logLevel: INFO

Добавьте официальный Helm-репозиторий SPIRE и обновите кеш. Затем выполните установку:

kubectl create namespace spire
helm install spire spiffe/spire --namespace spire --values values.yaml

Проверка установки: логи, поды и статусы

kubectl get pods -n spire -o wide
kubectl logs -n spire -l app=spire-server
kubectl logs -n spire -l app=spire-agent

Все поды сервера и агентов должны находиться в состоянии Running и проходить readiness-пробу. Если агент не запускается, смотрите логи через kubectl describe pod.

Настройка доверенного домена и подключение агентов

Что такое trust domain и как выбрать корректное имя

Формат SPIFFE ID: spiffe://trust-domain/path. Имя должно быть стабильным и уникальным, обычно используют домен организации: example.org. Переименование trust domain после развёртывания болезненно, потому что все записи и проверки mTLS завязаны на этот корень.

Методы аутентификации агентов: join token и Kubernetes PSAT

Join token подходит для начального подключения агентов. Генерируется на сервере:

kubectl exec -n spire spire-server-0 -- spire-server agent generate-join-token -spiffeID spiffe://example.org/agent/cluster1 -ttl 3600

Kubernetes PSAT использует projected service account token и лучше подходит для автоматического добавления узлов. Для PSAT задайте метод соединения в values.yaml агента и минимум прав для TokenReview.

Проверка регистрации агентов на сервере

kubectl exec -n spire spire-server-0 -- spire-server agent list

В выводе агент должен иметь статус attested. Пока агент не аттестован, выдача SVID для подов на этом узле невозможна.

Регистрация рабочих нагрузок: от ServiceAccount к SPIFFE ID

Selectors: как SPIRE сопоставляет поды с идентификаторами

Селекторы определяют, какие поды получают SPIFFE ID. Запись с селекторами k8s:ns:default и k8s:sa:service-a выдаёт один и тот же SPIFFE ID всем подам в namespace default, использующим ServiceAccount service-a.

Пример регистрации сервиса через namespace и ServiceAccount

kubectl exec -n spire spire-server-0 -- spire-server entry create -spiffeID spiffe://example.org/ns/default/sa/service-a -parentID spiffe://example.org/agent/cluster1 -selector k8s:ns:default -selector k8s:sa:service-a -ttl 3600

Параметр -ttl ограничивает срок жизни SVID. Для сервиса service-b создайте аналогичную запись с собственным SPIFFE ID.

Проверка выдачи SVID в тестовом поде

Запустите под с ServiceAccount service-a. Проверьте наличие сокета Workload API:

kubectl exec -n default test-pod -- ls -l /run/spire/agent/public/api.sock

Через Workload API под получит SPIFFE ID, приватный ключ в памяти и trust bundle. Приложение не хранит эти данные в файловой системе или Secret.

Интеграция приложений через Workload API и настройка mTLS без статических секретов

Приложение обращается к локальному сокету Workload API. Агент возвращает SVID, приватный ключ в памяти и корневые сертификаты. Если нужно настроить сетевой доступ между сервисами, смотрите Service и Ingress в Kubernetes.

Как приложение получает SVID и корневые сертификаты

SVID содержит цепочку сертификатов и приватный ключ. Trust bundle содержит корневые сертификаты, нужные для проверки оппонента. Всё передаётся через gRPC-вызовы к сокету, поэтому секрет не попадает в переменные окружения и файловую систему.

Настройка Envoy SDS для mTLS: практический пример

Envoy получает сертификаты через SDS от SPIRE Agent. Пример фрагмента конфигурации для upstream:

transport_socket:
  name: envoy.transport_sockets.tls
  typed_config:
    '@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
    common_tls_context:
      tls_certificate_sds_secret_configs:
      - name: spiffe://example.org/ns/default/sa/service-a
        sds_config:
          api_config_source:
            api_type: GRPC
            grpc_services:
              envoy_grpc:
                cluster_name: spire-agent
      validation_context_sds_secret_configs:
      - name: spiffe://example.org
        sds_config:
          api_config_source:
            api_type: GRPC
            grpc_services:
              envoy_grpc:
                cluster_name: spire-agent

Кластер spire-agent направляет SDS-запросы на UNIX-сокет Workload API. Envoy обновляет сертификаты без перезапуска.

Проверка mTLS между двумя сервисами

Отправьте запрос от service-a к service-b по HTTPS или gRPC. Проверьте, что оба сервиса предъявили SVID и доверяют корням. При ошибке рукопожатия в логах Envoy появится TLS error: certificate verify failed, что указывает на несовпадение trust domain или trust bundle.

Автоматическая ротация SVID и сертификатов

Жизненный цикл SVID: TTL, обновление и отзыв

TTL задаётся при создании registration entry. Агент запрашивает новый SVID до истечения срока, не дожидаясь протухания сертификата. Отзыв выполняется удалением registration entry, после чего новые SVID не выдаются, а уже выпущенные перестанут обновляться.

Ротация trust bundle и корневых сертификатов

Trust bundle обновляется через Workload API. Приложения должны принимать несколько корневых сертификатов в переходный период, чтобы обновление корня не разрывало mTLS-соединения.

Как проверить, что ротация работает без рестарта

Посмотрите срок действия выданного SVID, дождитесь обновления и повторите mTLS-запрос. Сессия между сервисами не должна прерываться. В логах агента видно, когда SVID был перевыпущен.

Безопасная эксплуатация SPIRE: минимальные RBAC-права и аудит

Какие права нужны SPIRE Server и Agent: минимальный набор

Агенту нужны права на чтение подов и узлов, а также создание TokenReview для аттестации. Пример Role:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: spire-agent
  namespace: spire
rules:
- apiGroups: ['']
  resources: ['pods', 'nodes']
  verbs: ['get', 'list', 'watch']
- apiGroups: ['authentication.k8s.io']
  resources: ['tokenreviews']
  verbs: ['create']
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: spire-agent
  namespace: spire
subjects:
- kind: ServiceAccount
  name: spire-agent
  namespace: spire
roleRef:
  kind: Role
  name: spire-agent
  apiGroup: rbac.authorization.k8s.io

Серверу нужны права на управление registration entries и узлами. Используйте Role + RoleBinding внутри namespace, ClusterRole только для кластерных ресурсов.

Типовые антипаттерны: wildcard, cluster-admin и лишние токены

Wildcard в verbs и resources даёт права на все текущие и будущие ресурсы. Привязка к встроенной роли cluster-admin снимает все ограничения. Отключайте автоматическое монтирование токена ServiceAccount, если приложение не обращается к Kubernetes API.

Аудит RBAC: kubectl auth can-i, rakkess, rbac-tool

Перед написанием манифеста проверьте текущие разрешения:

kubectl auth can-i --list --as=system:serviceaccount:spire:spire-agent

Для быстрого аудита используйте rakkess и rbac-tool. Запускайте проверку регулярно, чтобы права не накапливались при обновлениях.

Диагностика типовых неисправностей SPIRE в Kubernetes

Для быстрой диагностики подов и узлов через метрики CPU, памяти и сети используйте Kubernetes troubleshooting: диагностика pods и узлов через метрики мониторинга.

Агент не подключается к серверу

Проверьте join token, сетевое соединение до spire-server.spire.svc.cluster.local:8081, RBAC агента и отпечаток сервера. Выполните spire-server agent list и kubectl logs -n spire -l app=spire-agent. Частая причина: истёкший join token или неверный trust domain.

Под не получает SVID: селекторы и регистрационные записи

Проверьте селекторы k8s:ns и k8s:sa, наличие registration entry и правильность ServiceAccount пода. Выполните spire-server entry show и сравните с фактическим namespace и ServiceAccount. Если запись есть, проверьте сокет Workload API внутри пода.

mTLS-ошибки: trust domain и bundle mismatch

Проверьте SPIFFE ID обеих сторон, совпадение trust domain и наличие trust bundle. Ошибка certificate verify failed обычно означает, что оппонент предъявляет SVID из другого trust domain или в trust bundle нет нужного корня.

Чеклист production-развёртывания SPIFFE/SPIRE

Перед выкаткой в production сверьтесь с контрольным списком. Если проектируете кластер с нуля, за основу можно взять Kubernetes 2026: проектирование и управление промышленными кластерами.

Контрольные точки перед выкаткой

  • RBAC для сервера и агента ограничен минимальными правами.
  • Trust domain выбран и зафиксирован.
  • ServiceAccount с лишними токенами отключены или ограничены.
  • TTL SVID установлен, но не слишком короткий для стабильной работы.
  • Логи сервера и агентов собираются в систему мониторинга.
  • Резервная копия CA доступна и защищена.

Поддержание и обновление SPIRE в production

Регулярно проверяйте RBAC-права, обновляйте Helm-чарт в staging до production, тестируйте отказоустойчивость сервера и следите за ротацией SVID. План обновления должен включать откат и проверку trust bundle.

Поделиться:
Сохранить гайд? В закладки браузера