Join us Sept 17 at .local NYC! Use code WEB50 to save 50% on tickets. Learn more >
MongoDB Event
Docs Menu
Docs Home
/
MongoDB Controllers for Kubernetes Operator
/ /

Istio Service Mesh

While it is possible to deploy Multi-Cluster Ops Manager, Multi-Cluster Sharded Cluster, and Multi-Cluster Replica Set configurations without a service mesh, the recommended approach (presented here) is to leverage a service mesh to handle the networking across multiple Kubernetes clusters. To learn more, see How Does the Kubernetes Operator Establish Connectivity.

This page walks you through the process of deploying and validating an Istio service mesh across multiple Kubernetes clusters. Istio is only one of many options for deploying a service mesh, and it is not supported by MongoDB.

Note

Istio is not supported by MongoDB

Istio is not supported by MongoDB and is only one of many tools you can use to deploy a service mesh across your Kubernetes clusters.

Before you begin, perform the following tasks:

  • Install kubectl.

  • Set the K8S_CLUSTER_*_CONTEXT_NAME environment variables as explained in the GKE Clusters guide.

You can find all included source code in the MongoDB Kubernetes Operator repository.

1

Run the following command to clone the repository.

git clone https://github.com/mongodb/mongodb-kubernetes.git
cd mongodb-kubernetes
git checkout 1.2.0
cd public/architectures
2

Install Istio service mesh to allow cross-cluster DNS resolution and network connectivity between Kubernetes clusters.

1CTX_CLUSTER1=${K8S_CLUSTER_0_CONTEXT_NAME} \
2CTX_CLUSTER2=${K8S_CLUSTER_1_CONTEXT_NAME} \
3CTX_CLUSTER3=${K8S_CLUSTER_2_CONTEXT_NAME} \
4ISTIO_VERSION="1.20.2" \
5./install_istio_separate_network.sh
3

Label the Kubernetes namespaces in each cluster to enable Istio sidecar injection.

kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" label namespace "${OPERATOR_NAMESPACE}" istio-injection=enabled --overwrite
kubectl --context "${K8S_CLUSTER_1_CONTEXT_NAME}" label namespace "${OPERATOR_NAMESPACE}" istio-injection=enabled --overwrite
kubectl --context "${K8S_CLUSTER_2_CONTEXT_NAME}" label namespace "${OPERATOR_NAMESPACE}" istio-injection=enabled --overwrite
kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" label namespace "${OM_NAMESPACE}" istio-injection=enabled --overwrite
kubectl --context "${K8S_CLUSTER_1_CONTEXT_NAME}" label namespace "${OM_NAMESPACE}" istio-injection=enabled --overwrite
kubectl --context "${K8S_CLUSTER_2_CONTEXT_NAME}" label namespace "${OM_NAMESPACE}" istio-injection=enabled --overwrite
kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" label namespace "${MDB_NAMESPACE}" istio-injection=enabled --overwrite
kubectl --context "${K8S_CLUSTER_1_CONTEXT_NAME}" label namespace "${MDB_NAMESPACE}" istio-injection=enabled --overwrite
kubectl --context "${K8S_CLUSTER_2_CONTEXT_NAME}" label namespace "${MDB_NAMESPACE}" istio-injection=enabled --overwrite
4

The following optional scripts verify whether the service mesh is configured correctly for cross-cluster DNS resolution and connectivity.

  1. Create a Kubernetes namespace for the connectivity test.

    1kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" create namespace "connectivity-test"
    2kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" label namespace "connectivity-test" istio-injection=enabled --overwrite
    3
    4kubectl --context "${K8S_CLUSTER_1_CONTEXT_NAME}" create namespace "connectivity-test"
    5kubectl --context "${K8S_CLUSTER_1_CONTEXT_NAME}" label namespace "connectivity-test" istio-injection=enabled --overwrite
    6
    7kubectl --context "${K8S_CLUSTER_2_CONTEXT_NAME}" create namespace "connectivity-test"
    8kubectl --context "${K8S_CLUSTER_2_CONTEXT_NAME}" label namespace "connectivity-test" istio-injection=enabled --overwrite
  2. Run this script on cluster 0:

    1kubectl apply --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "connectivity-test" -f - <<EOF
    2 apiVersion: apps/v1
    3 kind: StatefulSet
    4 metadata:
    5 name: echoserver0
    6 spec:
    7 replicas: 1
    8 selector:
    9 matchLabels:
    10 app: echoserver0
    11 template:
    12 metadata:
    13 labels:
    14 app: echoserver0
    15 spec:
    16 containers:
    17 - image: k8s.gcr.io/echoserver:1.10
    18 imagePullPolicy: Always
    19 name: echoserver0
    20 ports:
    21 - containerPort: 8080
    22EOF
  3. Run this script on cluster 1:

    1kubectl apply --context "${K8S_CLUSTER_1_CONTEXT_NAME}" -n "connectivity-test" -f - <<EOF
    2 apiVersion: apps/v1
    3 kind: StatefulSet
    4 metadata:
    5 name: echoserver1
    6 spec:
    7 replicas: 1
    8 selector:
    9 matchLabels:
    10 app: echoserver1
    11 template:
    12 metadata:
    13 labels:
    14 app: echoserver1
    15 spec:
    16 containers:
    17 - image: k8s.gcr.io/echoserver:1.10
    18 imagePullPolicy: Always
    19 name: echoserver1
    20 ports:
    21 - containerPort: 8080
    22EOF
  4. Run this script on cluster 2:

    1kubectl apply --context "${K8S_CLUSTER_2_CONTEXT_NAME}" -n "connectivity-test" -f - <<EOF
    2 apiVersion: apps/v1
    3 kind: StatefulSet
    4 metadata:
    5 name: echoserver2
    6 spec:
    7 replicas: 1
    8 selector:
    9 matchLabels:
    10 app: echoserver2
    11 template:
    12 metadata:
    13 labels:
    14 app: echoserver2
    15 spec:
    16 containers:
    17 - image: k8s.gcr.io/echoserver:1.10
    18 imagePullPolicy: Always
    19 name: echoserver2
    20 ports:
    21 - containerPort: 8080
    22EOF
  5. Run this script to wait for the creation of StatefulSets:

    1kubectl wait --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "connectivity-test" --for=condition=ready pod -l statefulset.kubernetes.io/pod-name=echoserver0-0 --timeout=60s
    2kubectl wait --context "${K8S_CLUSTER_1_CONTEXT_NAME}" -n "connectivity-test" --for=condition=ready pod -l statefulset.kubernetes.io/pod-name=echoserver1-0 --timeout=60s
    3kubectl wait --context "${K8S_CLUSTER_2_CONTEXT_NAME}" -n "connectivity-test" --for=condition=ready pod -l statefulset.kubernetes.io/pod-name=echoserver2-0 --timeout=60s
  6. Create Pod service on cluster 0:

    1kubectl apply --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "connectivity-test" -f - <<EOF
    2apiVersion: v1
    3kind: Service
    4metadata:
    5 name: echoserver0-0
    6spec:
    7 ports:
    8 - port: 8080
    9 targetPort: 8080
    10 protocol: TCP
    11 selector:
    12 statefulset.kubernetes.io/pod-name: "echoserver0-0"
    13EOF
  7. Create Pod service on cluster 1:

    1kubectl apply --context "${K8S_CLUSTER_1_CONTEXT_NAME}" -n "connectivity-test" -f - <<EOF
    2apiVersion: v1
    3kind: Service
    4metadata:
    5 name: echoserver1-0
    6spec:
    7 ports:
    8 - port: 8080
    9 targetPort: 8080
    10 protocol: TCP
    11 selector:
    12 statefulset.kubernetes.io/pod-name: "echoserver1-0"
    13EOF
  8. Create Pod service on cluster 2:

    1kubectl apply --context "${K8S_CLUSTER_2_CONTEXT_NAME}" -n "connectivity-test" -f - <<EOF
    2apiVersion: v1
    3kind: Service
    4metadata:
    5 name: echoserver2-0
    6spec:
    7 ports:
    8 - port: 8080
    9 targetPort: 8080
    10 protocol: TCP
    11 selector:
    12 statefulset.kubernetes.io/pod-name: "echoserver2-0"
    13EOF
  9. Create round robin service on cluster 0:

    1kubectl apply --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "connectivity-test" -f - <<EOF
    2apiVersion: v1
    3kind: Service
    4metadata:
    5 name: echoserver
    6spec:
    7 ports:
    8 - port: 8080
    9 targetPort: 8080
    10 protocol: TCP
    11 selector:
    12 app: echoserver0
    13EOF
  10. Create round robin service on cluster 1:

    1kubectl apply --context "${K8S_CLUSTER_1_CONTEXT_NAME}" -n "connectivity-test" -f - <<EOF
    2apiVersion: v1
    3kind: Service
    4metadata:
    5 name: echoserver
    6spec:
    7 ports:
    8 - port: 8080
    9 targetPort: 8080
    10 protocol: TCP
    11 selector:
    12 app: echoserver1
    13EOF
  11. Create round robin service on cluster 2:

    1kubectl apply --context "${K8S_CLUSTER_2_CONTEXT_NAME}" -n "connectivity-test" -f - <<EOF
    2apiVersion: v1
    3kind: Service
    4metadata:
    5 name: echoserver
    6spec:
    7 ports:
    8 - port: 8080
    9 targetPort: 8080
    10 protocol: TCP
    11 selector:
    12 app: echoserver2
    13EOF
  12. Verify Pod 0 from cluster 1:

    1source_cluster=${K8S_CLUSTER_1_CONTEXT_NAME}
    2target_pod="echoserver0-0"
    3source_pod="echoserver1-0"
    4target_url="http://${target_pod}.connectivity-test.svc.cluster.local:8080"
    5echo "Checking cross-cluster DNS resolution and connectivity from ${source_pod} in ${source_cluster} to ${target_pod}"
    6out=$(kubectl exec --context "${source_cluster}" -n "connectivity-test" "${source_pod}" -- \
    7 /bin/bash -c "curl -v ${target_url}" 2>&1);
    8
    9if grep "Hostname: ${target_pod}" &>/dev/null <<< "${out}"
    10then
    11 echo "SUCCESS"
    12else
    13 echo "ERROR: ${out}"
    14 return 1
    15fi
    1Checking cross-cluster DNS resolution and connectivity from echoserver1-0 in gke_scratch-kubernetes-team_europe-central2-b_k8s-mdb-1-682f2df6e1745e000788a1d5-24552 to echoserver0-0
    2SUCCESS
  13. Verify Pod 1 from cluster 0:

    1source_cluster=${K8S_CLUSTER_0_CONTEXT_NAME}
    2target_pod="echoserver1-0"
    3source_pod="echoserver0-0"
    4target_url="http://${target_pod}.connectivity-test.svc.cluster.local:8080"
    5echo "Checking cross-cluster DNS resolution and connectivity from ${source_pod} in ${source_cluster} to ${target_pod}"
    6out=$(kubectl exec --context "${source_cluster}" -n "connectivity-test" "${source_pod}" -- \
    7 /bin/bash -c "curl -v ${target_url}" 2>&1);
    8
    9if grep "Hostname: ${target_pod}" &>/dev/null <<< "${out}"
    10then
    11 echo "SUCCESS"
    12else
    13 echo "ERROR: ${out}"
    14 return 1
    15fi
    1Checking cross-cluster DNS resolution and connectivity from echoserver0-0 in gke_scratch-kubernetes-team_europe-central2-a_k8s-mdb-0-682f2df6e1745e000788a1d5-24552 to echoserver1-0
    2SUCCESS
  14. Verify Pod 1 from cluster 2:

    1source_cluster=${K8S_CLUSTER_2_CONTEXT_NAME}
    2target_pod="echoserver1-0"
    3source_pod="echoserver2-0"
    4target_url="http://${target_pod}.connectivity-test.svc.cluster.local:8080"
    5echo "Checking cross-cluster DNS resolution and connectivity from ${source_pod} in ${source_cluster} to ${target_pod}"
    6out=$(kubectl exec --context "${source_cluster}" -n "connectivity-test" "${source_pod}" -- \
    7 /bin/bash -c "curl -v ${target_url}" 2>&1);
    8
    9if grep "Hostname: ${target_pod}" &>/dev/null <<< "${out}"
    10then
    11 echo "SUCCESS"
    12else
    13 echo "ERROR: ${out}"
    14 return 1
    15fi
    1Checking cross-cluster DNS resolution and connectivity from echoserver2-0 in gke_scratch-kubernetes-team_europe-central2-c_k8s-mdb-2-682f2df6e1745e000788a1d5-24552 to echoserver1-0
    2SUCCESS
  15. Verify Pod 2 from cluster 0:

    1source_cluster=${K8S_CLUSTER_0_CONTEXT_NAME}
    2target_pod="echoserver2-0"
    3source_pod="echoserver0-0"
    4target_url="http://${target_pod}.connectivity-test.svc.cluster.local:8080"
    5echo "Checking cross-cluster DNS resolution and connectivity from ${source_pod} in ${source_cluster} to ${target_pod}"
    6out=$(kubectl exec --context "${source_cluster}" -n "connectivity-test" "${source_pod}" -- \
    7 /bin/bash -c "curl -v ${target_url}" 2>&1);
    8
    9if grep "Hostname: ${target_pod}" &>/dev/null <<< "${out}"
    10then
    11 echo "SUCCESS"
    12else
    13 echo "ERROR: ${out}"
    14 return 1
    15fi
    1Checking cross-cluster DNS resolution and connectivity from echoserver0-0 in gke_scratch-kubernetes-team_europe-central2-a_k8s-mdb-0-682f2df6e1745e000788a1d5-24552 to echoserver2-0
    2SUCCESS
  16. Run the cleanup script:

    1kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "connectivity-test" delete statefulset echoserver0
    2kubectl --context "${K8S_CLUSTER_1_CONTEXT_NAME}" -n "connectivity-test" delete statefulset echoserver1
    3kubectl --context "${K8S_CLUSTER_2_CONTEXT_NAME}" -n "connectivity-test" delete statefulset echoserver2
    4kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "connectivity-test" delete service echoserver
    5kubectl --context "${K8S_CLUSTER_1_CONTEXT_NAME}" -n "connectivity-test" delete service echoserver
    6kubectl --context "${K8S_CLUSTER_2_CONTEXT_NAME}" -n "connectivity-test" delete service echoserver
    7kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "connectivity-test" delete service echoserver0-0
    8kubectl --context "${K8S_CLUSTER_1_CONTEXT_NAME}" -n "connectivity-test" delete service echoserver1-0
    9kubectl --context "${K8S_CLUSTER_2_CONTEXT_NAME}" -n "connectivity-test" delete service echoserver2-0
    10kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" delete ns "connectivity-test"
    11kubectl --context "${K8S_CLUSTER_1_CONTEXT_NAME}" delete ns "connectivity-test"
    12kubectl --context "${K8S_CLUSTER_2_CONTEXT_NAME}" delete ns "connectivity-test"

Back

GKE Clusters

On this page