Back to Resume
PrivateOctober 2023· 4 weeks

Exchange Platform on EKS (Helm, Istio, Vault)

Kubernetes Delivery of a Licensed Exchange Platform

RoleDevOps Engineer

A digital-asset exchange operator had bought a license to run a full trading platform, matching engine, market data, KYC, admin, the works, but needed it running on their own infrastructure. I packaged the licensed platform's 18 services into one versioned Helm chart for Amazon EKS, put a validated Istio mesh underneath it, and moved its secrets into HashiCorp Vault instead of the chart. The client got a repeatable, values-driven deployment of software they did not have to build.

The problem

The client licenses a third-party digital-asset exchange platform, not something built in-house, and needed it deployed and operated on their own AWS account rather than the vendor's infrastructure. That platform ships as roughly 18 separate container images: a matching engine, a market-data integration service, a KYC service, a block-sync service, a frontend, an admin panel, two backend-for-frontend services, and a three-part task-execution tier, each with its own configuration surface. Standing that up by hand, one `kubectl apply` at a time, means no repeatable path between environments and no single place to see or change how the whole platform is configured. The naive path, applying raw manifests per service, breaks down fast at 18 interdependent services that all need to agree on the same NATS cluster, the same Redis and Mongo endpoints, and the same feature toggles. What they needed was one deployable unit, a mesh that could carry latency-sensitive trading traffic, and secrets that lived outside version control.

Constraints

  • ·The application itself is licensed, closed-source software delivered as container images: configuration had to happen entirely through environment variables and Helm values, with no ability to change the application to fit the infrastructure.
  • ·Ten-week statement of work (2023-10-20), scoped and costed up front.
  • ·Eighteen interdependent services that all have to agree on shared configuration (NATS cluster name, Redis, MongoDB) without the chart forking per environment.
  • ·A trading platform is latency-sensitive, so a service mesh could not be bolted on without separate validation first.
  • ·Sole engineer on the infrastructure side of the engagement.

Architecture

One Helm chart (apiVersion v2) packages all 18 services of the licensed exchange platform as Kubernetes Deployments and Services on Amazon EKS. Istio (istio-base plus an ingress gateway) is installed into its own namespaces and validated independently before the platform is placed behind it. NGINX ingress handles the BFF and admin routes. Secrets (license key, database credentials, a custodial signing keypair) are read through a HashiCorp Vault AppRole login rather than committed to the chart, and cluster access is mapped from IAM to Kubernetes RBAC groups through an aws-auth ConfigMap.

  • Trading core: the matching engine and its internal counterpart
  • Market data: an integration service pulling a licensed commercial market-data feed
  • Compliance: a KYC API for customer verification
  • Chain integration: a block-sync service with a custodial signing-key integration
  • Front of house: frontend, admin panel, and two backend-for-frontend services
  • Task tier: a three-part API / task-host / executor split for automated trading strategies
  • Platform: NATS and MongoDB as their own workload+service pairs, fronted by NGINX ingress
  • Istio service mesh and ingress gateway, installed in dedicated namespaces
  • HashiCorp Vault (AppRole) for secret delivery, and an aws-auth-mapped EKS cluster for IAM-based access

Read left to right as EKS hosting the chart's 18 services behind Istio's ingress gateway and an NGINX ingress for the BFF/admin routes. Every service reads its configuration from Helm values, with Vault as the intended path for the secrets among them.

How one request flows

  1. 01Scope and cost the engagement: a ten-week statement of work covering the chart, the mesh, and the secrets path.
  2. 02Package the licensed platform: write one Helm chart with a template per service, driven entirely by values (replica counts, feature toggles, connection strings, the license key).
  3. 03Stand up the mesh separately: install istio-base and the ingress gateway into their own namespaces, enable sidecar injection, and validate with the Istio bookinfo sample and istioctl analyze before trusting it with real traffic.
  4. 04Wire secret delivery: read a Vault AppRole role-id, generate a secret-id, and exchange both for a token that can read the platform's secrets.
  5. 05Map cluster access: bind the EKS node IAM role to Kubernetes RBAC groups through the aws-auth ConfigMap.
  6. 06Deploy the platform: `helm install` the chart onto the validated mesh, with the private registry's licensed images pulled via imagePullSecrets.
  7. 07Hand over: the chart, the mesh, and the AppRole flow are the client's to operate and to scale by changing values, not manifests.

Engineering decisions

One chart, driven entirely by values

What. Packaged all 18 services into a single Helm chart where replica counts, feature toggles (Redis auth on/off, risk engine on/off), and connection strings are values, not template forks.

Why. The application is licensed and closed, so infrastructure is the only lever available. A single values-driven chart means an environment change is a values edit, not a manifest rewrite.

Tradeoff. One large chart is harder to reason about at a glance than 18 small ones, accepted because the services are genuinely coupled (shared NATS, Redis, Mongo) and have to move together.

Mesh validated before the platform touches it

What. Installed Istio into its own istio-system and istio-ingress namespaces and validated it with the bookinfo sample plus istioctl analyze before deploying the real services behind it.

Why. A latency-sensitive trading workload is the wrong place to discover a mesh misconfiguration. A disposable sample app is the cheap place to find that instead.

Tradeoff. An extra validation pass before every real deployment, worth the time given what a mesh outage would mean for a live matching engine.

Cluster access from IAM, not a separate credential

What. Mapped the EKS node IAM role to Kubernetes RBAC groups (system:bootstrappers, system:nodes) through the aws-auth ConfigMap.

Why. This is the standard EKS bridge between AWS identity and Kubernetes identity, avoiding a second access-control system to keep in sync with IAM.

Tradeoff. None significant. This is the supported pattern, not a workaround.

Vault AppRole for the secrets path, though not fully wired end to end

What. Set up an AppRole login (role-id plus a generated secret-id exchanged for a token) so secrets could be read from Vault at request time instead of committed to the chart.

Why. AppRole avoids static long-lived credentials in the chart's version-controlled values.

Tradeoff. Honestly: the delivered chart still carries several of these same secrets (the database password, a signing keypair, the license key, a JWT secret) as plain values entries, not pulled from Vault by the templates. The AppRole path was built and proven, but not every secret was migrated onto it before delivery. That gap is real and is called out rather than hidden.

What changed along the way

  • The original SoW's architecture diagram depicted ECS. The actual target was always EKS per the written scope, and the delivered chart is unambiguously EKS-only.
  • Two ingress templates (the BFF/admin NGINX ingress and the frontend ingress) ended up with hardcoded hostnames instead of the `.Values.bffURL` / `.Values.adminURL` fields that already existed in the chart for exactly that purpose, evident from a comment left in place next to each hardcoded line.
  • Not every secret made it onto the Vault AppRole path before delivery. Only the flow itself was proven. The database password, a custodial signing keypair, the license key, and a JWT secret remained as plain chart values.

Security and reliability

  • ·Secrets: intended path is HashiCorp Vault AppRole (role-id plus a generated, single-namespace secret-id exchanged for a token). Several credentials still shipped as plain chart values rather than fully migrated onto that path.
  • ·Access control: EKS cluster access mapped from IAM roles to Kubernetes RBAC groups via aws-auth, rather than a separate Kubernetes-native credential.
  • ·Network: Istio mesh with namespace-level sidecar injection, installed and validated independently before carrying production traffic.
  • ·Image supply: licensed container images pulled from a private registry via named imagePullSecrets.
  • ·Deployment strategy: Kubernetes Deployments use the Recreate strategy per service, trading brief downtime on rollout for avoiding two versions of a stateful trading service running at once.

Metrics

18
services packaged into one versioned Helm chart
measured
4 months
statement of work to production delivery (Oct 2023 to Jan 2024)
measured
1
engineer delivering the full Kubernetes build
measured

What shipped

  • An 18-service exchange platform packaged as a single versioned Helm chart, deployable from values rather than hand-edited manifests.
  • Istio mesh and ingress gateway installed into dedicated namespaces and validated independently before carrying production services.
  • Secrets moved to HashiCorp Vault via AppRole instead of living in the chart.
  • EKS cluster access mapped from IAM to Kubernetes RBAC through aws-auth.
  • A written statement of work with a ten-week plan, cost breakdown and architecture, preserved alongside the delivery.

Lessons learned

  • ·Validate a service mesh against a disposable sample app before trusting it with a latency-sensitive workload, not after.
  • ·A secrets path (Vault AppRole) proven end to end for one credential is not the same as every credential having been migrated onto it. Ship the migration with the chart, not as a follow-up.
  • ·When infrastructure is the only lever because the application is licensed and closed, put every environment difference into chart values on purpose, so scaling a service is an edit, not a redeploy.
  • ·A leftover comment next to a hardcoded value (`#{{ .Values.x }}`) is a cheap signal that a template swap was started and never finished. Worth grepping for before calling a chart done.

Tech stack

Backend
Amazon EKSHelm (single chart, 18 templates)Istio service mesh + ingress gatewayNGINX ingressNATS message bus
Data & state
MongoDB (in-cluster workload)HashiCorp Vault (AppRole secrets)
Ops & quality
AWS IAM / aws-auth RBAC mappingPrivate container registry with imagePullSecretsKubernetes Deployments (Recreate strategy)