Hashicorp Vault в Kubernetes: установка и интеграция

Vault - отличный инструмент для управления секретами, который кроме всего можно еще и интегрировать с Kubernetes. В этой статье разберём, как установить Vault в Kubernetes и как связать секреты Vault с аннотациями Kubernetes.

Установка Vault в Kubernetes

Есть несколько способов установить Vault в Kubernetes, но один из самых распространённых - через пакетный менеджер Helm. Helm упрощает процесс деплоя за счёт системы шаблонов для генерации Kubernetes-манифестов.

Чтобы установить Vault в Kubernetes с помощью Helm, сделайте следующее:

Установите Helm

Helm должен быть установлен на вашей локальной машине. Следуйте официальной инструкции по установке Helm для вашей операционной системы.

Добавьте репозиторий Helm от HashiCorp

Выполните следующую команду, чтобы добавить репозиторий HashiCorp в Helm:

helm repo add hashicorp https://helm.releases.hashicorp.com

Установите Vault

Выполните следующую команду, чтобы установить Vault в Kubernetes:

helm install vault hashicorp/vault \
  --set "server.dev.enabled=true"

Эта команда устанавливает Vault с включённым dev-сервером, что удобно для тестов и разработки. В продакшене так делать не стоит - там лучше использовать постоянное хранилище, например, Amazon S3 или Azure Blob Storage.

Интеграция секретов Vault с аннотациями Kubernetes

Когда Vault установлен в кластере, можно использовать его для управления секретами и интеграции этих секретов с аннотациями Kubernetes. Аннотации в Kubernetes - это пары ключ-значение, которые можно добавлять к объектам вроде pod'ов, deployment'ов и сервисов. Они дают дополнительную информацию об объекте и могут использоваться, например, для мониторинга, отладки или конфигурации.

Чтобы интегрировать секреты Vault с аннотациями Kubernetes, сделайте следующее:

Включите Kubernetes-аутентификацию в Vault

Запустите команду:

vault auth enable kubernetes

Это включает метод аутентификации через Kubernetes в Vault.

Настройте Kubernetes-аутентификацию

Выполните следующую команду:

vault write auth/kubernetes/config \
  token_reviewer_jwt="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
  kubernetes_host="https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT_HTTPS" \
  kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt

Здесь Vault настраивается на использование токена сервисного аккаунта Kubernetes, а также указываются адрес и порт API-сервера Kubernetes и путь к CA-сертификату. Всё это Vault будет использовать для проверки подлинности.

Создайте политику и токен в Vault

Выполните команды:

vault policy write myapp-policy - <<EOF
path "secret/myapp/*" {
  capabilities = ["read"]
}
EOF
vault token create -policy=myapp-policy -ttl=1h

Здесь создаётся политика myapp-policy, которая даёт права только на чтение секретов по пути secret/myapp/*. Также создаётся токен с этой политикой и временем жизни 1 час.

Создайте секрет Kubernetes с этим токеном Vault

Выполните:

kubectl create secret generic vault-auth \
  --from-literal "token=$(vault print-token)"

Это создаёт Kubernetes-секрет vault-auth, в котором токен Vault передаётся как обычное значение.

Добавьте аннотации к объекту Kubernetes

Добавьте следующие аннотации в объект Kubernetes - например, Pod или Deployment - чтобы получить секрет из Vault и пробросить его как переменную окружения:

annotations:
  vault.hashicorp.com/agent-inject: "true"
  vault.hashicorp.com/agent-inject-secret-myapp-password: "secret/myapp/password"
  vault.hashicorp.com/agent-inject-template-myapp-password: |
    {{- with secret "secret/data/myapp-password" -}}
    export MY_SECRET_PASSWORD={{ .Data.password }}
    {{- end }}

Эти аннотации указывают Vault Agent'у, что нужно инжектировать секрет secret/myapp/password и пробросить его в переменную окружения MY_SECRET_PASSWORD с помощью шаблона.

Задеплойте объект Kubernetes

После добавления аннотаций задеплойте объект. Vault Agent в виде побочного контейнера (sidecar) сам заберёт секрет из Vault и вставит его в основной контейнер как переменную окружения.

Пример манифеста Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  selector:
    matchLabels:
   app: myapp
  template:
    metadata:
      labels:
        app: myapp
      annotations:
        vault.hashicorp.com/agent-inject: "true"
        vault.hashicorp.com/agent-inject-secret-myapp-password: "secret/myapp/password"
        vault.hashicorp.com/agent-inject-template-myapp-password: |
          {{- with secret "secret/myapp/password" }}
          MYAPP_PASSWORD={{ .Data.password }}
          {{- end }}
    spec:
      containers:
        - name: myapp
          image: myapp:v1
          env:
            - name: MYAPP_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: vault-auth
                  key: token
        - name: vault-agent
          image: vault:1.7.1
          command: ["/bin/sh", "-c"]
          args:
            - "vault agent -config /etc/vault/config.hcl"
          volumeMounts:
            - name: vault-config
              mountPath: /etc/vault
      volumes:
        - name: vault-config
          configMap:
            name: vault-agent-config

В этом примере деплой включает два контейнера: основной контейнер приложения myapp и побочный контейнер с Vault Agent'ом. Аннотации указываются в метаданных шаблона pod’а и описывают, откуда брать секрет в Vault и как именно его вставлять в контейнер в виде переменной окружения.

Заключение

Интеграция Vault с Kubernetes даёт безопасный и гибкий способ управления секретами в кластере. С Vault вы централизованно управляете секретами через API или UI, а Kubernetes-аннотации позволяют автоматически инжектировать эти секреты в приложения. Если пройти по шагам из этой статьи, можно без особых сложностей установить Vault в Kubernetes и наладить доставку секретов в поды через аннотации.