<div><img src="https://top-fwz1.mail.ru/counter?id=3548135;js=na" style="position:absolute;left:-9999px;" alt="Top.Mail.Ru" /></div>
Managed Kubernetes — разверните готовый кластер за 5 минут →
Вход / Регистрация
На главную
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

Режим 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.

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