Skip to main content
Version: Developer

(RA-K2) Multi-Zone Kubernetes Control Plane with Distributed Session Planes Architecture Explained

RA-K1 answers the question "how do I run Kasm's control plane on Kubernetes?" It produces a working, coherent deployment with one control plane, one session plane, and one geography. RA-K2 answers a different question, and it is the same question RA4 asks: what happens when the users are not all in the same place?

The answer is the same one RA4 reaches. Control plane traffic must go to wherever the database is, because the App role issues synchronous blocking queries for every interaction. Session plane traffic must go to wherever the user is, because a pixel stream is felt in every keystroke. Those two requirements pull in opposite directions, and the only resolution is to stop treating them as one system.

What makes RA-K2 worth documenting separately is not that it reaches RA4's conclusion. It is that the Helm chart reaches it for you, and does not let you do otherwise. In RA4 an architect must understand why every zone's Web App belongs in the primary region and then choose to put it there. In RA-K2 the chart renders every zone's control plane into the cluster and offers no mechanism to place it anywhere else. The most surprising decision in RA4 is not a decision here. It is the shape of the tool.

That has a consequence worth stating up front: RA-K2 is easier to get structurally right than RA4, and easier to get nominally wrong. The topology is handed to you. DNS, however, is not, and DNS is a critical piece to implement this pattern.

note

This page documents Kasm Workspaces 1.19.0 and the Kasm Helm chart 1.1190.x. It builds directly on RA-K1. Read that page first.


Reference Architecture K2​

Kasm Workspaces RA-K2 multi-zone Kubernetes control plane and distributed session plane architecture diagram

Click the diagram to open it full size.


The Primary Load Balancer​

The Primary Load Balancer's role is unchanged from every other pattern in the series: a single controlled public entry point where TLS, WAF policy, DDoS mitigation, and traffic inspection apply uniformly before anything reaches a Kasm component. What changes in RA-K2 is what sits immediately behind it.

In RA-K1 the ingress path had one job: get traffic to kasm_proxy. In RA-K2 the ingress becomes a zone router. The chart renders one ingress host rule per zone, and the Host header on the request selects which zone's pods serve it:

Request hostRouted toServes
kasm.example.com (publicAddr){release}-proxy-{primary zone}Administrative UI, API, primary zone sessions
zone-a.kasm.example.com{release}-proxy-zoneaZone A, if given its own name
zone-b.kasm.example.com{release}-proxy-zonebZone B's control plane

Two constraints follow from this, and the chart enforces both:

Multi-zone requires an Ingress or an OpenShift Route. A Service of type LoadBalancer, the chart's single-zone default, cannot route by hostname, so it cannot select a zone. Setting kasmZones while leaving proxyService.type: LoadBalancer is not a supported configuration. proxyService.type must be ClusterIP, and either ingress.enabled or route.enabled must be true.

The TLS certificate must cover every zone hostname. One certificate secret serves all the ingress rules, so it needs publicAddr (kasm.example.com) plus every zone's proxy_hostname as SANs. A wildcard for *.kasm.example.com is the practical answer. An explicit SAN list works and has the advantage of being auditable, and the disadvantage of needing reissue when a zone is added, which, as covered below, is not something you can do anyway.


The Defining Characteristic: One Control Plane, Many Session Planes​

RA-K1 introduced two orchestrators separated by the cluster boundary. RA-K2 keeps that and adds a second axis: geography. The resulting rule is simple enough to state in one line, and every other property of the architecture follows from it.

Everything that talks to the database lives in the cluster. Everything that carries a pixel stream lives near the user.

Applied to the four Kasm service roles:

RoleWhere it runs in RA-K2Why
App (kasm_api, kasm_manager)In the cluster, one set per zoneSynchronous blocking database queries. Cross-region here would compound into multi-second control plane latency.
Dedicated Proxy (kasm_proxy)In the cluster per zone, and also on VMs in remote regionsThe in-cluster copy is the default path. The remote VM is the latency optimization that overrides it.
Connection Proxy (kasm_guac, RDP gateways)In the cluster for primary-region zones, and on VMs elsewhereIt should sit near the RDP, VNC, and SSH targets it proxies, which are regional.
AgentAlways on VMs, one pool per zoneUnchanged from RA-K1. Agents are never Kubernetes workloads.

