---
title: "Аддон Vault для Kubernetes"
description: "Аддон Vault для Kubernetes. Установка, настройка, примеры использования. Документация и инструкции по работе с облачными сервисами Timeweb Cloud."
---

# Vault

> Полный индекс документации для ИИ-агентов: [llms.txt](https://timeweb.cloud/llms.txt).

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

## Установка

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

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

![Scr 20251021 Piuk](https://content.timeweb.com/assets/f96762ca-3fae-4978-abd8-0fc40d7ce61b.png?width=1984&height=1656)

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

1.  Переключитесь в режим продвинутой установки;
    
2.  Отредактируйте конфигурацию вручную или загрузите свой файл `values.yaml`;
    
3.  Нажмите кнопку «Установить».
    

![Scr 20251021 Pizg](https://content.timeweb.com/assets/c861f3e3-215e-4d4c-b0b3-0a1e60a485c5.png?width=1984&height=1592)

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

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

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

```shell
kubectl get pods -n vault
```

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

-   `vault-0` — основной под Vault;
    
-   `vault-agent-injector-xxx` — сервис, отвечающий за автоматическую подстановку секретов в поды;
    
-   дополнительные поды (например, `vault-1`, `vault-2`), если установлен в HA-режиме.
    

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

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

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

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

```shell
http://localhost:8200
```

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

```shell
devRootToken: "root"
```

![Scr 20251021 Qnui](https://content.timeweb.com/assets/cfcd1d4a-6972-4dd6-a46f-8a12771aee34.png?width=1612&height=875)

_Интерфейс [HashiCorp Vault](https://www.hashicorp.com/en/products/vault)_

## Режим HA

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

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

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

> [!NOTE]
> Для работы в этом режиме рекомендуем установить и использовать дополнения [CSI-S3](https://timeweb.cloud/docs/k8s/addons/csi-s3) или [CSI-driver](https://timeweb.cloud/docs/k8s/network-drives-connection).

Чтобы включить режим 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.

Пример конфигурации (нажмите, чтобы развернуть)

```yaml
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`) :

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

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

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

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

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

```shell
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`).
    

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

```shell
vault operator unseal <UNSEAL_KEY_1>
vault operator unseal <UNSEAL_KEY_2>
vault operator unseal <UNSEAL_KEY_3>
```

3.  Проверьте статус:
    

```shell
vault status
```

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