Vault Agent Injector в Kubernetes

Как добавить под аннотацию — и секреты сами появятся внутри пода файлом, без правки кода и образа.

Vault Agent Injector — компонент для Kubernetes, который по аннотациям пода автоматически добавляет sidecar Vault Agent, доставляющий секреты в файлы внутри пода.

В Kubernetes неудобно встраивать Vault Agent вручную в каждый Deployment. Injector делает это автоматически: вы помечаете под аннотациями, а mutating webhook на лету добавляет init- и sidecar-контейнеры Agent.

Как помечают под

apiVersion: apps/v1
kind: Deployment
metadata:
  name: orders
spec:
  template:
    metadata:
      annotations:
        vault.hashicorp.com/agent-inject: "true"
        vault.hashicorp.com/role: "orders"
        vault.hashicorp.com/agent-inject-secret-db: "database/creds/readonly"
    spec:
      serviceAccountName: orders-sa
      containers:
        - name: app
          image: myorg/orders:1.0

Аннотации говорят: включить инъекцию, логиниться ролью orders (через Kubernetes auth), доставить секрет из database/creds/readonly. Образ myorg/orders при этом не меняется.

Что появляется в поде

Injector добавляет два контейнера: init-контейнер Agent, который при старте логинится и рендерит секреты до запуска приложения, и sidecar Agent, который продлевает аренды и обновляет файлы по ходу жизни пода.

Pod orders
  +-- init: vault-agent  (получает секреты ДО старта app)
  +-- app                (читает /vault/secrets/db)
  +-- sidecar: vault-agent (продлевает, обновляет файлы)

общий emptyDir-том: /vault/secrets

Секреты рендерятся в файл /vault/secrets/db на общем in-memory томе (emptyDir в памяти), доступном приложению.

Как работает под капотом

Injector — это mutating admission webhook. Когда создаётся под с нужной аннотацией, API-сервер Kubernetes отправляет объект webhook'у, тот мутирует спецификацию: добавляет контейнеры Agent, общий emptyDir-том в памяти и конфиг. Agent внутри логинится через Kubernetes auth, предъявляя ServiceAccount-токен пода (orders-sa), и Vault проверяет его через TokenReview. Секреты живут только в памяти пода и исчезают вместе с ним — на диск ноды они не пишутся.

Зачем это нужно

  • Без правки образа — приложение остаётся неизменным, читает файл.
  • Секреты в памяти пода — не в etcd как обычные k8s Secret, не на диске ноды.
  • Динамика и ротация — sidecar продлевает аренды, файлы обновляются.
  • Декларативно — всё управляется аннотациями.

Частые ошибки

  • Забыть указать serviceAccountName, под который настроена роль — логин не пройдёт.
  • Несоответствие bound_service_account_* в роли — Vault отвергнет под.
  • Ждать инъекции без установленного Injector — нужен задеплоенный webhook (обычно через Helm-чарт Vault).

Итог

  • Agent Injector по аннотациям добавляет в под sidecar/init Vault Agent без правки образа.
  • Секреты рендерятся в файл на in-memory томе и обновляются sidecar'ом.
  • Логин идёт через Kubernetes auth по ServiceAccount пода; секреты не попадают в etcd.
Проверьте себя
1. Как Vault Agent Injector узнаёт, что поду нужны секреты?
AСканирует все поды подряд
BПо аннотациям пода (vault.hashicorp.com/agent-inject и др.)
CПо имени образа
DИз ConfigMap
2. Где оказываются секреты, доставленные Injector?
AВ etcd как обычный k8s Secret
BВ файле на in-memory томе внутри пода
CВ переменных образа
DНа диске ноды
3. Под какой личностью Agent логинится в Vault внутри пода?
AПод root-токеном
BЧерез Kubernetes auth по ServiceAccount-токену пода
CЧерез AppRole в коде приложения
DАнонимно