The headline feature of KV v2 is safely keeping multiple versions of the same secret. In real-world operations, that maps directly to rollback, audit, and conflict prevention via CAS (check-and-set).
This article covers the differences from v1, the behavior of delete/destroy/undelete, the metadata fields, and the API-path pitfalls — all framed around what the exam tends to ask.
KV v2 manages metadata independently from the value itself and auto-assigns a version number on every write. Overwriting the latest version preserves the previous ones, so you can restore or diff them.
The API paths are not compatible with v1. The CLI hides this, but in policies and direct API calls you must split between `data/` and `metadata/`.
| Aspect | KV v1 | KV v2 | Exam angle |
|---|---|---|---|
| Versioning | None | Yes (auto-numbered) | Whether you can read/restore a specific version |
| API path | /v1/<mount>/<path> | /v1/<mount>/data|metadata/<path> | Policies must also reference `data/` and `metadata/` |
| Delete behavior | Simple delete | `delete` = tombstone, `destroy` = purge | Only `delete` is reversible via `undelete` |
| CAS | None | Yes (`-cas` flag and `metadata.cas_required`) | The basics of optimistic concurrency control |
| Metadata config | Limited | `max_versions`, `cas_required`, `delete_version_after`, etc. | Mind how older versions are handled when the limit is exceeded |
KV v2 request path and version retention
Client
| vault kv put/get/delete
v
[Mount: secret (kv-v2)]
|-- /v1/secret/data/<path> # Value and version operations
|-- /v1/secret/metadata/<path> # Attributes, limits, deletion state
'-- backend storage (raft/consul)
Versions: 1 -> 2 -> 3 (latest)
delete: tombstone (reversible)
destroy: purge (permanent)Enable the engine and verify the basics
vault secrets enable -path=secret kv-v2
vault kv put secret/app api_key=AAA env=prod # create v1
vault kv put secret/app api_key=BBB # create v2
vault kv get secret/app # default returns the latest (v2)
vault kv get -version=1 secret/app # read a previous versionOn the CLI, the `-version` flag reads any previous version you want. Writes always create a new version — they never overwrite an existing one.
`list` returns the keys under a hierarchy (the CLI `list` works on v2 too). When calling the API directly, listings live under the `metadata/` path.
Version reads and listings
# Latest and a specific version
vault kv get secret/app
vault kv get -version=1 secret/app
# Pull just the version number via JSON
vault kv get -format=json secret/app | jq -r '.data.metadata.version'
# List
vault kv list secret/
Each version's metadata carries `created_time`, `deletion_time`, `destroyed`, and `version`. That lets your code decide programmatically whether a version is recoverable and when it was created.
Metadata settings control `max_versions` (retention cap), `cas_required` (require CAS on updates), and `delete_version_after` (auto-cleanup timer for soft-deleted versions). When unset, the mount's defaults apply.
Reading and writing metadata (CLI and API)
# Read metadata for a single key
vault kv metadata get secret/app
# Set metadata (limit / CAS / delayed delete)
vault kv metadata put -max-versions=20 -cas-required=true -delete-version-after=168h secret/app
# Read and write metadata via the API
curl -s \
-H "X-Vault-Token: $VAULT_TOKEN" \
$VAULT_ADDR/v1/secret/metadata/app | jq
curl -s -X POST \
-H "X-Vault-Token: $VAULT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"max_versions":20, "cas_required":true, "delete_version_after":"168h"}' \
$VAULT_ADDR/v1/secret/metadata/app
In KV v2, `delete` soft-deletes (tombstones) the specified version. You can bring it back with `undelete`. `destroy` permanently wipes the version's data — there is no coming back.
Deleting the metadata for an entire key (`metadata delete`) wipes every version and all metadata at once. The blast radius is huge, so design your capabilities carefully.
Delete-and-undelete sequence
# Check v2 (the latest)
vault kv get secret/app
# Soft-delete v1 (reversible)
vault kv delete -versions=1 secret/app
vault kv get -version=1 secret/app # unreadable (tombstone)
vault kv undelete -versions=1 secret/app # bring it back
vault kv get -version=1 secret/app # readable again
# Destroy v1 permanently (irreversible)
vault kv destroy -versions=1 secret/app
# Wipe the entire key (all versions and metadata)
vault kv metadata delete secret/app
With CAS, the client states the version it expects to update, and the write is accepted only if that matches. It prevents mix-ups under concurrent updates.
Rollback usually means reading a previous version and writing its contents back as a brand-new version. You are not really "going back" to the old version — you are creating a new version that contains the old contents.
CAS update and rollback example
# Look up the current version
CURR=$(vault kv get -format=json secret/app | jq -r '.data.metadata.version')
# Safe update with CAS (fails on mismatch)
vault kv put -cas="$CURR" secret/app api_key=CCC
# Roll back using v1's contents (written as v3)
OLD=$(vault kv get -format=json -version=1 secret/app | jq -r '.data.data | to_entries | map(\"\(.key)=\(.value)\") | join(" ")')
eval vault kv put secret/app $OLD
On v2 you must grant appropriate capabilities on both `data/` and `metadata/`. Keep `read` vs `list`, and `delete` vs `destroy` / `metadata delete`, clearly separated.
To control storage growth, combine `max_versions` with `delete_version_after`. Pruning older versions when the cap is hit avoids hoarding data you do not need.
Least-privilege policy example for v2
path "secret/data/app" {
capabilities = ["create", "update", "read"]
}
path "secret/metadata/app" {
capabilities = ["read", "list", "update"]
}
# Keep destructive operations in a separate role
path "secret/destroy/app" {
capabilities = ["update"]
}
path "secret/metadata/app" {
capabilities = ["delete"] # for metadata delete (use carefully)
}
Associate
問題 1
In KV v2, you want to make a specific version inaccessible while keeping future restoration possible. Which operation fits best?
正解: A
`delete` is a soft delete (tombstone) and can be reversed later with `undelete`. `destroy` is irreversible, `metadata delete` wipes the entire key, and `put -cas` is an update, not a delete.
How do I permanently remove a specific version?
Use `vault kv destroy -versions=N <mount>/<path>`. `delete` is a soft delete — the data still lives in storage and can be undeleted, so it is not a real purge.
After switching to v2, my API calls return 404 or permission denied.
Your policies or request paths are probably still v1-shaped. For v2, reads go through `/v1/<mount>/data/<path>`, while metadata and listings go through `/v1/<mount>/metadata/<path>`. Grant capabilities on the matching paths.
What happens to older versions once `max_versions` is exceeded?
When a new write pushes the count over the limit, the oldest versions are automatically pruned and can no longer be read or undeleted. Plan the limit around your retention requirements.
Practice with certification-focused question sets
無料で問題を解いてみるNicheeLab Editorial Team
NicheeLab editorial team focused on data engineering and cloud certification learning. Content is structured around practical study needs and official exam domains.
Vault Core Concepts: Sealed/Unsealed, Auth, Secrets (2026)
Vault fundamentals — sealed/unsealed state, auth methods, se...
Vault Operations Professional (VOP-003): Complete Guide (2026)
Pass the Vault Operations Professional exam — enterprise pat...
Vault Path-Based Routing: API URL Structure (2026)
How Vault's path-based routing works — mount points, sub-pat...
Vault Tokens: Auth Token Mechanics (2026)
Token fundamentals — service vs. batch tokens, accessor, ren...
Vault Token Types: Service, Batch, Periodic (2026)
Service vs. batch tokens compared — performance, ACL behavio...