Service-Reflector mirrors Kubernetes Services so that Pods running in one cluster can natively access Services from another cluster.
A key use for multi-cluster Kubernetes is to allow Pods and Services in one cluster to access those running in another cluster. However, a Pod in cluster A has no Kubernetes-native way of discovering a Service in cluster B or determining its endpoints; instead it must be pointed explicitly at the Service's ClusterIP. One solution to this issue is for an administrator to create a Service in cluster A to mirror the one in cluster B with Endpoints that point at the Service’s Pods. Service-Reflector automates the mirroring of selected Services from one cluster to another to simplify running multi-cluster Kubernetes.
Service-Reflector is comprised of two components: a Reflector and an Emitter.
Both components are run by default, though either can be run independently or disabled, via the --reflector
and --emitter
flags.
The Reflector is a controller that watches source APIs for Services to reflect and creates mirror Services and Endpoints in the host cluster. One Reflector can watch many sources for Services, allowing a cluster to access Services from many different clusters. The source APIs can be any Kubernetes-style API that allows listing and watching Services and Endpoints, for example:
- a Kubernetes apiserver, specified with the
--reflector.source-kubeconfig
flag; or - an Emitter, specified with the
--reflector.source-api
flag.
In order allow a Reflector in cluster A to find Services in cluster B, we must point the Reflector at a source API, namely cluster B's Kubernetes apiserver.
Doing so requires configuring the Reflector with a Kubeconfig or ServiceAccount token from cluster B.
To simplify deployment, Service-Reflector provides an Emitter, a Kubernetes-style apiserver that implements only the list and watch verbs for Services and Endpoints.
The only details a Reflector needs to access an Emitter's API is the Emitter's URL.
Furthermore, the Emitter allows an administrator to specify a selector to limit which Services are exposed to the Reflector; this is done via the --emitter.selector
flag.
Start by connecting two or more Kubernetes clusters with the desired multi-cluster solution, e.g. Kilo. The Service CIDR and Pod CIDR of each cluster must be routable from the others.
Service-Reflector can be installed on any Kubernetes cluster by deploying a Deployment:
kubectl apply -f https://raw.githubusercontent.com/squat/service-reflector/master/manifests/service-reflector.yaml
In order for the Reflector to find Services to mirror, it must be configured with a source API. The following snippet could be used to configure Service-Reflectors in two clusters:
# Register the emitter in cluster1 as a source of the reflector in cluster2.
cat <<EOF | kubectl --kubeconfig $KUBECONFIG2 apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
name: service-reflector
data:
source-api: http://$(kubectl --kubeconfig $KUBECONFIG1 get service service-reflector -o jsonpath='{.spec.clusterIP}'):8080
EOF
# Restart the reflector.
kubectl --kubeconfig $KUBECONFIG2 delete pod --selector app.kubernetes.io/name=service-reflector
# Register the emitter in cluster2 as a source of the reflector in cluster1.
cat <<EOF | kubectl --kubeconfig $KUBECONFIG1 apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
name: service-reflector
data:
source-api: http://$(kubectl --kubeconfig $KUBECONFIG2 get service service-reflector -o jsonpath='{.spec.clusterIP}'):8080
EOF
# Restart the reflector.
kubectl --kubeconfig $KUBECONFIG1 delete pod --selector app.kubernetes.io/name=service-reflector