The database is the fixed point the whole arrangement rotates around. One PostgreSQL instance serves every zone. It has no regional replica, no per-zone shard, and no local read path. Every authentication and every session provisioning decision for a user anywhere in the world is a query against it.


What the Chart Actually Renders Per Zone​

The prose documentation in Kubernetes Deployment Options says additional zones receive only the App role from the Helm chart. Reading the chart templates gives a more precise picture, and the difference matters when you are planning capacity and reading kubectl get deployments output.

For every zone in kasmZones, the chart renders:

ObjectName pattern
kasm_api Deployment{release}-api-{zone}
kasm_manager Deployment{release}-manager-{zone}
kasm_proxy Deployment{release}-proxy-{zone}
Ingress host rule and certificate SANThe zone's proxy_hostname

For primary-region zones only, the chart additionally renders:

ObjectName pattern
kasm_guac StatefulSet{release}-guac-{zone}
kasm_rdp_gateway Deployment{release}-rdp-gateway-{zone}
kasm_rdp_https_gateway StatefulSet{release}-rdp-https-gateway-{zone}

A zone is in the primary region when it is the primary zone, or when it declares the same non-empty region_name as the primary zone. If no zone sets region_name, only the primary zone is in the primary region.

This is the most useful undocumented-in-prose behavior in the pattern, because it gives kasmZones two distinct modes:

Zones within the primary region. Give several zones the same region_name as the primary and each receives a complete in-cluster stack: App, Dedicated Proxy, and Connection Proxy. No external proxy VMs are needed at all. This is the right shape when zones represent tenancy or security segmentation rather than geography: a contractor zone, a PCI-scoped zone, a zone with dedicated Agent capacity for a specific team. All of them sit in one data center. Only the Agent pools differ.

Zones in other regions. Omit region_name, or set a different one, and the zone gets App and Dedicated Proxy pods in the cluster but no Connection Proxy. Those must be provisioned as VMs in that region. This is the geographic mode, and it is the one RA-K2 is drawn around.

note

The in-cluster kasm_proxy-{zone} for a remote zone is not redundant with the external Dedicated Proxy. It is the fallback path. If you never set the zone's Proxy Hostname to a regional VM, container session traffic still works. It just routes back through the cluster, which is precisely the latency the architecture exists to avoid. The external Dedicated Proxy is optional in the sense that the deployment functions without it, not in the sense that it is optional for the pattern to make sense.


Identity and DNS: Four Names, Two Continents​

This is where RA-K2 deployments fail, and they fail quietly. The topology is handed to you by the chart. The naming is not, and two of the four names look almost identical while pointing at opposite sides of the world.

Kasm Workspaces RA-K2 DNS and name resolution diagram across two regions
NameSet inResolves toCarries
kasm.example.comHelm publicAddrRegion 1 Primary LB, to cluster ingressUI, API, auth, primary zone sessions
zone-b.kasm.example.comHelm kasmZones[].proxy_hostname, and the zone's Upstream Auth AddressRegion 1 cluster ingress, to kasm_proxy-zonebZone B's control plane and token validation
proxy.zone-b.kasm.example.comKasm UI: the zone's Proxy HostnameRegion 2 Dedicated Proxy VMsZone B's session stream
rdp.zone-b.kasm.example.comKasm UI: the zone's RDP HTTPS Proxy HostnameRegion 2 Connection Proxy VMsZone B's RDP, VNC, and SSH traffic

The two middle rows are the whole problem. zone-b.kasm.example.com is Zone B's control plane address and points at Region 1. proxy.zone-b.kasm.example.com is Zone B's session plane address and points at Region 2. They share a parent domain, they are both "the zone B address" in casual conversation, and they are eight thousand kilometers apart.

The failure modes are asymmetric in how obvious they are:

  • Upstream Auth Address pointed at the regional proxy produces a deployment that cannot validate tokens. It fails visibly and immediately, which is the good outcome.
  • Proxy Hostname left pointing at the cluster produces a deployment that works perfectly in every functional test and streams every Region 2 session across the ocean and back. Nobody notices in staging. Everyone notices in production, and the symptom, "Kasm is slow in London," points at everything except the actual cause.

