Skip to content

feat(aws): make instance refresh safe on one-node clusters - #29

Merged
BSick7 merged 2 commits into
masterfrom
feat/single-node-upgrade-path
Oct 7, 2026
Merged

BSick7 merged 2 commits into
masterfrom
feat/single-node-upgrade-path

Conversation

@BSick7

@BSick7 BSick7 commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Why

A rolling instance refresh on aws-ec2-vault-cluster counted a new node healthy on EC2 status alone and terminated the old node before the new one had joined Raft. On a one-node cluster that is the only copy of the data. It happened on the previews-shared cluster during an upgrade; the new node sat uninitialized and the old root volume went with the instance.

What

Two Auto Scaling lifecycle hooks, answered by a new vault-utils lifecycle daemon (vault-lifecycle.service) on each node:

  • vault-join holds a new instance in Pending:Wait until it is unsealed, a Raft voter, and caught up. A node that never joins is abandoned after 30 minutes, which fails the refresh and rolls it back with the old node untouched.
  • vault-leave holds a departing instance in Terminating:Wait until it has stepped down (if leader) and removed itself from the peer set, so the survivors keep quorum. It terminates either way after two minutes of retries; the sole voter is left in place.
  • Operator policy gains sys/step-down and sys/storage/raft/remove-peer. Goldens regenerated.
  • IAM: autoscaling:DescribeAutoScalingInstances, and autoscaling:CompleteLifecycleAction scoped by the cluster tag (the group name is unknown at plan time).
  • Instance refresh instance_warmup = 60; the hook, not warmup, proves the node joined. ASG health check stays EC2 on purpose: an ELB check would replace a one-node cluster on transient Vault unhealth.
  • CHANGELOG: adds the missing 0.3.0 entry; 0.3.1 unchanged.

Rollout

  • Needs a fresh node AMI (new daemon and unit). Tag to bake, then apply.
  • A cluster bootstrapped before 0.4.0 must rewrite the operator policy with a break-glass root before the leave step works; otherwise it logs a permission error and falls through to plain termination.
  • The launch-template change rolls the nodes.

Verification

go vet, go test -short ./..., Docker-backed TestOperatorBreakGlass, tofu fmt, tofu validate, tofu test (new hook assertion). Not exercised: a live instance refresh.

Not fixed

Why the original join failed. The node that knew is gone. With the join gate a repeat is harmless and journalctl -u vault-lifecycle will show the join state next time.

BSick7 added 2 commits October 7, 2026 17:13
A rolling refresh counted a new node healthy on EC2 status alone and
terminated the old node, the only copy of the data, before the new one
had joined Raft. Two lifecycle hooks, answered by a new `vault-utils
lifecycle` daemon on each node, close that gap at any cluster size:

- vault-join holds a new instance in Pending:Wait until it is unsealed,
  a Raft voter, and caught up. A node that never joins is abandoned
  after 30 minutes, which fails the refresh and rolls it back.
- vault-leave holds a departing instance in Terminating:Wait until it
  has stepped down and removed itself from the peer set, so the
  survivors keep quorum. It terminates either way after two minutes.

The operator policy gains sys/step-down and sys/storage/raft/remove-peer
for the leave step. The ASG health check stays EC2 on purpose.

Nodes now advertise api_addr as the URL clients use (user_vault_addr
with a subdomain, else vault_addr) instead of https://vault.internal,
which the NLB certificate never names. A standby redirect broke the web
UI with "The request failed and the interceptors did not return an
alternative response".

Needs a fresh node AMI. Module 0.4.0.
@BSick7
BSick7 merged commit 2b4f714 into master Oct 7, 2026
7 checks passed
@BSick7
BSick7 deleted the feat/single-node-upgrade-path branch October 7, 2026 21:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant