Submariner is a tool built to connect overlay networks of different Kubernetes clusters. These clusters can be on different public clouds or on-premises. An important use case for Submariner is to connect disparate independent clusters into a ClusterSet.
However, by default, a limitation of Submariner is that it doesn’t handle overlapping CIDRs (ServiceCIDR and ClusterCIDR) across clusters. Each cluster must use distinct CIDRs that don’t conflict or overlap with any other cluster that is going to be part of the ClusterSet.
This is largely problematic because most actual deployments use the default CIDRs for a cluster so every cluster ends up using the same CIDRs. Changing CIDRs on existing clusters is a very disruptive process and requires a cluster restart. So Submariner needs a way to allow clusters with overlapping CIDRs to connect together.
To support overlapping CIDRs in connected clusters, Submariner has a component called Global Private Network, Globalnet (globalnet
). This
Globalnet is a virtual network specifically to support Submariner’s multi-cluster solution with a global CIDR. Each cluster is given a
subnet from this virtual Global Private Network, configured as new cluster parameter GlobalCIDR
(e.g. 242.0.0.0/8) which is
configurable at time of deployment. User can also manually specify GlobalCIDR for each cluster that is joined to the Broker using the flag
globalnet-cidr
passed to subctl join
command. If Globalnet is not enabled in the Broker or if a GlobalCIDR is preconfigured in
the cluster, the supplied Globalnet CIDR will be ignored.
By default, every cluster is assigned a configurable number of global IPs, represented by a ClusterGlobalEgressIP
resource, which are
used as egress IPs for cross-cluster communication. Multiple IPs are supported to avoid ephemeral port exhaustion issues. The default is 8.
The IPs are allocated from a configurable global CIDR.
Applications running on the host network that access remote clusters also use the cluster-level global egress IPs.
A user can assign a configurable number of global IPs per namespace by creating a GlobalEgressIP
resource. These IPs are also allocated
from the global CIDR and are used as egress IPs for all or selected pods in the namespace and take precedence over the cluster-level
global IPs. In addition, the global IPs allocated for a GlobalEgressIP
that targets specific pods in a namespace take precedence
over the global IPs allocated for a GlobalEgressIP
that just targets the namespace.
Exported ClusterIP
type services are automatically allocated a global IP from the global CIDR for ingress. For headless services, each
backing pod is allocated a global IP that is used for both ingress and egress. However, if a backing pod matches a GlobalEgressIP
then
its allocated IPs are used for egress.
Routing and iptable rules are configured to use the corresponding global IPs for ingress and egress. All address translations occur on the active Gateway node of the cluster.
submariner-globalnet
Submariner Globalnet is a component that provides cross-cluster connectivity from pods to remote services using their global IPs. Compiled as
binary submariner-globalnet
, it is responsible for maintaining a pool of global IPs, allocating IPs from the global IP pool to pods and
services, and configuring the required rules on the gateway node to provide cross-cluster connectivity using global IPs.
Globalnet also supports connectivity from the nodes (including pods that use host networking) to the global IP of remote services.
It mainly consists of two key components: the IP Address Manager and Globalnet.
The IP Address Manager (IPAM) component does the following:
GlobalCIDR
configured on cluster.This component is responsible for programming the routing entries, iptable rules and does the following:
GlobalEgressIP
, creates corresponding SNAT rules to convert the source IPs for all the matching pods to the corresponding
global IP(s) allocated to the GlobalEgressIP
object.externalIPs
, in the same namespace as
the exported Service, and sets the externalIPs
to the globalIP assigned to the respective Service.Pod
, Service
, or ServiceExport
.Connectivity is only part of the solution as pods still need to know the IPs of services on remote clusters.
This is achieved by enhancing Lighthouse with support for Globalnet. The Lighthouse
controller uses a service’s global IP when creating the ServiceImport
for services of type ClusterIP
. For headless services, backing
pod’s global IP is used when creating the EndpointSlice
resources to be distributed to other clusters. The Lighthouse
plugin then uses the global IPs when replying to DNS queries.
Nothing extra needs to be done to build submariner-globalnet
as it is built with the standard Submariner build.
Allow Globalnet controller to create/update/delete the Service
with externalIPs
by below steps:
Service
with externalIPs
:
Service
with externalIPs
only for users with permission to handle
the service/externalips
resource in the network.openshift.io
group.
By default, submariner-globalnet
's ServiceAccount
has such an RBAC rule.allowed-external-ip-cidrs
to
include the GlobalCIDR
allocated to the cluster and allowed-usernames
to include
system:serviceaccount:submariner-operator:submariner-globalnet
.The steps above are necessary because for every exported Service
, Submariner
Globalnet internally creates a Service
with externalIPs
and sets the externalIPs
to the globalIP assigned to the respective Service
.
Some deployments of Kubernetes do not allow the Service
with externalIPs
to be created
for security reasons.
Refer to the Quickstart Guides on how to deploy Submariner with Globalnet enabled. For most deployments users will not
need to do anything else once deployed. However, users can create GlobalEgressIP
s or edit the ClusterGlobalEgressIP
for specific
use cases.
By default, 8 cluster-scoped global IPs are allocated which allows for ~8x64k active ephemeral ports. If those are still
not enough for a cluster, this number can be increased by setting the NumberOfIPs
field in the ClusterGlobalEgressIP
with the
well-known name cluster-egress.submariner.io
:
apiVersion: submariner.io/v1
kind: ClusterGlobalEgressIP
metadata:
name: cluster-egress.submariner.io
spec:
numberOfIPs: 9
Only the ClusterGlobalEgressIP
resource with the name cluster-egress.submariner.io
is recognized by Globalnet. This resource is automatically
created with the default number of IPs.
If it’s desired for all pods in a namespace to use a unique global IP instead of one of the cluster-scoped IPs, a user can create a
GlobalEgressIP
resource in that namespace:
apiVersion: submariner.io/v1
kind: GlobalEgressIP
metadata:
name: ns-egressip
namespace: ns1
spec:
numberOfIPs: 1
The example above will allocate 1 global IP which will be used as egress IP for all pods in namespace ns1
.
NumberOfIPs
can have minimum value of 0
and maximum of 20
If it’s desired for a set of pods in a namespace to use unique global IP(s), a user can create a GlobalEgressIP
resource in that
namespace with the podSelector
field set:
apiVersion: submariner.io/v1
kind: GlobalEgressIP
metadata:
name: db-pods
namespace: ns1
spec:
podSelector:
matchLabels:
role: db
numberOfIPs: 1
The example above will allocate 1 global IP which will be used as egress IP for all pods matching label role=db
in namespace ns1
.