Vault é um sistema de gerenciamento de segredos da HashiCorp que permite armazenar e acessar com segurança tokens, senhas, certificados e outros dados sensíveis.
No Kubernetes, o Vault é usado como armazenamento externo de segredos e pode fornecer gerenciamento centralizado de acesso.
Você pode instalar o Vault no cluster através do painel de controle Hostman. Para isso:
values.yaml;A configuração padrão assume que o add-on será executado no modo dev. Este é um modo simplificado em que o Vault se inicializa automaticamente, não requer configuração de armazenamento e utiliza um token root pré-configurado.
O modo dev é adequado apenas para testes e desenvolvimento; não é seguro para produção.
Após a instalação, certifique-se de que os componentes do Vault foram iniciados com sucesso. Execute o seguinte comando:
kubectl get pods -n vault
Você deve ver uma lista de pods, incluindo:
vault-0: o pod principal do Vault;vault-agent-injector-xxx: o serviço responsável por injetar segredos automaticamente nos pods;vault-1, vault-2) se o Vault estiver instalado em modo HA.Se a configuração incluir a opção ui = true (ativada por padrão), você pode acessar a interface web do Vault.
kubectl port-forward -n vault svc/vault 8200:8200
http://localhost:8200
No modo dev, o Vault já está inicializado, e você pode fazer login usando o token especificado na configuração.
Por padrão, o valor é:
devRootToken: "root"

HashiCorp Vault Interface
O modo HA (Alta Disponibilidade) permite implantar várias instâncias do Vault com armazenamento de dados distribuído. Isso fornece:
Um dos pods se torna o leader, enquanto os outros permanecem em standby. As requisições de leitura/escrita são tratadas apenas pelo leader, mas se ele ficar indisponível, o controle passa automaticamente para um dos pods em standby.
Para este modo funcionar, recomendamos instalar o add-on CSI-S3.
Para habilitar o modo HA, especifique os seguintes parâmetros na configuração do add-on:
server.dev.enabled: false # disable dev mode
server.standalone.enabled: false # disable standalone mode
server.ha.enabled: true # enable HA mode
server.ha.replicas: 3 # specify number of replicas
server.ha.raft.enabled: true # use built-in Raft storage
server.dataStorage.storageClass: csi-s3 # connect S3 storage via 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: []
Após instalar o cluster com o modo HA habilitado, o Vault não é inicializado automaticamente. Você deve fazer isso manualmente usando a CLI.
Para inicializar o Vault, conecte-se ao pod principal (vault-0):
kubectl exec -it vault-0 -n vault -- /bin/sh
Em seguida, execute os seguintes comandos:
export VAULT_ADDR=http://127.0.0.1:8200
export VAULT_CLIENT_TIMEOUT=300s
vault operator init
Você receberá várias Unseal Keys e um Initial Root Token. Armazene essas informações em um local seguro — sem elas, você não conseguirá restaurar o acesso ao Vault.
Exemplo de saída:
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
Por padrão, cinco chaves são geradas, e pelo menos três delas são necessárias para ativar o armazenamento.
Após a inicialização, o Vault estará em estado selado. Para iniciar o cluster, é necessário deslacrar.
Para isso:
vault-0, vault-1, vault-2).vault operator unseal <UNSEAL_KEY_1>
vault operator unseal <UNSEAL_KEY_2>
vault operator unseal <UNSEAL_KEY_3>
vault status
Se tudo ocorreu corretamente, o campo Sealed terá o valor false.