Управление секретами и почему это так важно для нас?
Привет! Меня зовут Евгений, я работаю на позиции Lead DevOps в EXANTE. В этой статье мы разберем жизненный опыт сетапа high availability Hashicorp Vault с gcp storage backend и auto unseal в k8s.
Некоторое время назад наша инфраструктура состояла из тысяч виртуальных и железных машин, на которых были размещены наши легаси сервисы. На эти машины, частично руками, частично при помощи chef, распространялись конфигурационные файлы с уже вписанными секретами в открытом виде.
По целому ряду причин, включающих в себя ускорение процессов доставки кода, обеспечение беспрерывности доставки и безопасного хранения секретов, а также ускорение развертывания новых приложений и окружений, было принято решение о смене стратегии компании.
Мы решили сделать наш продукт cloud native, и для этого нужно было изменить подход к разработке и инфраструктуре, провести рефакторинг наших легаси сервисов, начать двигаться в сторону микросервисной архитектуры, разворачивать сервисы в cloud k8s, использовать managed ресурсы (redis, postgres).
В наших реалиях под изменения попасть должно было все – от приложений и инфраструктуры до методов распространения конфигов и секретов. В качестве облачного провайдера был выбран Google, а хранилищем секретов был выбран Hashicorp Vault. На данный момент мы довольно успешно прошли большую часть пути.
Почему Hashicorp Vault?
У нас есть несколько причин:
Нам нужен был готовый инструмент, который может изменить ситуацию с управлениям секретами в моменте без необходимости глобальных доработок кода наших приложений. Также этот инструмент должен иметь возможность интеграции с chef.
Hashicorp Vault – наиболее популярный инструмент с необходимой функциональностью (хранение секретов, управление доступом к секретам, инъекция секретов в поды k8s, интеграция с chef, gitlab ci).
Наличие практического опыта у наших devops инженеров в конфигурировании HA и unseal.
Возможность в дальнейшем интегрировать в наш k8s кластер Secret injection webhook.
Где и в какой конфигурации мы разворачиваем Hashicorp Vault?
Мы разворачиваем Hashicorp Vault в k8s кластере на отдельном нодпуле.
С точки зрения конфигурации, мы используем подход с автоматическим распечатыванием хранилища при помощи gcpckms в момент рестарта подов Hashicorp Vault. В качестве storage backend для хранения данных Hashicorp Vault мы используем Google Cloud Storage, так как это позволяет просто и дешево кластеризовать сервис Hashicorp Vault.
Почему нам так важен автоматический unseal?
Здесь все довольно просто – на данный момент большая часть сервисов получает секреты в виде переменных окружения при помощи Vault Secret injection webhook, именно поэтому нам необходим автоматический unseal: без него мы потенциально столкнемся с недоступностью сервисов Hashicorp Vault и отсутствием возможности передать переменные окружения в сервисы при любых манипуляциях с подами (рестарт, новый релиз и т.д.)
Что необходимо иметь для настройки HA с gcs storage backend и gcpckms auto unseal?
Сервисный аккаунт для Hashicorp Vault.
GCS bucket.
Keyring + cryptokey.
Мы создаем необходимые сущности при помощи terraform.
Подробнее про iam политики для сервисного аккаунта и про связку keyring и cryptokey gcpckms можно прочитать в официальной документации.
Каким образом мы разворачиваем Hashicorp Vault в k8s?
В k8s кластере мы используем подход GitOps при помощи инструмента Flux CD. Соответственно все новые приложения деплоятся в кластер через репозиторий Flux CD. Мы не будем вдаваться в подробности использования GitOps в этой статье.
Для шифрования первичных секретов (необходимых для развертывания Hashicorp Vault) мы используем SOPS. SOPS — редактор зашифрованных файлов, поддерживающий форматы YAML, JSON, ENV, INI и BINARY и шифрующий с помощью AWS KMS, GCP KMS, Azure Key Vault, age и PGP. Мы используем age, и ключ для расшифровки находится в секретах k8s.
Мы конфигурируем Hashicorp Vault следующим образом:
- HA режим (3 реплики).
- GCS storage backend.
- Auto unseal при помощи gcpckms.
В первую очередь нам необходимо создать секрет с именем vault-gcs, положив в него наш сервисный аккаунт. Этот файл мы создаем по шаблону ниже и шифруем при помощи SOPS.
apiVersion: v1
kind: Secret
metadata:
name: vault-gcs
namespace: vault
type: Opaque
data:
Vault_gcs_key.json: <base64-serviceaccount>
Для корректной работы Hashicorp Vault в указанной конфигурации необходимо пробросить в под файл с нашим сервисным аккаунтом и указать дополнительные переменные окружения. Таким образом, мы наполняем файл values.yaml:
server:
enabled: true
extraEnvironmentVars:
GOOGLE_APPLICATION_CREDENTIALS: /vault/userconfig/vault-gcs/vault_gcs_key.json
GOOGLE_PROJECT: your-project
extraVolumes:
- name: vault-gcs
path: /vault/userconfig
type: secret
Далее мы продолжаем наполнять values.yaml. Важно корректно настроить конфиг HA для работы в несколько реплик и поддержки gcs storage backend + gcpckms unseal. В конечном итоге values.yaml выглядит следующим образом:
server:
enabled: true
extraEnvironmentVars:
GOOGLE_APPLICATION_CREDENTIALS: /vault/userconfig/vault-gcs/vault_gcs_key.json
GOOGLE_PROJECT: your-project
extraVolumes:
- name: vault-gcs
path: /vault/userconfig
type: secret
ha:
config: |
ui = true
listener "tcp" {
address = "[::]:8200"
cluster_address = "[::]:8201"
}
storage "gcs" {
bucket = "bucket-name"
ha_enabled = "true"
}
seal "gcpckms" {
project = "gcp-project-name"
region = "global"
key_ring = "your-keyring"
crypto_key = "your-cryptokey"
}
enabled: true
replicas: 3
Дополнительно в нашем helm chart используются настройки внутреннего ingress, но они довольно специфичные и для общего понимания не требуются. Помимо этого, мы отключаем использование vault-agent-injector, данные параметры можно настроить самостоятельно на основе примера в официальном helm-chart.
Установка в кластер производится при помощи Flux CD и полностью автоматизирована, используется официальный helm chart от hashicorp.
После успешной установки мы имеем три пода vault-0, vault-1, vault-2 в неймспейсе vault. Для успешного запуска сервиса достаточно выполнить команду:
kubectl exec -ti vault-0 -- vault operator init
В результате выполнения получаем root token и пять recovery keys.
Настоятельно рекомендуем сохранить эти данные, так как их утрата является фатальной и фактически отрезает доступ к управлению Hashicorp Vault кластером.
Мы провели сравнительное тестирование производительности Hashicorp Vault с разными storage backend. Мы запускали его с postgresql, consul, aws s3, gcs. В наших тестах gcs был примерно в 10 раз медленнее, чем postgresql.
Поскольку для нас скорость отдачи секретов не критична и приоритетом является возможность удобного auto unseal, быстрой интеграции с storage backend – было принято решение использовать gcs.
Наш k8s работает в такой конфигурации с Hashicorp Vault два года, на текущий момент мы не встречали проблем в использовании данной конфигурации.
Итоги:
Hashicorp Vault для нас – это постоянно доступный, единый и безопасный источник правды с разграничением доступа к секретам и различными методами авторизации. Это простой в использовании и конфигурировании инструмент, имеющий актуальную документацию. Он позволяет интегрировать Secret injection webhook, который предоставляет необходимую функциональность: создавать последующие секреты внутри кластера без SOPS шифрования, импортируя их прямо из хранилища, интегрировать практически любые другие инструменты и импортировать в них секреты из хранилища (ci, k8s поды, chef и т.д), но об этом – в следующий раз!