nginx

Running basic connectivity between nginx server and client across two clusters using ClusterLink.

In this tutorial, we’ll establish connectivity across clusters using ClusterLink to access a remote nginx server. The tutorial uses two kind clusters:

  1. Client cluster - runs ClusterLink along with a client.
  2. Server cluster - runs ClusterLink along with a nginx server.
  1. Install ClusterLink CLI on Linux or Mac using the installation script:

    curl -L https://github.com/clusterlink-net/clusterlink/releases/latest/download/clusterlink.sh | sh -
    
  2. Verify the installation:

    clusterlink --version
    

Initialize clusters

This tutorial uses kind as a local Kubernetes environment. You can skip this step if you already have access to existing clusters, just be sure to set KUBECONFIG accordingly.

To setup two kind clusters:

  1. Install kind using kind installation guide.

  2. Create a directory for all the tutorial files:

    mkdir nginx-tutorial
    
  3. Open two terminals in the tutorial directory and create a kind cluster in each terminal:

    Client cluster:

    cd nginx-tutorial
    kind create cluster --name=client
    

    Server cluster:

    cd nginx-tutorial
    kind create cluster --name=server
    

    Note

    kind uses the prefix kind, so the name of created clusters will be kind-client and kind-server.

  4. Setup KUBECONFIG on each terminal to access the cluster:

    Client cluster:

    kubectl config use-context kind-client
    cp ~/.kube/config $PWD/config-client
    export KUBECONFIG=$PWD/config-client
    

    Server cluster:

    kubectl config use-context kind-server
    cp ~/.kube/config $PWD/config-server
    export KUBECONFIG=$PWD/config-server
    

Tip

You can run the tutorial in a single terminal and switch access between the clusters using kubectl config use-context kind-client and kubectl config use-context kind-server.

Deploy nginx client and server

Setup the TEST_FILES variable, and install nginx on the server cluster.

Client cluster:

export TEST_FILES=https://raw.githubusercontent.com/clusterlink-net/clusterlink/main/demos/nginx/testdata

Server cluster:

export TEST_FILES=https://raw.githubusercontent.com/clusterlink-net/clusterlink/main/demos/nginx/testdata
kubectl apply -f $TEST_FILES/nginx-server.yaml
  1. Create the fabric and peer certificates for the clusters:

    Client cluster:

    clusterlink create fabric
    clusterlink create peer-cert --name client
    

    Server cluster:

    clusterlink create peer-cert --name server
    

    All peer certificates (i.e., for the client and server clusters, in this tutorial) should be created from the same fabric CA files. In this tutorial, we assume the server has access to the Fabric certificate created in the default_fabric folder. In this tutorial, we assume the server cluster creation has access to the fabric certificate stored in the default_fabric folder. If it doesn’t, the fabric certificate should be copied from the client to the server.

    For more details regarding fabric and peer see core concepts.

  2. Deploy ClusterLink on each cluster:

    Client cluster:

    clusterlink deploy peer --name client --ingress=NodePort --ingress-port=30443
    

    Server cluster:

    clusterlink deploy peer --name server --ingress=NodePort --ingress-port=30443
    

    This tutorial uses NodePort to create an external access point for the kind clusters. By default deploy peer creates an ingress of type LoadBalancer, which is more suitable for Kubernetes clusters running in the cloud.

  3. Verify that ClusterLink control and data plane components are running:

    It may take a few seconds for the deployments to be successfully created.

    Client cluster:

    kubectl rollout status deployment cl-controlplane -n clusterlink-system
    kubectl rollout status deployment cl-dataplane -n clusterlink-system
    

    Server cluster:

    kubectl rollout status deployment cl-controlplane -n clusterlink-system
    kubectl rollout status deployment cl-dataplane -n clusterlink-system
    
Sample output
deployment "cl-controlplane" successfully rolled out
deployment "cl-dataplane" successfully rolled out

Enable cross-cluster access

In this step, we enable access between the client and server. For each step, you have an example demonstrating how to apply the command from a file or providing the complete custom resource (CR) associated with the command.

Note that the provided YAML configuration files refer to environment variables (defined below) that should be set when running the tutorial. The values are replaced in the YAMLs using envsubst utility.

Installing envsubst on macOS

In case envsubst does not exist, you can install it with:

brew install gettext
brew link --force gettext

Set-up peers

Add the remote peer to each cluster:

Client cluster:

export SERVER_IP=`docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' server-control-plane`
curl -s $TEST_FILES/clusterlink/peer-server.yaml | envsubst | kubectl apply -f -
export SERVER_IP=`docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' server-control-plane`
echo "
apiVersion: clusterlink.net/v1alpha1
kind: Peer
metadata:
  name: server
  namespace: clusterlink-system
spec:
  gateways:
    - host: "${SERVER_IP}"
      port: 30443
" | kubectl apply -f -

Server cluster:

export CLIENT_IP=`docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' client-control-plane`
curl -s $TEST_FILES/clusterlink/peer-client.yaml | envsubst | kubectl apply -f -
export CLIENT_IP=`docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' client-control-plane`
echo "
apiVersion: clusterlink.net/v1alpha1
kind: Peer
metadata:
  name: client
  namespace: clusterlink-system
spec:
  gateways:
    - host: "${CLIENT_IP}"
      port: 30443
" | kubectl apply -f -

The CLIENT_IP and SERVER_IP refers to the node IP of the peer kind cluster, which assigns the peer YAML file.

To verify that the connectivity between the peers is established correctly, please check if the condition PeerReachable has been added to the peer CR status in each cluster.

kubectl describe peers.clusterlink.net -A
Sample output
Name:         client
Namespace:    clusterlink-system
Labels:       <none>
Annotations:  <none>
API Version:  clusterlink.net/v1alpha1
Kind:         Peer
Metadata:
  Creation Timestamp:  2024-05-28T12:47:33Z
  Generation:          1
  Resource Version:    807
  UID:                 1fdeafff-707a-43e2-bb3a-826f003a42ed
Spec:
  Gateways:
    Host:  172.18.0.4
    Port:  30443
Status:
  Conditions:
    Last Transition Time:  2024-05-28T12:47:33Z
    Message:
    Reason:                Heartbeat
    Status:                True
    Type:                  PeerReachable

Export the nginx server endpoint

In the server cluster, export the nginx server service:

Server cluster:

kubectl apply -f $TEST_FILES/clusterlink/export-nginx.yaml
echo "
apiVersion: clusterlink.net/v1alpha1
kind: Export
metadata:
  name: nginx
  namespace: default
spec:
  port:  80
" | kubectl apply -f -

Set-up import

In the client cluster, import the nginx service from the server cluster:

Client cluster:

kubectl apply -f $TEST_FILES/clusterlink/import-nginx.yaml
echo "
apiVersion: clusterlink.net/v1alpha1
kind: Import
metadata:
  name: nginx
  namespace: default
spec:
  port:       80
  sources:
    - exportName:       nginx
      exportNamespace:  default
      peer:             server
" | kubectl apply -f -

Set-up access policies

Create access policies on both clusters to allow connectivity:

Client cluster:

kubectl apply -f $TEST_FILES/clusterlink/allow-policy.yaml
echo "
apiVersion: clusterlink.net/v1alpha1
kind: AccessPolicy
metadata:
  name: allow-policy
  namespace: default
spec:
  action: allow
  from:
    - workloadSelector: {}
  to:
    - workloadSelector: {}
" | kubectl apply -f -

Server cluster:

kubectl apply -f $TEST_FILES/clusterlink/allow-policy.yaml
echo "
apiVersion: clusterlink.net/v1alpha1
kind: AccessPolicy
metadata:
  name: allow-policy
  namespace: default
spec:
  action: allow
  from:
    - workloadSelector: {}
  to:
    - workloadSelector: {}
" | kubectl apply -f -

For more details regarding policy configuration, see policies documentation.

Test service connectivity

Test the connectivity between the clusters with a batch job of the curl command:

Client cluster:

kubectl apply -f $TEST_FILES/nginx-job.yaml

Verify the job succeeded:

kubectl logs jobs/curl-nginx-homepage
Sample output
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

Cleanup

  1. Delete the kind clusters: Client cluster:

    kind delete cluster --name=client
    

    Server cluster:

    kind delete cluster --name=server
    
  2. Remove the tutorial directory:

    cd .. && rm -rf nginx-tutorial
    
  3. Unset the environment variables: Client cluster:

    unset KUBECONFIG TEST_FILES
    

    Server cluster:

    unset KUBECONFIG TEST_FILES