Истории успеха наших клиентов — лучшие проекты
Вход/ Регистрация
На главную
25eb9e0a-a5a8-472a-ace7-940b8bd2adf0
Облачные сервисы

Vault

Vault — это система управления секретами от HashiCorp, которая позволяет безопасно хранить и получать доступ к токенам, паролям, сертификатам и другим чувствительным данным. В Kubernetes Vault используется как внешнее хранилище секретов и может обеспечивать централизованное управление доступом к ним.

Установка

Установить Vault в кластер можно через панель управления. Для этого:

Перейдите во вкладку «Дополнения» на странице управления кластером. Найдите карточку «Vault» и нажмите «Установить».

Scr 20251021 Piuk

В появившемся окне вы можете изменить параметры установки:

  1. Переключитесь в режим продвинутой установки;

  2. Отредактируйте конфигурацию вручную или загрузите свой файл values.yaml;

  3. Нажмите кнопку «Установить».

Scr 20251021 Pizg

Конфигурация по умолчанию подразумевает что дополнение будет использоваться в dev-режиме. Это упрощенный режим, в котором Vault автоматически инициализируется, не требует настройки хранилища и использует предустановленный root token. Такой режим подходит только для тестирования и разработки — он небезопасен для продакшена.

Проверка установки

После завершения установки дополнения убедитесь, что компоненты Vault успешно запустились. Для этого выполните команду:

    
kubectl get pods -n vault

Вы должны увидеть список подов, среди которых:

  • vault-0 — основной под Vault;

  • vault-agent-injector-xxx — сервис, отвечающий за автоматическую подстановку секретов в поды;

  • дополнительные поды (например, vault-1, vault-2), если установлен в HA-режиме.

Если в конфигурации была включена опция ui = true (по умолчанию включена), вы можете получить доступ к веб-интерфейсу Vault:

Пробросьте порт с помощью следующей команды:

    
kubectl port-forward -n vault svc/vault 8200:8200

Откройте браузер и перейдите по адресу:

    
http://localhost:8200

В dev-режиме Vault уже инициализирован, и вы можете авторизоваться с помощью токена, указанного в конфигурации. По умолчанию значение такое:

    
devRootToken: "root"

Scr 20251021 Qnui

Список метрик в интерфейсе HashiCorp Vault®

Режим HA

Режим HA (High Availability) позволяет развернуть несколько экземпляров Vault с распределенным хранением данных. Это обеспечивает:

  • отказоустойчивость — при выходе из строя одного экземпляра кластер продолжит работать;
  • централизованное хранилище;
  • возможность масштабирования.

Один из подов становится лидером, остальные работают в режиме standby. Запросы на чтение/запись обрабатывает только лидер, но в случае его недоступности управление автоматически перейдет к одному из standby-подов.

Для работы в этом режиме рекомендуем установить и использовать дополнения CSI-S3 или CSI-driver.

Чтобы включить режим HA, в конфигурации дополнения укажите параметры:

  • server.dev.enabled: false — отключаем dev-режим;
  • server.standalone.enabled: false — отключаем standalone-режим;
  • server.ha.enabled: true — включаем HA-режим;
  • server.ha.replicas: 3 — указываем количество реплик;
  • server.ha.raft.enabled: true — используем встроенное хранилище Raft;
  • server.dataStorage.storageClass: csi-s3 — подключаем S3-хранилище через CSI.
Пример конфигурации (нажмите, чтобы развернуть)
    
global: enabled: true namespace: "" imagePullSecrets: [] tlsDisable: true externalVaultAddr: "" openshift: false psp: enable: false annotations: | seccomp.security.alpha.kubernetes.io/allowedProfileNames: docker/default,runtime/default apparmor.security.beta.kubernetes.io/allowedProfileNames: runtime/default seccomp.security.alpha.kubernetes.io/defaultProfileName: runtime/default apparmor.security.beta.kubernetes.io/defaultProfileName: runtime/default serverTelemetry: prometheusOperator: false injector: enabled: true replicas: 1 port: 8080 leaderElector: enabled: true metrics: enabled: false externalVaultAddr: "" image: repository: "hashicorp/vault-k8s" tag: "1.7.0" pullPolicy: IfNotPresent agentImage: repository: "hashicorp/vault" tag: "1.20.4" agentDefaults: cpuLimit: "500m" cpuRequest: "250m" memLimit: "128Mi" memRequest: "64Mi" template: "map" templateConfig: exitOnRetryFailure: true staticSecretRenderInterval: "" livenessProbe: failureThreshold: 2 initialDelaySeconds: 5 periodSeconds: 2 successThreshold: 1 timeoutSeconds: 5 readinessProbe: failureThreshold: 2 initialDelaySeconds: 5 periodSeconds: 2 successThreshold: 1 timeoutSeconds: 5 startupProbe: failureThreshold: 12 initialDelaySeconds: 5 periodSeconds: 5 successThreshold: 1 timeoutSeconds: 5 authPath: "auth/kubernetes" logLevel: "info" logFormat: "standard" revokeOnShutdown: false webhook: failurePolicy: Ignore matchPolicy: Exact timeoutSeconds: 30 namespaceSelector: {} objectSelector: | matchExpressions: - key: app.kubernetes.io/name operator: NotIn values: - {{ template "vault.name" . }}-agent-injector annotations: {} failurePolicy: Ignore namespaceSelector: {} objectSelector: {} webhookAnnotations: {} certs: secretName: null caBundle: "" certName: tls.crt keyName: tls.key securityContext: pod: {} container: {} resources: {} extraEnvironmentVars: {} affinity: | podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchLabels: app.kubernetes.io/name: {{ template "vault.name" . }}-agent-injector app.kubernetes.io/instance: "{{ .Release.Name }}" component: webhook topologyKey: kubernetes.io/hostname topologySpreadConstraints: [] tolerations: [] nodeSelector: {} priorityClassName: "" annotations: {} extraLabels: {} hostNetwork: false service: annotations: {} serviceAccount: annotations: {} podDisruptionBudget: {} strategy: {} server: enabled: true enterpriseLicense: secretName: "" secretKey: "license" image: repository: "hashicorp/vault" tag: "1.20.4" pullPolicy: IfNotPresent updateStrategyType: "OnDelete" logLevel: "info" logFormat: "standard" resources: {} ingress: enabled: false labels: {} annotations: {} ingressClassName: "" pathType: Prefix activeService: true hosts: - host: chart-example.local paths: [] extraPaths: [] tls: [] hostAliases: [] route: enabled: false activeService: true labels: {} annotations: {} host: chart-example.local tls: termination: passthrough authDelegator: enabled: true extraInitContainers: null extraContainers: null shareProcessNamespace: false extraArgs: "" extraPorts: null readinessProbe: enabled: true port: 8200 failureThreshold: 2 initialDelaySeconds: 5 periodSeconds: 5 successThreshold: 1 timeoutSeconds: 3 livenessProbe: enabled: false execCommand: [] path: "/v1/sys/health?standbyok=true" port: 8200 failureThreshold: 2 initialDelaySeconds: 60 periodSeconds: 5 successThreshold: 1 timeoutSeconds: 3 terminationGracePeriodSeconds: 10 preStopSleepSeconds: 5 preStop: [] postStart: [] extraEnvironmentVars: {} extraSecretEnvironmentVars: [] extraVolumes: [] volumes: null volumeMounts: null affinity: | podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchLabels: app.kubernetes.io/name: {{ template "vault.name" . }} app.kubernetes.io/instance: "{{ .Release.Name }}" component: server topologyKey: kubernetes.io/hostname topologySpreadConstraints: [] tolerations: [] nodeSelector: {} networkPolicy: enabled: false egress: [] ingress: - from: - namespaceSelector: {} ports: - port: 8200 protocol: TCP - port: 8201 protocol: TCP priorityClassName: "" extraLabels: {} annotations: {} includeConfigAnnotation: false service: enabled: true active: enabled: true annotations: {} standby: enabled: true annotations: {} instanceSelector: enabled: true ipFamilyPolicy: "" ipFamilies: [] publishNotReadyAddresses: true externalTrafficPolicy: Cluster port: 8200 targetPort: 8200 annotations: {} dataStorage: enabled: true size: 1Gi mountPath: "/vault/data" storageClass: "csi-s3" accessMode: ReadWriteOnce annotations: {} labels: {} persistentVolumeClaimRetentionPolicy: {} auditStorage: enabled: false size: 1Gi mountPath: "/vault/audit" storageClass: "csi-s3" accessMode: ReadWriteOnce annotations: {} labels: {} dev: enabled: false devRootToken: "root" standalone: enabled: false config: |- ui = true listener "tcp" { tls_disable = 1 address = "[::]:8200" cluster_address = "[::]:8201" } storage "file" { path = "/vault/data" } ha: enabled: true replicas: 3 apiAddr: null clusterAddr: null raft: enabled: true setNodeId: false config: | ui = true listener "tcp" { tls_disable = 1 address = "[::]:8200" cluster_address = "[::]:8201" } storage "raft" { path = "/vault/data" } service_registration "kubernetes" {} disruptionBudget: enabled: true maxUnavailable: null serviceAccount: create: true name: "" createSecret: false annotations: {} extraLabels: {} serviceDiscovery: enabled: true statefulSet: annotations: {} securityContext: pod: {} container: {} hostNetwork: false ui: enabled: true publishNotReadyAddresses: true activeVaultPodOnly: false serviceType: "ClusterIP" serviceNodePort: null externalPort: 8200 targetPort: 8200 serviceIPFamilyPolicy: "" serviceIPFamilies: [] externalTrafficPolicy: Cluster annotations: {} csi: enabled: true image: repository: "hashicorp/vault-csi-provider" tag: "1.5.1" pullPolicy: IfNotPresent volumes: null volumeMounts: null resources: {} hmacSecretName: "" hostNetwork: false daemonSet: updateStrategy: type: RollingUpdate maxUnavailable: "" annotations: {} providersDir: "/var/run/secrets-store-csi-providers" kubeletRootDir: "/var/lib/kubelet" extraLabels: {} securityContext: pod: {} container: {} pod: annotations: {} tolerations: [] nodeSelector: {} affinity: {} extraLabels: {} agent: enabled: true extraArgs: [] image: repository: "hashicorp/vault" tag: "1.20.4" pullPolicy: IfNotPresent logFormat: standard logLevel: info resources: {} securityContext: container: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsNonRoot: true runAsUser: 100 runAsGroup: 1000 priorityClassName: "" serviceAccount: annotations: {} extraLabels: {} readinessProbe: failureThreshold: 2 initialDelaySeconds: 5 periodSeconds: 5 successThreshold: 1 timeoutSeconds: 3 livenessProbe: failureThreshold: 2 initialDelaySeconds: 5 periodSeconds: 5 successThreshold: 1 timeoutSeconds: 3 logLevel: "info" debug: false extraArgs: [] serverTelemetry: serviceMonitor: enabled: false selectors: {} interval: 30s scrapeTimeout: 10s tlsConfig: {} authorization: {} metricRelabelings: [] prometheusRules: enabled: false selectors: {} rules: []

