Mux And Channel Services
A channel Service is a normal Kubernetes Service with type: LoadBalancer,
but its spec.loadBalancerClass points at a mux instead of a cloud-provider
load balancer controller.
This page explains how channel ports map to mux ports and backend ports.
Required Shape
Section titled “Required Shape”apiVersion: v1kind: Servicemetadata: name: app-http namespace: appspec: type: LoadBalancer loadBalancerClass: svc-mux.nowake.ai/mux.svc-mux allocateLoadBalancerNodePorts: false selector: app: app-http ports: - name: http protocol: TCP port: 8080 targetPort: httpRules:
spec.loadBalancerClassis<api-prefix>/<mux>[.<namespace>].- Every channel port must have a stable
name. - The port name is the identity used by annotations and generated mux port names.
allocateLoadBalancerNodePorts: falseis the normal channel setting. The mux Service owns provider-facing load balancer plumbing.- Each
(mux public port, protocol)pair can be claimed by only one channel on a mux.
Port Meaning
Section titled “Port Meaning”For this Service port:
ports: - name: http protocol: TCP port: 8080 targetPort: httpThe meanings are:
| Field | Meaning |
|---|---|
name | Stable channel port identity. Required. |
port | Channel Service port. By default, also the mux public port. |
targetPort | Backend pod port or named container port. |
protocol | Mux and backend protocol. Defaults to TCP if omitted. |
Default mapping:
channel spec.ports[].port == mux public portchannel spec.ports[].targetPort == backend pod portExample:
ports: - name: p2p port: 30303 targetPort: p2pThe mux exposes 30303/TCP, and the generated mux Endpoints route to the pod
port resolved from targetPort: p2p.
Override The Mux Public Port
Section titled “Override The Mux Public Port”Use <api-prefix>/external-ports only when the mux public port should differ
from the channel Service port.
metadata: annotations: svc-mux.nowake.ai/external-ports: "http:30080"spec: ports: - name: http port: 8080 targetPort: httpMapping:
channel Service port: 8080mux public port: 30080backend targetPort: httpThe controller writes a readable annotation:
svc-mux.nowake.ai/ports: http:8080->30080Use explicit overrides for compatibility with an existing public port, a provider port plan, or a migration where internal Service ports should remain unchanged.
Automatic Port Allocation
Section titled “Automatic Port Allocation”Use name:auto when you want the controller to allocate a mux public port from
the mux range.
Mux annotation or chart value:
defaultLoadBalancer: portRange: "20000-20099"Channel annotation:
metadata: annotations: svc-mux.nowake.ai/external-ports: "http:auto"spec: ports: - name: http port: 8080 targetPort: httpThe assignment is stored in the per-mux state ConfigMap, so the selected port remains stable across controller restarts and repeated GitOps applies. Static and explicit port claims are stored there as well, which prevents newly added channels from stealing an existing port after a restart.
Do not reuse one state ConfigMap for multiple muxes.
Multiple Ports
Section titled “Multiple Ports”A channel can expose multiple named ports:
metadata: annotations: svc-mux.nowake.ai/external-ports: "http:30080,grpc:auto"spec: ports: - name: http port: 8080 targetPort: http - name: grpc port: 9090 targetPort: grpcEvery name referenced in external-ports must exist in spec.ports.
Unreferenced ports use their own spec.ports[].port as the mux public port.
Common Mistakes
Section titled “Common Mistakes”- Missing port names. The controller rejects unnamed channel ports.
- Treating
targetPortas the mux public port. It is the backend pod port. - Keeping
external-portsafter changingspec.ports[].portto the desired public port. The annotation is an override, so it should be absent unless an override is intentional. - Reusing the same public port and protocol across two channels on one mux.
- Managing controller-owned
svc-mux.nowake.ai/portsin Git. This annotation is generated by the controller.