A simple database-backed web application that runs in the public cloud but keeps its data in a private database
This example is part of a suite of examples showing the different ways you can use Skupper to connect services across cloud providers, data centers, and edge sites.
- Overview
- Prerequisites
- Step 1: Install the Skupper command-line tool
- Step 2: Configure separate console sessions
- Step 3: Access your clusters
- Step 4: Set up your namespaces
- Step 5: Install Skupper in your namespaces
- Step 6: Check the status of your namespaces
- Step 7: Link your namespaces
- Step 8: Deploy and expose the database
- Step 9: Deploy and expose the payment processor
- Step 10: Deploy and expose the frontend
- Step 11: Test the application
- Cleaning up
- About this example
This example is a simple database-backed web application that shows how you can use Skupper to access a database at a remote site without exposing it to the public internet.
It contains three services:
-
A PostgreSQL database running on a bare-metal or virtual machine in a private data center.
-
A payment-processing service running on Kubernetes in a private data center.
-
A web frontend service running on Kubernetes in the public cloud. It uses the PostgreSQL database and the payment-processing service.
This example uses two Kubernetes namespaces, "private" and "public", to represent the private Kubernetes cluster and the public cloud.
-
The
kubectlcommand-line tool, version 1.15 or later (installation guide) -
Access to at least one Kubernetes cluster, from any provider you choose
The skupper command-line tool is the primary entrypoint for
installing and configuring the Skupper infrastructure. 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) to download and extract the command:
curl https://skupper.io/install.sh | shThe 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.
Skupper is designed for use with multiple namespaces, usually on
different clusters. The skupper command uses your
kubeconfig and current context to select the
namespace where it operates.
Your kubeconfig is stored in a file in your home directory. The
skupper and kubectl commands use the KUBECONFIG environment
variable to locate it.
A single kubeconfig supports only one active context per user. Since you will be using multiple contexts at once in this exercise, you need to create distinct kubeconfigs.
Start a console session for each of your namespaces. Set the
KUBECONFIG environment variable to a different path in each
session.
Console for public:
export KUBECONFIG=~/.kube/config-publicConsole for private:
export KUBECONFIG=~/.kube/config-privateThe methods for accessing your clusters vary by Kubernetes provider. Find the instructions for your chosen providers and use them to authenticate and configure access for each console session. See the following links for more information:
- Minikube
- Amazon Elastic Kubernetes Service (EKS)
- Azure Kubernetes Service (AKS)
- Google Kubernetes Engine (GKE)
- IBM Kubernetes Service
- OpenShift
- More providers
Use kubectl create namespace to create the namespaces you wish
to use (or use existing namespaces). Use kubectl config set-context to set the current namespace for each session.
Console for public:
kubectl create namespace public
kubectl config set-context --current --namespace publicSample output:
$ kubectl create namespace public
namespace/public created
$ kubectl config set-context --current --namespace public
Context "minikube" modified.Console for private:
kubectl create namespace private
kubectl config set-context --current --namespace privateSample output:
$ kubectl create namespace private
namespace/private created
$ kubectl config set-context --current --namespace private
Context "minikube" modified.The skupper init command installs the Skupper router and service
controller in the current namespace. Run the skupper init command
in each namespace.
Note: If you are using Minikube, you need to start minikube tunnel before you install Skupper.
Console for public:
skupper initSample output:
$ skupper init
Waiting for LoadBalancer IP or hostname...
Skupper is now installed in namespace 'public'. Use 'skupper status' to get more information.Console for private:
skupper initSample output:
$ skupper init
Waiting for LoadBalancer IP or hostname...
Skupper is now installed in namespace 'private'. Use 'skupper status' to get more information.Use skupper status in each console to check that Skupper is
installed.
Console for public:
skupper statusSample output:
$ skupper status
Skupper is enabled for namespace "public" in interior mode. It is connected to 1 other site. It has 1 exposed service.
The site console url is: <console-url>
The credentials for internal console-auth mode are held in secret: 'skupper-console-users'Console for private:
skupper statusSample output:
$ skupper status
Skupper is enabled for namespace "private" in interior mode. It is connected to 1 other site. It has 1 exposed service.
The site console url is: <console-url>
The credentials for internal console-auth mode are held in secret: 'skupper-console-users'As you move through the steps below, you can use skupper status at
any time to check your progress.
Creating a link requires use of two skupper commands in
conjunction, skupper token create and skupper link create.
The skupper token create command generates a secret token that
signifies permission to create a link. The token also carries the
link details. Then, in a remote namespace, The skupper link create command uses the token to create a link to the namespace
that generated it.
Note: The link token is truly a secret. Anyone who has the token can link to your namespace. Make sure that only those you trust have access to it.
First, use skupper token create in one namespace to generate the
token. Then, use skupper link create in the other to create a
link.
Console for public:
skupper token create ~/secret.tokenSample output:
$ skupper token create ~/secret.token
Token written to ~/secret.tokenConsole for private:
skupper link create ~/secret.tokenSample output:
$ skupper link create ~/secret.token
Site configured to link to https://10.105.193.154:8081/ed9c37f6-d78a-11ec-a8c7-04421a4c5042 (name=link1)
Check the status of the link using 'skupper link status'.If your console sessions are on different machines, you may need
to use sftp or a similar tool to transfer the token securely.
By default, tokens expire after a single use or 15 minutes after
creation.
Use docker to run the database service on your local machine.
In the public namespace, use the skupper gateway expose
command to expose the database on the Skupper network.
Use kubectl get service/database to ensure the database
service is available.
Console for public:
docker run --name database --detach --rm -p 5432:5432 quay.io/skupper/patient-portal-database
skupper gateway expose database localhost 5432 --type docker
kubectl get service/databaseSample output:
$ skupper gateway expose database localhost 5432 --type docker
2022/05/19 16:37:00 CREATE io.skupper.router.tcpConnector fancypants-jross-egress-database:5432 map[address:database:5432 host:localhost name:fancypants-jross-egress-database:5432 port:5432 siteId:0e7b70cf-1931-4c93-9614-0ecb3d0d6522]
$ kubectl get service/database
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
database ClusterIP 10.104.77.32 <none> 5432/TCP 15sIn the private namespace, use the kubectl apply command to
deploy the payment processor service. Use the skupper expose
command to expose the service on the Skupper network.
In the public namespace, use kubectl get service/payment-processor to
check that the payment-processor service appears after a
moment.
Console for private:
kubectl apply -f payment-processor/kubernetes.yaml
skupper expose deployment/payment-processor --port 8080Sample output:
$ kubectl apply -f payment-processor/kubernetes.yaml
deployment.apps/payment-processor created
$ skupper expose deployment/payment-processor --port 8080
deployment payment-processor exposed as payment-processorConsole for public:
kubectl get service/payment-processorSample output:
$ kubectl get service/payment-processor
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
payment-processor ClusterIP 10.103.227.109 <none> 8080/TCP 1sIn the public namespace, use the kubectl apply command to
deploy the frontend service. This also sets up an external load
balancer for the frontend.
Console for public:
kubectl apply -f frontend/kubernetes.yamlSample output:
$ kubectl apply -f frontend/kubernetes.yaml
deployment.apps/frontend created
service/frontend createdNow we're ready to try it out. Use kubectl get service/frontend
to look up the external IP of the frontend service. Then use
curl or a similar tool to request the /api/health endpoint at
that address.
Note: The <external-ip> field in the following commands is a
placeholder. The actual value is an IP address.
Console for public:
kubectl get service/frontend
curl http://<external-ip>:8080/api/healthSample output:
$ kubectl get service/frontend
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
frontend LoadBalancer 10.103.232.28 <external-ip> 8080:30407/TCP 15s
$ curl http://<external-ip>:8080/api/health
OKIf everything is in order, you can now access the web interface by
navigating to http://<external-ip>:8080/ in your browser.
To remove Skupper and the other resources from this exercise, use the following commands.
Console for public:
docker stop database
skupper gateway delete
skupper delete
kubectl delete service/frontend
kubectl delete deployment/frontendConsole for private:
skupper delete
kubectl delete deployment/payment-processorCheck out the other examples on the Skupper website.
This example was produced using Skewer, a library for documenting and testing Skupper examples.
Skewer provides some utilities 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.