После установки кластера с включенным HA-режимом Vault не инициализируется автоматически. Это нужно сделать вручную с помощью CLI.

Для инициализации Vault подключитесь к основному поду (vault-0) :

    
kubectl exec -it vault-0 -n vault -- /bin/sh

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

    
export VAULT_ADDR=http://127.0.0.1:8200 export VAULT_CLIENT_TIMEOUT=300s vault operator init

В результате вы получите несколько Unseal Keys и Initial Root Token. Сохраните эти данные в надежном месте — без них восстановить доступ к Vault будет невозможно.

Пример вывода:

    
Unseal Key 1: 4ErPXwe87rjULP6yz7h3XZ8Dr/nhTyMrVLiIsQ8s5ksX Unseal Key 2: IVk3hipR5D/yR5ngi1LJaaxRwarEWjR/hjC8DFwXuNYb Unseal Key 3: qBCx+7B+wiehep0yArs7nVT73SyMYXh+AH3jCXTCs80H Unseal Key 4: CQm+0tOTS9wZQWYJJU8Roo2tMCGS+dZt7eXMDLjU5gX+ Unseal Key 5: KTvyD+vhEXPNQgcQJQe69Gu/sjkhhl/ScGZNnmmN64xC Initial Root Token: hvs.uKO8ZtmUgARVtrLhzBlQV4tA

По умолчанию создается 5 ключей, из которых требуется минимум 3 для активации хранилища.

После инициализации Vault находится в sealed состоянии. Чтобы запустить кластер, его нужно активировать. Для этого:

  1. Подключитесь к каждому поду по очереди (vault-0, vault-1, vault-2).

  1. Выполните команду, указав три любых из полученных ключей:

    
vault operator unseal <UNSEAL_KEY_1> vault operator unseal <UNSEAL_KEY_2> vault operator unseal <UNSEAL_KEY_3>
  1. Проверьте статус:

    
vault status

Если все прошло успешно, Sealed будет иметь значение false.

Была ли статья полезна?
Ваша оценка очень важна
Пока нет комментариев