Only the first two names are created by the chart's ingress. The last two are DNS records you create yourself, pointing at load balancers in front of VMs the chart knows nothing about.

tip

Both regional names must share a parent domain with the zone's proxy_hostname, because Kasm enforces origin rules against the configured Allow Origin Domain. Keeping everything under one parent domain and one wildcard certificate is not just convenient. It is the path of least resistance through the CORS and WebSocket origin checks.


Cross-Region Session Establishment​

The architecture's entire justification is a latency trade, and the trade is only visible in the sequence.

Kasm Workspaces RA-K2 cross-region session establishment sequence diagram

At connect time, a Region 2 user's request crosses the ocean several times: the login itself, the provisioning instruction from kasm_manager-zoneb out to the Region 2 Agent, the response carrying the session token, and then one final validation call from the Region 2 Dedicated Proxy back to zone-b.kasm.example.com in Region 1.

That last step is the one worth naming explicitly, because it is the only point where the session plane touches the control plane. The Dedicated Proxy accepts the browser's WebSocket connection and, before relaying anything, validates the session token against the zone's Upstream Auth Address. It happens once, at connection time, not continuously during the session. After it succeeds, the control plane leaves the data path entirely, and the stream runs between two endpoints that are both in Region 2.

The economics are straightforward. Roughly half a second of one-time setup, against a session that runs at local latency for the next eight hours. Inverting the placement, moving Zone B's control plane to Region 2, would buy a faster login and pay for it with every database query for every interaction crossing the Atlantic. The chart does not offer that option, and that is the correct default.


Zone Configuration: The Settings That Define a Zone​

The chart creates zones and their hostnames. Everything else about a zone's behavior is configured in the Kasm admin UI under Infrastructure → Deployment Zones. For a remote zone in RA-K2, these are the settings that matter:

SettingValue for a remote zoneConsequence if wrong
Upstream Auth AddressThe zone's proxy_hostname, for example zone-b.kasm.example.comToken validation fails. No session in the zone can connect.
Proxy HostnameThe regional Dedicated Proxy, for example proxy.zone-b.kasm.example.comSessions work but stream through the primary region
RDP HTTPS Proxy HostnameThe regional Connection Proxy, for example rdp.zone-b.kasm.example.comRDP and VNC traffic hairpins through Region 1
Allow Origin DomainThe shared parent domainWebSocket origin checks reject the session
Search Alternate ZonesSee below. A policy decision, not a default.Either an outage that should have been a degradation, or a boundary violation
Load Balance StrategyLeast Load unless you have a reasonUneven Agent utilization
LabelsZone-scoped labels for workspace targetingWorkspaces launch outside their intended zone

Search Alternate Zones deserves its own paragraph because it is the one setting where the correct value depends entirely on what a zone means in your deployment, and the two meanings are incompatible.

If zones represent geography, leave it enabled. A Region 2 capacity exhaustion then degrades to "London users get a session from Frankfurt with higher latency" rather than "London users get an error." Degradation beats failure.

If zones represent a compliance or tenancy boundary, a PCI-scoped segment, a classified enclave, a contractor population that must not share compute with staff, it must be disabled. When the alternative to a capacity error is a silent boundary violation, the capacity error is the correct behavior. This is the setting that turns a segmentation control into a suggestion, and it is enabled by default.


Zones Are an Install-Time Decision​

This is the hardest constraint in the pattern, and the one most likely to force a rebuild.

kasmZones feeds the chart's database preseed mechanism, which generates seed data consumed by the db-init Job. That job runs when dbManagement.initialize: true, that is, at first install against an empty database. The chart's own preseed documentation is explicit that rerunning preseed against an existing database is not supported, and the upstream Kasm documentation states plainly that Deployment Zones can only be created at Web App installation time.

The practical consequence: enumerate every zone you will need before the first helm install. Adding a zone later by appending to kasmZones and running helm upgrade renders the new Deployments, Services, and ingress rules, but the corresponding zone record reaches the database through a preseed path that no longer runs. That is not a documented upgrade route.

warning

Do not discover this in production. If you expect to add zones later, validate the exact upgrade path in a throwaway deployment first, and treat "we will add the APAC zone next quarter" as a requirement to declare it now. An empty zone with no Agents costs three small Deployments and an ingress rule.

There is a corollary worth planning for: because the certificate must cover every zone hostname, and because zones are fixed at install, a wildcard certificate converts a future rebuild into a future configuration change. Use one.


Asymmetrical Failure Behavior​

Multi-zone changes the failure modes substantially.

Kasm Workspaces RA-K2 multi-zone failure domains and blast radius diagram
FailureRecovered byScope
Any control plane pod crashes, any zoneKubernetesNone. Invisible.
A Zone B Agent VM failsNobody, or an AutoScale providerOne zone, partial
Zone B Dedicated Proxy failsThe zone's session load balancer, if there are twoOne zone, reconnect
The WAN path from Region 2 to Region 1 degradesNobodyOne zone, new connections only
Complete Region 2 outageSearch Alternate Zones, if policy permitsOne zone, total. Others unaffected.
The cluster or Region 1 failsNobodyGlobal
PostgreSQL failsThe managed service, if externalGlobal

Two rows deserve comment.

The WAN path failure is RA-K2's signature failure mode, and it has no equivalent in any single-region pattern. When connectivity from Region 2 to Region 1 degrades, token validation fails, so new Zone B sessions cannot connect, while every stream already established keeps running perfectly, because those streams no longer need Region 1 at all. The symptom is "nobody can start a session but everyone already working is fine," which is a genuinely confusing thing to page on and points at nothing obvious. This path needs explicit synthetic monitoring from each remote region. No component-level health check will surface it.

The two global rows are unchanged from RA-K1. This is the honest summary of what multi-zone buys. It distributes the session plane, so a regional outage becomes regional. It does not distribute the control plane: every zone's kasm_api and kasm_manager are Deployments in the same cluster talking to the same database. Adding a third continent adds a third session plane and a third way to lose sessions locally. It does not add any resilience to the cluster or the database.

info

RA-K2 is a latency architecture, not a disaster recovery architecture. It is the correct answer to "our London users have a terrible experience" and the wrong answer to "we cannot tolerate losing the primary region." The latter requires a second cluster and a replicated database, with a failover story the chart's kasmZones mechanism does not address and does not claim to.


Capacity: Three Scaling Dimensions​

RA-K1 had two independent capacity curves. RA-K2 has three, and they are independent per zone, which means the real count is closer to 2N + 1.

Control plane capacity scales with deploymentSize and per-component replica overrides, and it now scales per zone: each zone has its own api, manager, and proxy Deployments. A zone with ten users and a zone with ten thousand both get whatever deploymentSize says unless you override them individually. At scale this is worth doing: components.<name>.replicas applies globally, so genuinely asymmetric zones need per-zone attention or deliberate over-provisioning.

Session capacity scales with Agent VMs, per zone, and does not cross zone boundaries unless Search Alternate Zones is enabled. Zone A having spare capacity does nothing for Zone B users by default.

Regional relay capacity is new in RA-K2: the Dedicated Proxy and Connection Proxy VMs in each remote region. These are lightweight. The Dedicated Proxy runs kasm_proxy and nothing else, with no database and no container runtime, which makes deploying them in pairs cheap and makes running a single one an unforced error.

The failure mode this invites is the same one as RA-K1, amplified. The cluster is instrumented and visible. The remote VMs are machines somebody built once, in another region, that nobody looks at. Every remote zone needs its own capacity plan and its own dashboards, with metrics tagged by zone. Zone-specific problems that are not zone-tagged present as intermittent global weirdness, and they are diagnosed slowly.


Ports and Protocols​

Defaults. Everything on 443 except the legacy protocols and direct RDP.

SourceDestinationPortPurpose
End user (any region)Primary LB, to cluster ingress443UI, API, authentication
End user (Region 2)Zone B Dedicated Proxy443Session stream, stays in region
End user (Region 2)Zone B Connection Proxy443RDP, VNC, and SSH stream, stays in region
kasm_api / kasm_manager pods (all zones)PostgreSQL5432All platform state
kasm_manager-{zone} podsThat zone's Agent VMs443Session provisioning. Crosses regions.
Agent VMs (any zone)That zone's proxy_hostname443Check-in and registration. Crosses regions.
Zone B Dedicated Proxyzone-b.kasm.example.com443Token validation. The one session-plane crossing.
Zone B Dedicated ProxyZone B Agent VMs443Session relay, in region
Zone B Connection ProxyZone B RDP, VNC, and SSH targets3389 / 5900 / 22Protocol translation, in region
Zone B Connection Proxyzone-b.kasm.example.com443Connection authorization and status

Three of these cross a region boundary, and all three are on 443 outbound from something the cluster's NetworkPolicy governs or something the remote region's firewall governs. Neither of those artifacts is visible from the other side. The cross-region rules are the ones that will be broken by a routine security review in one region by someone who cannot see what depends on them in the other.


What RA-K2 Reveals About Kasm's Design Philosophy​

The control plane is centralized on purpose, and the centralization is load-bearing. Kasm's control plane is stateless precisely so that it can be replicated freely, but only next to the database it depends on. RA-K2 makes the boundary of that freedom explicit: replicate as many api and manager pods as you like, for as many zones as you like, in one place.

Zones are a routing and policy construct, not an infrastructure construct. A zone is a name, a set of hostnames, a set of settings, and an affinity rule for session placement. It is not a copy of Kasm. Understanding this is what makes the "Zone B's control plane is in Region 1" arrangement stop feeling wrong.

The session plane is the only thing worth distributing. Everything Kasm does to serve a distributed user base, dedicated proxies, zone affinity, alternate zone search, per-zone Agent pools, is about moving the stream closer to the user while leaving the decisions where the data is. RA4 states this. RA-K2 ships it.


RA-K2 in the Deployment Progression​

RA-K1RA-K2RA4
Control plane locationOne cluster, one zoneOne cluster, N zonesPrimary region, multi-server
Control plane placement decisionNot applicableMade by the chartMade by the architect
Session planesOneN, one per zoneN, one per zone
Zone routingNot applicableIngress Host headerDNS and load balancers
Regional outageTotalRegionalRegional
Cluster or primary region outageTotalTotalTotal
Zones addable after installNot applicableNo — install-time onlyInstall-time only
Operational complexityModerateHighHighest

What RA-K2 lacks, and what each gap teaches:

What RA-K2 lacksWhat it teaches
Control plane redundancy across regionsThat distributing the session plane and distributing the platform are different projects, and only one of them is a Helm value
Any ability to add a zone after installThat in a preseeded, declarative deployment, some decisions are made once, and the planning must happen before the first install rather than during the first incident
Visibility into the remote regions it depends onThat the components an orchestrator cannot see are the ones that need explicit monitoring, and multi-zone multiplies them by the number of regions
A local fallback when the WAN degradesThat "the control plane leaves the data path" is a precise statement: it leaves after validation, and validation is a hard dependency for every new connection

RA-K2's value is that it takes the hardest structural decision in RA4, where each zone's control plane belongs, and removes it from the architect's hands. What it hands back is a naming problem, a planning problem, and a monitoring problem, all three of which are solvable with discipline and none of which the chart can solve for you.


Appendix A: Multi-Zone Values​

The essential shape, fully commented. Start from RA-K1's Appendix A. This file shows only what multi-zone changes or adds.

# ---------------------------------------------------------------------------
# RA-K2 — Kasm Helm values for a MULTI-ZONE deployment.
#
# One Kubernetes cluster in the primary region hosts every zone's control
# plane. Session compute lives in each zone's own region on external VMs.
#
# Chart: oci://registry-1.docker.io/kasmweb/kasm-helm
# Version: 1.1190.x (chart 1.1190.x == Kasm 1.19.0)
# ---------------------------------------------------------------------------

publicAddr: kasm.example.com

# ---------------------------------------------------------------------------
# Ingress — REQUIRED for multi-zone
#
# A Service of type LoadBalancer cannot route by hostname, so it cannot select
# a zone. Multi-zone needs hostname-based routing, which means an Ingress (or
# an OpenShift Route) fronting a ClusterIP proxy Service.
#
# The chart renders one ingress host rule per zone. The Host header on each
# request selects which zone's kasm_proxy pods serve it.
# ---------------------------------------------------------------------------
proxyService:
type: ClusterIP

ingress:
enabled: true
tls: true
ingressClassName: nginx
annotations:
{}
# Long-lived WebSockets carry the session stream. Most ingress controllers
# default to timeouts far shorter than a working day.
# nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
# nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"

# ---------------------------------------------------------------------------
# TLS
#
# ONE certificate secret serves every ingress rule, so it must cover
# publicAddr AND every zone's proxy_hostname.
#
# Use a wildcard. Zones cannot be added after install, but certificates outlive
# deployments, and a wildcard turns a future rebuild into a config change.
# ---------------------------------------------------------------------------
certificate:
secretName: kasm-wildcard-tls # CN/SAN: *.kasm.example.com, kasm.example.com
# certManager:
# enabled: true
# addWildCard: true
# issuerName: letsencrypt-prod
# issuerKind: ClusterIssuer

# ---------------------------------------------------------------------------
# Zones
#
# >>> DECLARE EVERY ZONE YOU WILL EVER NEED, BEFORE THE FIRST INSTALL. <<<
#
# kasmZones feeds the chart's database preseed, which is consumed by the
# db-init Job. That job runs only when dbManagement.initialize is true — i.e.
# on a fresh database. Rerunning preseed against an initialized database is not
# supported, and upstream Kasm states that Deployment Zones can only be created
# at Web App installation time.
#
# Appending a zone later and running helm upgrade renders the Deployments,
# Services and ingress rules, but the zone record reaches the database through
# a path that no longer runs. Validate that upgrade in a throwaway deployment
# before relying on it. An empty zone with no Agents costs three small
# Deployments and an ingress rule — declare it now.
#
# Fields:
# name zone name (alias: zone_name)
# proxy_hostname builds the ingress host rule, the certificate SAN, and the
# zone's seeded proxy_hostname (alias: proxyAddress — the
# name used in the Multi-Zone Proxies how-to guide)
# primary at most one zone may set this; otherwise the FIRST zone in
# the list is primary. publicAddr routes to the primary zone.
# region_name optional. Zones sharing the primary zone's non-empty
# region_name are "primary-region" zones.
#
# WHAT region_name CONTROLS
#
# Every zone gets, in-cluster:
# {release}-api-{zone} {release}-manager-{zone} {release}-proxy-{zone}
#
# PRIMARY-REGION zones additionally get, in-cluster:
# {release}-guac-{zone} {release}-rdp-gateway-{zone}
# {release}-rdp-https-gateway-{zone}
#
# Zones outside the primary region get NO Connection Proxy from the chart.
# If such a zone serves RDP/VNC/SSH, provision a Connection Proxy VM in that
# zone's region — see Appendix B.
#
# If no zone sets region_name, only the primary zone is in the primary region.
# ---------------------------------------------------------------------------
kasmZones:
# --- Primary zone. Full in-cluster stack. Agents on VMs in us-east. -------
- name: zonea
proxy_hostname: zone-a.kasm.example.com
region_name: us-east
primary: true

# --- Segmentation zone, SAME region as primary. --------------------------
# Shares region_name with the primary, so it also gets an in-cluster
# Connection Proxy. No remote VMs needed at all — only its own Agent pool.
# This is the right shape for tenancy or compliance separation rather than
# geography: a PCI-scoped zone, a contractor zone, dedicated team capacity.
- name: zonea-pci
proxy_hostname: zone-a-pci.kasm.example.com
region_name: us-east

# --- Geographic zone, DIFFERENT region. ----------------------------------
# Gets api + manager + proxy in-cluster (beside the database, by design),
# but no Connection Proxy. Its session plane is external:
# proxy.zone-b.kasm.example.com -> Dedicated Proxy VMs (eu-west)
# rdp.zone-b.kasm.example.com -> Connection Proxy VMs (eu-west)
# Those two names are DNS records you create; the chart knows nothing of them.
- name: zoneb
proxy_hostname: zone-b.kasm.example.com
region_name: eu-west

# ---------------------------------------------------------------------------
# Database — one instance, shared by every zone.
#
# Multi-zone raises the stakes here rather than lowering them: more users, more
# regions, and no local fallback anywhere. Use a managed service with automatic
# failover, in the primary region, beside the cluster.
# ---------------------------------------------------------------------------
database:
standalone: true
hostname: kasm-db.us-east.example.internal
port: 5432
kasmDbName: kasm
kasmDbUser: kasmapp
# kasmDbSecret:
# name: kasm-db-credentials
# key: password

