# Skupper enables inter-cluster TCP communication
[](https://github.com/pwright/skupper-example-tcp-echo/actions/workflows/main.yaml)
#### TCP tunneling with Skupper
This example is part of a [suite of examples][examples] showing the
different ways you can use [Skupper][website] to connect services
across cloud providers, data centers, and edge sites.
[website]: https://skupper.io/
[examples]: https://skupper.io/examples/index.html
#### Contents
* [Overview](#overview)
* [Prerequisites](#prerequisites)
* [Step 1: Access your Kubernetes clusters](#step-1-access-your-kubernetes-clusters)
* [Step 2: Create your Kubernetes namespaces](#step-2-create-your-kubernetes-namespaces)
* [Step 3: Install Skupper on your Kubernetes clusters](#step-3-install-skupper-on-your-kubernetes-clusters)
* [Step 4: Install the Skupper command-line tool](#step-4-install-the-skupper-command-line-tool)
* [Step 5: Deploy the TCP echo server](#step-5-deploy-the-tcp-echo-server)
* [Step 6: Create your sites](#step-6-create-your-sites)
* [Step 7: Link your sites](#step-7-link-your-sites)
* [Step 8: Expose the TCP echo service](#step-8-expose-the-tcp-echo-service)
* [Step 9: Access the public service remotely](#step-9-access-the-public-service-remotely)
* [Cleaning up](#cleaning-up)
* [Summary](#summary)
* [Next steps](#next-steps)
* [About this example](#about-this-example)
## Overview
This is a simple demonstration of TCP communication tunneled through
a Skupper network from a private to a public cluster and back again.
During development of this demonstration, the private cluster was
running locally, while the public cluster was on AWS.
We set up a Skupper network between the two clusters, start a TCP
echo-server on the public cluster, then communicate to it from the
private cluster and receive its replies. At no time is any port
opened on the machine running the private cluster.
## Prerequisites
* Access to at least one Kubernetes cluster, from [any provider you
choose][kube-providers].
* The `kubectl` command-line tool, version 1.15 or later
([installation guide][install-kubectl]).
[kube-providers]: https://skupper.io/start/kubernetes.html
[install-kubectl]: https://kubernetes.io/docs/tasks/tools/install-kubectl/
## Step 1: Access your Kubernetes clusters
Skupper is designed for use with multiple Kubernetes clusters.
The `skupper` and `kubectl` commands use your
[kubeconfig][kubeconfig] and current context to select the cluster
and namespace where they operate.
[kubeconfig]: https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/
This example uses multiple cluster contexts at once. The
`KUBECONFIG` environment variable tells `skupper` and `kubectl`
which kubeconfig to use.
For each cluster, open a new terminal window. In each terminal,
set the `KUBECONFIG` environment variable to a different path and
log in to your cluster.
_**Public:**_
~~~ shell
export KUBECONFIG=/tmp/public-kubeconfig
~~~
_**Private:**_
~~~ shell
export KUBECONFIG=/tmp/private-kubeconfig
~~~
**Note:** The login procedure varies by provider.
## Step 2: Create your Kubernetes namespaces
The example application has different components deployed to
different Kubernetes namespaces. To set up our example, we need
to create the namespaces.
For each cluster, use `kubectl create namespace` and `kubectl
config set-context` to create the namespace you wish to use and
set the namespace on your current context.
_**Public:**_
~~~ shell
kubectl create namespace public
kubectl config set-context --current --namespace public
~~~
_**Private:**_
~~~ shell
kubectl create namespace private
kubectl config set-context --current --namespace private
~~~
## Step 3: Install Skupper on your Kubernetes clusters
Using Skupper on Kubernetes requires the installation of the
Skupper custom resource definitions (CRDs) and the Skupper
controller.
For each cluster, use `kubectl apply` with the Skupper
installation YAML to install the CRDs and controller.
_**Public:**_
~~~ shell
kubectl apply -f https://skupper.io/v2/install.yaml
~~~
_**Private:**_
~~~ shell
kubectl apply -f https://skupper.io/v2/install.yaml
~~~
## Step 4: Install the Skupper command-line tool
This example uses the Skupper command-line tool to create Skupper
resources. You need to install the `skupper` command only once
for each development environment.
On Linux or Mac, you can use the install script (inspect it
[here][install-script]) to download and extract the command:
~~~ shell
curl https://skupper.io/v2/install.sh | sh
~~~
The script installs the command under your home directory. It
prompts you to add the command to your path if necessary.
For Windows and other installation options, see [Installing
Skupper][install-docs].
[install-script]: https://github.com/skupperproject/skupper-website/blob/main/input/install.sh
[install-docs]: https://skupper.io/install/
## Step 5: Deploy the TCP echo server
_**Public:**_
~~~ shell
kubectl apply -f ./public-deployment.yaml
~~~
## Step 6: Create your sites
A Skupper _site_ is a location where your application workloads
are running. Sites are linked together to form a network for your
application.
For each namespace, use `skupper site create` with a site name of
your choice. This creates the site resource and deploys the
Skupper router to the namespace.
**Note:** If you are using Minikube, you need to [start minikube
tunnel][minikube-tunnel] before you run `skupper site create`.
[minikube-tunnel]: https://skupper.io/start/minikube.html#running-minikube-tunnel
_**Public:**_
~~~ shell
skupper site create public --enable-link-access
~~~
_Sample output:_
~~~ console
$ skupper site create public --enable-link-access
Waiting for status...
Site "public" is configured. Check the status to see when it is ready
~~~
_**Private:**_
~~~ shell
skupper site create private
~~~
_Sample output:_
~~~ console
$ skupper site create private
Waiting for status...
Site "private" is configured. Check the status to see when it is ready
~~~
You can use `skupper site status` at any time to check the status
of your site.
## Step 7: Link your sites
A Skupper _link_ is a channel for communication between two sites.
Links serve as a transport for application connections and
requests.
Creating a link requires the use of two Skupper commands in
conjunction: `skupper token issue` and `skupper token redeem`.
The `skupper token issue` command generates a secret token that
can be transferred to a remote site and redeemed for a link to the
issuing site. The `skupper token redeem` command uses the token
to create the link.
**Note:** The link token is truly a *secret*. Anyone who has the
token can link to your site. Make sure that only those you trust
have access to it.
First, use `skupper token issue` in Public to generate the token.
Then, use `skupper token redeem` in Private to link the sites.
_**Public:**_
~~~ shell
skupper token issue ~/secret.token
~~~
_Sample output:_
~~~ console
$ skupper token issue ~/secret.token
Waiting for token status ...
Grant "west-cad4f72d-2917-49b9-ab66-cdaca4d6cf9c" is ready
Token file /run/user/1000/skewer/secret.token created
Transfer this file to a remote site. At the remote site,
create a link to this site using the "skupper token redeem" command:
skupper token redeem
The token expires after 1 use(s) or after 15m0s.
~~~
_**Private:**_
~~~ shell
skupper token redeem ~/secret.token
~~~
_Sample output:_
~~~ console
$ skupper token redeem ~/secret.token
Waiting for token status ...
Token "west-cad4f72d-2917-49b9-ab66-cdaca4d6cf9c" has been redeemed
You can now safely delete /run/user/1000/skewer/secret.token
~~~
If your terminal sessions are on different machines, you may need
to use `scp` or a similar tool to transfer the token securely. By
default, tokens expire after a single use or 15 minutes after
being issued.
## Step 8: Expose the TCP echo service
Create a listener in the private cluster where the client runs and
a connector in the public cluster where the echo server runs. This
makes the public echo service reachable inside the private
namespace as `tcp-go-echo` on port 9090.
_**Private:**_
~~~ shell
skupper listener create tcp-go-echo 9090
~~~
_**Public:**_
~~~ shell
skupper connector create tcp-go-echo 9090 --workload deployment/tcp-go-echo
~~~
## Step 9: Access the public service remotely
From the private cluster, forward traffic to the exposed echo
service and verify that it responds.
_**Private:**_
~~~ shell
kubectl get svc
kubectl port-forward service/tcp-go-echo 9090:9090
telnet 0.0.0.0 9090
~~~
_Sample output:_
~~~ console
$ telnet 0.0.0.0 9090
hello, Skupper
tcp-go-echo-7ddbc7756c-wxgcq : HELLO, SKUPPER
~~~
## Cleaning up
To remove Skupper and the other resources from this exercise, use
the following commands.
_**Public:**_
~~~ shell
skupper site delete --all
kubectl delete -f ./public-deployment.yaml
~~~
_**Private:**_
~~~ shell
skupper site delete --all
~~~
## Summary
The TCP echo server runs only in the public cluster, but Skupper
exposes it as a local service in the private cluster. By forwarding
to the private cluster, you can reach the public service without
opening any ports on the private side. Skupper handles the encrypted
traffic between clusters transparently, so the echo replies arrive as
if the service were running locally.
## Next steps
Check out the other [examples][examples] on the Skupper website.
## About this example
This example was produced using [Skewer][skewer], a library for
documenting and testing Skupper examples.
[skewer]: https://github.com/skupperproject/skewer
Skewer provides utility functions for generating the README and
running the example steps. Use the `./plano` command in the project
root to see what is available.
To quickly stand up the example using Minikube, try the `./plano demo`
command.