Running Terraform Enterprise Active-Active on OpenShift: Lessons Learned

2026年8月21日2 次浏览来源:Dev.to阅读原文

Introduction In my last post, I covered the four challenges I hit running Vault Enterprise on OpenShift.

That same lab cluster also runs Terraform Enterprise (TFE) in active-active mode, using that Vault cluster as its secrets backend.

TFE brought its own set of OpenShift-specific problems — some in TFE itself, some in the supporting PostgreSQL and object storage layers, and one that turned out to be the same VSO bug from the Vault post showing up again in a different place.

The deployment follows the same GitOps pattern as Vault: ArgoCD, a three-source Helm setup (upstream TFE chart, a values file from the repo, and raw manifests for VSO custom resources, the Route, and the ImageStream/BuildConfig that supporting pieces need).

TFE runs with 2 replicas against a CloudNativePG-based PostgreSQL cluster, a Redis deployment for active-active coordination, and a NooBaa S3 bucket (via OpenShift Data Foundation) for object storage.

Every secret TFE needs — license, encryption password, database credentials, Redis password, S3 keys, registry pull secret, TLS certificate — comes from the local Vault cluster through Vault Secrets Operator (VSO).

This post covers five things that caught me off guard: TFE's hard refusal to run mixed versions during a rolling update, why one Postgres cluster ended up with two different Vault-managed role designs, a missing trust anchor for the in-cluster S3 endpoint, the VSO stuck-reconciliation bug recurring across two more secrets, and what it takes to get TFE's job agent running under OpenShift's restricted security model.

Challenge 1: Active-Active Means Lockstep Versions The Problem TFE's active-active mode replicates its Rails processes across multiple pods that all have to agree on the running version.

I found this out during what should have been a routine chart and image bump.

The new pod came up as while the two existing pods stayed healthy: The root cause is the Helm chart's default strategy with — it starts the new-version pod alongside the two still-running old-version pods to keep capacity up during the rollout.

TFE's own startup check treats that mixed-version state as invalid and refuses to come up, so the new pod crash-loops forever while the old pods sit there looking healthy.

The Solution The fix is to pin the Deployment to : tears down all pods before bringing any of them back up on the new image, so there's never a moment where two versions coexist.

The trade-off is real and worth stating plainly: every deploy that touches the pod template — image bump or not — causes a brief full TFE outage while pods restart (around 3 minutes, observed).

For an active-active system, that's a step back from zero-downtime rollouts, but it's the only option that matches TFE's lockstep version requirement.

If you ever hit the crash-loop mid-upgrade (say, the strategy setting got reverted by mistake), the recovery is a coordinated restart: One subtlety if you're running ArgoCD with : it will fight the scale-to-0 and start restoring replicas almost immediately.

That's fine here — the new ReplicaSet on the new image brings both pods up together, which is exactly what you want.

Both pods reached within a few minutes.

Challenge 2: One Postgres Cluster, Two Vault Role Designs The Problem Vault's database secrets engine has an obvious, idiomatic pattern: a dynamic role that creates a brand-new Postgres user on every lease, with a short TTL.

That's what I set up first: It works — Vault happily mints a fresh, uniquely-named Postgres role every hour.

The problem is that TFE doesn't want that.

It expects to connect as one stable database user across restarts, and its migrations need that user to own the database and the schema — not just have grants on them.

Dynamic per-lease roles with randomized names don't fit that model at all.

The Solution The fix was to layer Vault's static role feature on top of the same database connection, rather than replacing the dynamic role.

A static role manages the password for an ex

分享
Baike.dev

baike.dev helps you discover great languages, frameworks, databases, DevOps and cloud-native tools.

Quick links

About

Contribute

Found a great developer tool? Share it with the community.

Submit a tool
© 2026 baike.dev Developer EncyclopediaUpdated daily · Discover great developer tools