dbManagement:
initialize: true # true ONLY for the very first install
upgrade:
enable: false # true deliberately, for ONE upgrade, on a schema change

# ---------------------------------------------------------------------------
# Sizing
#
# deploymentSize applies to EVERY zone's components equally. A ten-user zone
# and a ten-thousand-user zone both get the same replica count unless you
# override individually. Note that components.<name>.replicas is global too —
# genuinely asymmetric zones need either deliberate over-provisioning or
# per-zone attention after install.
# ---------------------------------------------------------------------------
deploymentSize: medium

useImageTags: "1.19.0-rolling"

components:
api:
image:
tag: 1.19.0-rolling-20260215
manager:
image:
tag: 1.19.0-rolling-20260215
proxy:
image:
tag: 1.19.0-rolling-20260215
guac:
image:
tag: 1.19.0-rolling-20260215
rdpGateway:
image:
tag: 1.19.0-rolling-20260215
rdpHttpsGateway:
image:
tag: 1.19.0-rolling-20260215

imagePullPolicy: Always
applySecurity: true
applyHealthChecks: true

# Spread replicas across nodes, or replica count buys no node-failure tolerance.
affinity:
{}
# podAntiAffinity:
# preferredDuringSchedulingIgnoredDuringExecution:
# - weight: 100
# podAffinityTerm:
# topologyKey: kubernetes.io/hostname
# labelSelector:
# matchExpressions:
# - key: app.kubernetes.io/instance
# operator: In
# values: [kasm]

Appendix B: Remote Zone Bootstrap​

A remote zone's session plane needs up to three roles installed on VMs in that region: a Dedicated Proxy, a Connection Proxy if the zone serves RDP, VNC, or SSH, and at least one Agent.

Provisioning the Dedicated Proxy and Connection Proxy, including the zone-specific flag values, the DNS hostname pattern, and the Kasm UI settings to configure afterward, is covered step by step in Multi-Zone Proxies with Kubernetes. Those steps apply unchanged here: --api-hostname is still the zone's proxy_hostname, which still means the primary-region cluster ingress, not the regional VM being installed.

Installing the Agent role follows the same --role agent procedure as Multi-Server Installation, with one RA-K2-specific detail those generic steps do not cover: --manager-hostname must be the zone's proxy_hostname (for example zone-b.kasm.example.com), not publicAddr. Pointing it at publicAddr instead silently registers the Agent to the primary zone, where it works correctly and serves the wrong region's users. After install, enable the Agent under Admin → Infrastructure → Docker Agents, and confirm it landed in the intended zone from the Zone column before moving on.

Whichever role you provision, verify the WAN path to the zone's proxy_hostname before installing anything else. A broken path discovered after install looks like a dozen unrelated problems, and it is the one dependency every role here shares.

Appendix C: Readiness Checklist​

Everything in RA-K1's checklist, plus:

  • Every zone the deployment will ever need is declared in kasmZones before the first install
  • proxyService.type: ClusterIP with ingress.enabled: true (or an OpenShift Route)
  • Wildcard certificate covering publicAddr and every zone proxy_hostname
  • region_name set deliberately on every zone. It decides which zones get an in-cluster Connection Proxy.
  • For each remote zone, all four names resolve correctly and to different places: zone-X.* resolves to the cluster ingress, while proxy.zone-X.* and rdp.zone-X.* resolve to regional VMs
  • Zone settings verified in the UI per zone: Upstream Auth Address, Proxy Hostname, RDP HTTPS Proxy Hostname, Allow Origin Domain
  • Search Alternate Zones set deliberately per zone: enabled for latency zones, disabled for compliance zones
  • Two Dedicated Proxies per remote zone, and two Connection Proxies if the zone serves RDP or VNC
  • Pod egress to each remote region's Agents on 443 verified from a pod
  • Each remote region's Agents verified able to reach their zone hostname on 443
  • Synthetic monitoring of the token-validation path from each remote region to the cluster. The WAN failure mode is invisible to component health checks.
  • Observability tagged by zone, with per-zone dashboards and alerts
  • Workspace images pre-pulled on every zone's Agents. Staggered image cache state causes zone-specific launch failures.
  • Per-zone configuration documented and version-controlled

References​


This article is part of the Kasm Workspaces Reference Architecture Explanation Series.