In the OpenShift world, Services take place on the OSI Layer 3 / IP, while Routing is an OSI Layer 7 / HTTP/TLS concept. Once you’ve wrapped your head around this backwards choice of naming, things are fairly easy:
An OpenShift Router is a component which listens on a physical host’s HTTP/S ports for incoming connections and proxies them into the OpenShift SDN. This allows clients who are NOT part of the OpenShift SDN (probably most of them) to access Services provided in OpenShift. The hostname of the HTTP request or the TLS Service Name Indication triggers certain forwarding rules which determine which Pod IP Addresses are targeted. Note that it does not address the service IP address, but uses the same information as the service to target the pods directly. Thus the selection logic behind a service is the single source of truth defining which pods are accessed.
Just like the kube-proxy and the SkyDNS service, the Router listens continuously for events which signify OpenShift configuration changes, and adapt the forwarding rules accordingly. The router itself is implemented as OpenShift pod and uses the “host port” concept that was already introduced in the plain docker networking to expose port 80/443 on the physical network. Note that this can be built upon to allow custom loadbalancing solutions, integrate with existing load balancers, etc.
This adds the additional flows (single node for simplicity again):
- From external client to OpenShift Pod: external client → network → OpenShift Node eth0 → (IPTables DNAT) → tun0 → ovs br0 → vethXXXX → Pod A eth0 → (userspace router) → Pod A eth0 → vethXXXX → ovs br0 → vethYYYY → Pod B eth0
But of course applies also to scenarios spanning multiple nodes: