Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
2b7b862
initial draft for EKS how-to
mister-ken Oct 1, 2025
fdba38a
update the docs-nav-data.json to include amazon-eks.md
mister-ken Oct 1, 2025
1d75d03
update eks file name, add aks.md
mister-ken Oct 6, 2025
7befb69
Merge branch 'main' into vault/k8s-how-tos-eks
mister-ken Oct 6, 2025
d147159
clean up aks.md
mister-ken Oct 7, 2025
94ebe00
clean up aks.md
mister-ken Oct 7, 2025
f54aa08
Merge branch 'main' into vault/k8s-how-tos-eks
mister-ken Oct 7, 2025
a572704
fix titles
mister-ken Oct 7, 2025
ebc6984
Merge branch 'main' into vault/k8s-how-tos-eks
mister-ken Oct 7, 2025
4f19b25
Merge branch 'main' into vault/k8s-how-tos-eks
mister-ken Oct 7, 2025
928d468
change user id to username
netramali Oct 7, 2025
ee80626
add beta partial to mcp docs
trujillo-adam Oct 7, 2025
2ceacde
add missing docs for oracle
vinay-gopalan Oct 6, 2025
d8bacbe
address feedback
vinay-gopalan Oct 7, 2025
cb32f2a
Update content/vault/v1.20.x/content/docs/secrets/databases/oracle.mdx
schavis Oct 7, 2025
e890561
Update content/vault/v1.19.x/content/docs/secrets/databases/oracle.mdx
schavis Oct 7, 2025
749a8a7
Compress Vault images (#1044)
RubenSandwich Oct 7, 2025
ea01cc4
new supported product api route (#1059)
RubenSandwich Oct 7, 2025
510e921
Add information on the HCP Terraform Operator for Kubernetes to the a…
BrianMMcClain Oct 7, 2025
7b75460
Add a note to change the tfc_hostname variable (#1068)
rkoron007 Oct 7, 2025
b88440b
Updates and optimizes images
Younique98 Oct 7, 2025
3423a1e
Update CLI documentation to reflect changes from Admin API to System …
nikolasrieble Oct 7, 2025
2196af5
Update content/terraform-enterprise/1.0.x/docs/enterprise/deploy/refe…
nikolasrieble Oct 8, 2025
ef8b048
trigger CI
nikolasrieble Oct 8, 2025
6a08482
cleaned up after vale review
mister-ken Oct 8, 2025
36de543
Merge branch 'main' into vault/k8s-how-tos-eks
mister-ken Oct 8, 2025
78b1ba5
Merge branch 'main' into vault/k8s-how-tos-eks
mister-ken Oct 13, 2025
f51a44f
standardization of cloud k8s how-tos
mister-ken Oct 13, 2025
13dd833
expanded cloud deplo indexes
mister-ken Oct 13, 2025
77acf69
fix title for azure index
mister-ken Oct 13, 2025
e14cee9
Merge branch 'main' into vault/k8s-how-tos-eks
mister-ken Oct 13, 2025
b06715b
clean up typo and standarize preqs, steps on vault
mister-ken Oct 14, 2025
2b97675
Merge branch 'main' into vault/k8s-how-tos-eks
mister-ken Oct 14, 2025
dd6e5a5
removed references to lease quota tutorial
mister-ken Oct 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
449 changes: 449 additions & 0 deletions content/vault/v1.20.x/content/docs/deploy/aws/eks-anywhere.mdx

Large diffs are not rendered by default.

384 changes: 384 additions & 0 deletions content/vault/v1.20.x/content/docs/deploy/aws/eks.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,384 @@
---
layout: docs
page_title: Deploy Vault on Amazon EKS
description: >-
Guide to deploying and setting up Vault on Amazon EKS.
---

# Deploy Vault on Amazon EKS

Amazon Elastic Kubernetes Service (EKS) can run and scale Vault in the Amazon Web Services (AWS) cloud or on-premises. Amazon EKS is a managed Kubernetes service that makes it easy to run Kubernetes without needing to install and operate your own Kubernetes control plane or nodes.

In this guide, you create an EKS cluster in AWS, deploy a MySQL server, install Vault in high-availability (HA) mode via the Helm chart. Then you configure the authentication between Vault and the cluster.

## Prerequisites

This guide focuses on setting up HashiCorp Vault on Amazon EKS and assumes a understanding of both Amazon EKS concepts and terminology. The guide assumes the user is familiar with AWS accounts, EKS clusters, Kubernetes pods, service accounts, and manifests.

This guide requires:

- [AWS account](https://aws.amazon.com/account/)
- [AWS command-line interface (CLI)](https://aws.amazon.com/cli/)
- [Amazon EKS CLI](https://docs.aws.amazon.com/eks/latest/userguide/getting-started-eksctl.html)
- [Kubernetes CLI](https://kubernetes.io/docs/tasks/tools/install-kubectl/)
- [Helm CLI](https://helm.sh/docs/helm/)
- [jq](https://jqlang.org/)

In addition you need to have the Vault Helm chart. You can add the Helm repositories with the following commands:

```shell-session
$ helm repo add hashicorp https://helm.releases.hashicorp.com
"hashicorp" has been added to your repositories
```

You will need a SSH key pair to access the nodes in your cluster. You can create a key pair using the AWS Management Console or the AWS CLI. For more information, see [Create a key pair for Amazon EC2 instances](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/create-key-pairs.html).

## Step 1: Start cluster

A high availability Vault cluster that requires a Kubernetes cluster with three nodes.

1. Log in to your AWS account with the AWS CLI.

1. Create a three node cluster named `learn-vault`.

```shell-session
$ eksctl create cluster \
--name learn-vault \
--nodes 3 \
--with-oidc \
--ssh-access \
--ssh-public-key learn-vault \
--managed
```

1. MySQL needs EBS volume type to use a the `gp2` storage class as the default. Patch the default storage class with the following command.

```shell-session
$ kubectl patch storageclass gp2 -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
```

1. Once all the nodes are in `Ready` status, enable volume support with the [EBS CSI driver add-on](https://docs.aws.amazon.com/eks/latest/userguide/ebs-csi.html).

```shell-session
$ eksctl create iamserviceaccount \
--name ebs-csi-controller-sa \
--namespace kube-system \
--cluster learn-vault \
--attach-policy-arn arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy \
--approve \
--role-only \
--role-name AmazonEKS_EBS_CSI_DriverRole
```

1. Run the following command to create the add-on:

```shell-session
$ eksctl create addon \
--name aws-ebs-csi-driver \
--cluster learn-vault \
--service-account-role-arn arn:aws:iam::$(aws sts get-caller-identity --query Account --output text):role/AmazonEKS_EBS_CSI_DriverRole
```

The cluster is ready.

## Step 2: Install Vault

The Vault Helm chart contains all the necessary components to run Vault in several different modes.

1. Create a file named `helm-vault-raft-values.yml` with the following contents:

```shell-session
$ cat > helm-vault-raft-values.yml <<EOF
server:
affinity: ""
ha:
enabled: true
raft:
enabled: true
setNodeId: true
config: |
cluster_name = "vault-integrated-storage"
storage "raft" {
path = "/vault/data/"
}

listener "tcp" {
address = "[::]:8200"
cluster_address = "[::]:8201"
tls_disable = "true"
}
service_registration "kubernetes" {}
EOF
```

<Note title="Recommendation">

If you are using Prometheus for monitoring and alerting, we recommend to set the `cluster_name` in the HCL configuration. use the `config` parameter in the Vault Helm chart.

</Note>

Helm deploys the Vault pods and Vault Agent Injector pod in the default namespace.

1. Install the latest version of the Vault Helm chart with Integrated Storage.

```shell-session
$ helm install vault hashicorp/vault --values helm-vault-raft-values.yml
```

This creates three Vault server instances with an Integrated Storage (Raft) backend.

Helm installs the Vault pods and Vault Agent Injector pod in the default namespace.

## Step 3: Initialize and unseal primary Vault pod

Vault starts [uninitialized](/vault/docs/commands/operator/init) and in the [sealed](/vault/docs/concepts/seal#why) state. Prior to initialization the Integrated Storage backend is not prepared to receive data.

1. Initialize Vault with one key share and one key threshold.

```shell-session
$ kubectl exec vault-0 -- vault operator init \
-key-shares=1 \
-key-threshold=1 \
-format=json > cluster-keys.json
```

1. Display the unseal key found in `cluster-keys.json`.

```shell-session
$ cat cluster-keys.json | jq -r ".unseal_keys_b64[]"
```

1. Create a variable named `VAULT_UNSEAL_KEY` to capture the Vault unseal key.

```shell-session
$ VAULT_UNSEAL_KEY=$(cat cluster-keys.json | jq -r ".unseal_keys_b64[]")
```

1. Unseal Vault running on the `vault-0` pod.

```shell-session
$ kubectl exec vault-0 -- vault operator unseal $VAULT_UNSEAL_KEY
```

## Step 4: Join the other Vaults to the Vault cluster

The Vault server running on the `vault-0` pod is a Vault HA cluster with a
single node. To display the list of nodes requires that you are logging in with
the root token.

1. Create a variable named `CLUSTER_ROOT_TOKEN` to capture the Vault unseal key.

```shell-session
$ CLUSTER_ROOT_TOKEN=$(cat cluster-keys.json | jq -r ".root_token")
```

1. Login with the root token on the `vault-0` pod.

```shell-session
$ kubectl exec vault-0 -- vault login $CLUSTER_ROOT_TOKEN
```

1. Join the Vault server on `vault-1` to the Vault cluster.

```shell-session
$ kubectl exec vault-1 -- vault operator raft join http://vault-0.vault-internal:8200
```

This Vault server joins the cluster sealed. To unseal the Vault server requires
the same unseal key, `VAULT_UNSEAL_KEY`, provided to the first Vault server.

1. Unseal the Vault server on `vault-1` with the unseal key.

```shell-session
$ kubectl exec vault-1 -- vault operator unseal $VAULT_UNSEAL_KEY
```

The Vault server on `vault-1` is now a functional node within the Vault
cluster.

1. Join the Vault server on `vault-2` to the Vault cluster.

```shell-session
$ kubectl exec vault-2 -- vault operator raft join http://vault-0.vault-internal:8200
```

1. Unseal the Vault server on `vault-2` with the unseal key.

```shell-session
$ kubectl exec vault-2 -- vault operator unseal $VAULT_UNSEAL_KEY
```

## Step 5: Set a secret in Vault

The web application expects Vault to store a username and password at the path `secret/webapp/config`. Creating this secret requires you to login with the root token, enable the key-value secret engine](/vault/docs/secrets/kv/kv-v2), and store a secret username and password at that defined path.

1. First, start an interactive shell session on the `vault-0` pod.

```shell-session
$ kubectl exec --stdin=true --tty=true vault-0 -- /bin/sh
/ $
```

This replaces the system prompt with a new prompt `/ $`.

1. Enable kv-v2 secrets at the path `secret`.

```shell-session
$ vault secrets enable -path=secret kv-v2
```

1. Create a secret at path `secret/devwebapp/config` with a `username` and
`password`.

```shell-session
$ vault kv put secret/devwebapp/config username='giraffe' password='salsa'
```

1. Verify that the secret is defined at the path `secret/data/devwebapp/config`.

```shell-session
$ vault kv get secret/devwebapp/config
```

<Note title="Learn more">

For more information refer to the [Versioned Key/Value Secrets Engine](/vault/tutorials/secrets-management/versioned-kv) tutorial.

</Note>

You created the secret for the web application.

## Step 7: Configure Kubernetes authentication

The initial [root token](/vault/docs/concepts/tokens#root-tokens) is a privileged user that can perform any operation at any path. The web application only requires the ability to read secrets defined at a single path. This application should authenticate and Vault grants a token with limited access.

<Note title="Best practice">

We recommend that [root
tokens](/vault/docs/concepts/tokens#root-tokens) are
used only for initial setup of an authentication method and policies. Afterwards they should be revoked. This tutorial does not show you how to revoke the root token.

</Note>

Vault provides a [Kubernetes authentication](/vault/docs/auth/kubernetes) method that enables clients to authenticate with a Kubernetes Service Account Token.

1. Enable the Kubernetes authentication method.

```shell-session
$ vault auth enable kubernetes
Success! Enabled kubernetes auth method at: kubernetes/
```

Vault accepts a service token from any client within the Kubernetes cluster. During authentication, Vault verifies that the service account token is valid by querying a token review Kubernetes endpoint.

1. Configure the Kubernetes authentication method to use the location of the Kubernetes API. It will automatically use the pod's own identity to authenticate with Kubernetes when querying the token review API.

```shell-session
$ vault write auth/kubernetes/config \
kubernetes_host="https://$KUBERNETES_PORT_443_TCP_ADDR:443"
```

1. Write out the policy named `devwebapp` that enables the `read` capability for secrets at path `secret/data/devwebapp/config`

```shell-session
$ vault policy write devwebapp - <<EOF
path "secret/data/devwebapp/config" {
capabilities = ["read"]
}
EOF
```

1. Create a Kubernetes authentication role named `devweb-app`.

```shell-session
$ vault write auth/kubernetes/role/devweb-app \
bound_service_account_names=internal-app \
bound_service_account_namespaces=default \
policies=devwebapp \
ttl=24h
```

The role connects a Kubernetes service account, `internal-app` (created in the next step), and namespace, `default`, with the Vault policy, `devwebapp`. The tokens returned after authentication are valid for 24 hours.

1. Lastly, exit the `vault-0` pod.

```shell-session
$ exit
```

## Step 8: Deploy web application

The web application pod requires the creation of the `internal-app` Kubernetes service account specified in the Vault Kubernetes authentication role created in the [Configure Kubernetes authentication](#configure-kubernetes-authentication)
step.

1. Create a Kubernetes service account named `internal-app`.

```shell-session
$ kubectl create sa internal-app
```

1. Define a pod named `devwebapp` with the web application.

```shell-session
$ cat > devwebapp.yaml <<EOF
---
apiVersion: v1
kind: Pod
metadata:
name: devwebapp
labels:
app: devwebapp
annotations:
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/role: "devweb-app"
vault.hashicorp.com/agent-inject-secret-credentials.txt: "secret/data/devwebapp/config"
spec:
serviceAccountName: internal-app
containers:
- name: devwebapp
image: caddy
EOF
```

This definition creates a pod with the specified container running with the `internal-app` Kubernetes service account. The container within the pod is unaware of the Vault cluster. The Vault Injector service reads the [annotations](/vault/docs/platform/k8s/injector#annotations) to find the secret path, stored within Vault at `secret/data/devwebapp/config` and the file location, `/vault/secrets/secret-credentials.txt`, to mount that secret with the pod.

<Note title="Learn more">

For more information about annotations refer to the
[Injecting Secrets into Kubernetes Pods via Vault Agent
Injector](/vault/tutorials/kubernetes/kubernetes-sidecar) tutorial.

</Note>

1. Create the `devwebapp` pod.

```shell-session
$ kubectl apply --filename devwebapp.yaml
```

1. Wait until the `devwebapp` pod reports that is running and ready (`2/2`).

1. Display the secrets written to the file `/vault/secrets/secret-credentials.txt`
on the `devwebapp` pod.

```shell-session
$ kubectl exec --stdin=true --tty=true devwebapp -c devwebapp -- cat /vault/secrets/credentials.txt
data: map[password:salsa username:giraffe]
metadata: map[created_time:2020-12-11T19:14:05.170436863Z deletion_time: destroyed:false version:1]
```

The result displays the unformatted secret data present on the container.

<Tip title="Format data">

Apply a [template](/vault/tutorials/kubernetes/kubernetes-sidecar#apply-a-template-to-the-injected-secrets) to this structure this data to meet the needs of the application.

</Tip>

## Step 9: Clean up

Destroy the cluster.

```shell-session
$ eksctl delete cluster --name learn-vault
```
Loading
Loading