Skip to main content
Version: Next 🚧

Network Topology

This document describes the network architecture managed by TFRS Operator, including traffic ingress, routing mechanisms, mTLS, and tenant isolation.

Traffic Ingress Chain​

External requests traverse the following chain to reach backend services:

Client
│
â–ŧ
Cloud LB (CLB / NodePort) ← Determined by TFRCluster.spec.clusterType
│
â–ŧ
Istio Ingress Gateway (Port 80) ← istio-ingress namespace
│
â–ŧ
Gateway CR (default-gateway) ← Cluster-wide shared gateway
│
â–ŧ
VirtualService (cluster-routes) ← Unified routing entry point
│
â–ŧ
EnvoyFilter (Cookie/QP → Header) ← Extract tenant identifiers
│
â–ŧ
EnvoyFilter (Lua Dynamic Routing) ← Dynamic routing to target service
│
â–ŧ
Backend Service ← Service in tenant namespace

Gateway Architecture​

TFRCluster creates a shared Istio Gateway through which all tenant traffic enters the cluster.

ConfigurationDefault ValueDescription
Gateway Namedefault-gatewayOverridable via spec.ingress.gatewayRef
Gateway Namespaceistio-ingressIstio Ingress Gateway namespace
Listen Port80 (HTTP)TLS terminated by upstream CLB
Hosts["*"]Restrictable via spec.ingress.hosts

Cluster Type Adaptation​

Cluster TypeIngress MethodSpecial Configuration
tkeCLB (LoadBalancer)Binds Tencent Cloud CLB via tkeClusterConfig.clbId
kindNodePortUses nodePortConfig for HTTP/HTTPS port mappings
docker-desktopNodePortSame as Kind, adapted for Docker Desktop networking

TFRCluster deploys two EnvoyFilters to implement dynamic routing based on cookies and query parameters.

Extracts tenant identifiers from request cookies or URL query parameters and converts them to HTTP headers:

Cookie Source:

Cookie NameMapped HeaderDefault Cookie KeyDescription
tfNamespaceX-TF-NamespaceConfigurable via spec.routing.cookieNamesTarget tenant namespace
tfRobotIdX-TF-RobotIdConfigurable via spec.routing.cookieNamesTarget robot instance ID

QueryParam Source:

QueryParamMapped HeaderDescription
namespaceX-TF-NamespaceTarget tenant namespace
ridX-TF-RobotIdTarget robot instance ID

Priority: When both cookie and query parameter are present, the query parameter takes precedence. For example, /v1/login?namespace=tenant-a&rid=robot-1 overrides the corresponding cookie values.

Step 2: Lua Dynamic Routing (EnvoyFilter lua-dynamic-routing)​

Dynamically selects backend services based on request path and headers:

Request PathRequired HeadersRouting Target
/v1/loginX-TF-Namespacetfrobot-http.{namespace}:80 (regardless of rid)
/socket.io/X-TF-Namespace + X-TF-RobotIdtf-robot-{robotId}.{namespace}:8080
/socket.io/ (missing rid)X-TF-NamespaceReturns 400 JSON error response
Other pathsX-TF-Namespacetfrobot-http.{namespace}:80
Missing routing info—Returns 401 JSON error response

VirtualService Header Processing​

The cluster-level VirtualService cluster-routes also performs the following:

  • X-Real-IP injection: Writes the client's real IP into the X-Real-IP header
  • X-Forwarded-Host injection: Preserves the original request Host
  • Underscore header support: Allows header names containing underscores via Istio mesh config

Tenant Network Isolation​

Each TFRTenant namespace achieves network isolation through the following Istio policies:

PeerAuthentication (mTLS)​

apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
name: default
namespace: {tenant-namespace}
spec:
mtls:
mode: STRICT

All service communication within the namespace is forced to use mTLS, preventing unencrypted traffic.

AuthorizationPolicy​

Restricts traffic to the tenant namespace to only the following sources:

SourceDescription
istio-ingressExternal traffic forwarded by the Ingress Gateway
Same namespaceIntra-namespace service communication
spec.extraAllowedNamespacesAdditional allowed namespaces (e.g., Prometheus namespace)

DestinationRule​

Configures client-side mTLS mode to ensure all inter-service communication within the namespace is encrypted:

apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: default
namespace: {tenant-namespace}
spec:
host: "*.{tenant-namespace}.svc.cluster.local"
trafficPolicy:
tls:
mode: ISTIO_MUTUAL

Service DNS Patterns​

Key services within tenant namespaces follow these DNS naming patterns:

ServiceDNS PatternPortDescription
TFRobot APItfrobot-http.{ns}.svc.cluster.local80Unified API service entry
TFRobot Instancetf-robot-{robotId}.{ns}.svc.cluster.local8080Individual robot instance (Socket.IO)
PostgreSQL{ns}-pg-rw.{ns}.svc.cluster.local5432CNPG read-write endpoint
Redisredis.{ns}.svc.cluster.local6379Redis cache
MinIOminio.{ns}.svc.cluster.local9000Object storage API
RabbitMQrabbitmq.{ns}.svc.cluster.local5672AMQP message queue
Jaegerjaeger-collector.{ns}.svc.cluster.local4317OTLP gRPC endpoint
Grafanagrafana.{ns}.svc.cluster.local3000Monitoring dashboard

Network Topology Overview​

graph TB
subgraph External
Client[Client]
CLB[Cloud LB]
end

subgraph istio-ingress
IGW[Istio Ingress Gateway]
GW[Gateway CR]
VS[VirtualService]
EFC[EnvoyFilter Cookie]
EFL[EnvoyFilter Lua]
end

subgraph tenant-ns-1[Tenant Namespace A]
PA1[PeerAuthentication STRICT]
AP1[AuthorizationPolicy]
API1[TFRobot API :80]
BOT1[tf-robot-1 :8080]
PG1[PostgreSQL :5432]
RD1[Redis :6379]
MN1[MinIO :9000]
RQ1[RabbitMQ :5672]
end

subgraph tenant-ns-2[Tenant Namespace B]
PA2[PeerAuthentication STRICT]
AP2[AuthorizationPolicy]
API2[TFRobot API :80]
BOT2[tf-robot-2 :8080]
PG2[PostgreSQL :5432]
end

Client --> CLB --> IGW
IGW --> GW --> VS
VS --> EFC --> EFL
EFL -->|X-TF-Namespace=A| API1
EFL -->|X-TF-Namespace=A, X-TF-RobotId=1| BOT1
EFL -->|X-TF-Namespace=B| API2

API1 -.->|mTLS| PG1
API1 -.->|mTLS| RD1
API1 -.->|mTLS| MN1
API1 -.->|mTLS| RQ1