Skip to content

Send traffic to the arm64 pods from one Service - #241

Merged
koikonom merged 1 commit into
lago-v2from
arm64_shared_service
Sep 1, 2026
Merged

Send traffic to the arm64 pods from one Service#241
koikonom merged 1 commit into
lago-v2from
arm64_shared_service

Conversation

@koikonom

@koikonom koikonom commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

Follow-up to #240.

The problem

#240 gave the arm64 variant its own app.kubernetes.io/name, for example
lago-api-arm64, so the chart rendered a second Service for it. The HTTPRoute
backs lago-rails.fullname, which is the amd64 Service, so the arm64 pods were
never a target of the load balancer.

On lago-dev-us-1 the arm64 API pod is Ready and answers /ready with 200, but
its only endpoint is the unused main-lago-api-arm64 Service. Its logs hold
kubelet probes and nothing else.

The change

Every pod template now carries app.kubernetes.io/component, which holds the
workload name (lago-api) and is the same for all architectures. The Service
and the PodDisruptionBudget select it when arm64 is enabled:

global.architectures.arm64.enabled Service and PDB selector
false {name, instance} — no change from today
true {instance, component} — matches the pods of both architectures

Deployment selectors keep a name for each architecture, so each one matches only
its own pods:

Object Selector
Deployment lago-api name=lago-api, instance=lago
Deployment lago-api-arm64 name=lago-api-arm64, instance=lago

Traffic distribution stays with the NLB and the gateway. Because one Service
holds the pods of both architectures, the share of each follows the endpoint
count, so it tracks the replica count of each Deployment with no weights to
maintain.

No workload is recreated

spec.selector of a Deployment is immutable. No Deployment selector changes
here, so nothing has to be deleted, in any environment, including the arm64
Deployments that lago-dev-us-1 already runs.

Each Deployment matches only its own pods, so an HPA collects the metrics of one
architecture. This matters: the lago-api HPA in both production clusters
scales on Resource:cpu and Resource:memory.

Order of the rollout

Bump the chart first. Enable arm64 in a later sync.

The label is added whether arm64 is on or off, so by the time an environment
enables arm64, its amd64 pods already carry the label and the selector finds
them at once. In one sync the amd64 pods would still roll to get the label while
the selector had already moved, which empties the endpoint list for the length
of the rollout.

Verification

Rendered against the real values of lago-staging-eu-1 — the five value files
from lago-infrastructure and lago-deploy at origin/main, and the inline
valuesObject of the Argo app. Compared with the published 0.13.0 chart, the
complete diff is one label on 14 Deployments:

+        app.kubernetes.io/component: lago-api
+        app.kubernetes.io/component: lago-worker
+        app.kubernetes.io/component: lago-clock
   ... 11 more

46 objects before, 46 after. No Service selector change, no PDB selector change,
and no arm64 object, because staging does not enable arm64.

With arm64 enabled, the Service and the PDB move to {instance, component} and
both Deployments keep their own name selector.

task test:unit gives 200 passed and 0 failed over 10 charts. task lint
passes.

Note for a local render

helm dependency build in this repository vendors a nested lago-config in
lago-rails, which the published charts do not have. A local helm template
then stops with global.database.uri value is required. Render the published
chart, or give the values of the secret.

🤖 Generated with Claude Code

@koikonom
koikonom force-pushed the arm64_shared_service branch from 7c08ce8 to 68e0d05 Compare September 1, 2026 08:15
@koikonom
koikonom marked this pull request as draft September 1, 2026 08:40
@koikonom

koikonom commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator Author

Don't review yet. I want to figure out a clean migration path that does not involve deleting deployments (hence causing downtime).

The arm64 variant has its own `app.kubernetes.io/name`, so the chart made
a second Service for it. The HTTPRoute backs only the amd64 Service, so
the arm64 pods never received traffic.

Every pod template now carries `app.kubernetes.io/component`, which holds
the workload name and is the same for all architectures. When arm64 is
enabled, the Service and the PodDisruptionBudget select that label, so
one Service reaches the pods of both architectures and the load balancer
sends traffic to both. When arm64 is off, the selector does not change.

No Deployment selector changes, so no workload is recreated. The label is
added before it is selected, so an environment that enables arm64 later
gets no interval without endpoints.

Bump the chart first, then enable arm64. In one sync the amd64 pods would
still roll to get the label while the selector already moved.
@koikonom
koikonom force-pushed the arm64_shared_service branch from 68e0d05 to 3e493e1 Compare September 1, 2026 09:39
@koikonom koikonom changed the title Put both architectures in one Service Send traffic to the arm64 pods from one Service Sep 1, 2026
@koikonom
koikonom marked this pull request as ready for review September 1, 2026 11:18
@koikonom
koikonom merged commit 271b675 into lago-v2 Sep 1, 2026
3 checks passed
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.

2 participants