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
kubectl
command-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 | 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.
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-public
Console for private:
export KUBECONFIG=~/.kube/config-private
The 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:
oc new-project public
oc config set-context --current --namespace public
Sample output:
$ oc new-project public ─╯
Now using project "public" on server "https://api.tenant-01-aws.sandbox1286.opentlc.com:6443".
You can add applications to this project with the 'new-app' command. For example, try:
oc new-app rails-postgresql-example
to build a new example application in Ruby. Or use kubectl to deploy a simple Kubernetes application:
kubectl create deployment hello-node --image=registry.k8s.io/e2e-test-images/agnhost:2.43 -- /agnhost serve-hostname
$ oc config set-context --current --namespace public ─╯
Context "public/api-tenant-01-aws-sandbox1286-opentlc-com:6443/system:admin" modified.
Console for private:
oc new-project private
oc config set-context --current --namespace private
Sample output:
$ oc new-project private ─╯
Now using project "private" on server "https://<ocp_api>:6443".
You can add applications to this project with the 'new-app' command. For example, try:
oc new-app rails-postgresql-example
to build a new example application in Ruby. Or use kubectl to deploy a simple Kubernetes application:
kubectl create deployment hello-node --image=registry.k8s.io/e2e-test-images/agnhost:2.43 -- /agnhost serve-hostname
$ oc config set-context --current --namespace private ─╯
Context "private/<ocp_api>:6443/system:admin" 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 init --enable-console --enable-flow-collector
Sample output:
$ skupper init --enable-console --enable-flow-collector
Skupper is now installed in namespace 'public'. Use 'skupper status' to get more information.
Console for private:
skupper init --enable-console --enable-flow-collector
Sample output:
$ skupper init --enable-console --enable-flow-collector
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 status
Sample output:
$ skupper status ─╯
Skupper is enabled for namespace "public" in interior mode. It is not connected to any other sites. It has no exposed services.
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 status
Sample 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.token
Sample output:
$ skupper token create ~/secret.token
Token written to ~/secret.token
Console for private:
skupper link create ~/secret.token
Sample output:
$ skupper link create ~/secret.token
Site configured to link to https://claims-public.apps.<ocp_cluster_basename>:443/382186f1-fe4e-11ed-816b-8c8caa458e86 (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 podman
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 oc get service/database
to ensure the database
service is available.
Console for public:
podman run --name database --detach --rm -p 5432:5432 quay.io/skupper/patient-portal-database
skupper gateway expose database localhost 5432 --type podman
oc get service/database
Sample output:
$ skupper gateway expose database localhost 5432 --type podman
2023/05/29 21:04:12 CREATE io.skupper.router.tcpConnector database:5432 map[address:database:5432 host:localhost name:database:5432 port:5432 siteId:70aaec38-0f06-4cae-b0a6-db700f705c6f]
$ oc get service/database
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
database ClusterIP 172.30.88.107 <none> 5432/TCP 35s
In the private namespace, use the oc 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 oc get service/payment-processor
to
check that the payment-processor
service appears after a
moment.
Console for private:
oc apply -f payment-processor/kubernetes.yaml
skupper expose deployment/payment-processor --port 8080
Sample output:
$ oc apply -f payment-processor/kubernetes.yaml
deployment.apps/payment-processor created
$ skupper expose deployment/payment-processor --port 8080
deployment payment-processor exposed as payment-processor
Console for public:
oc get service/payment-processor
Sample 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 1s
In the public namespace, use the oc apply
command to
deploy the frontend service. We need to also set up a route for the frontend.
Console for public:
oc apply -f frontend/kubernetes.yaml
Sample output:
$ oc apply -f frontend/kubernetes.yaml
deployment.apps/frontend created
service/frontend created
oc expose service frontend
Sample output:
$ oc expose service frontend
route.route.openshift.io/frontend exposed
Now we're ready to try it out. Use oc get route frontend --output jsonpath={.spec.host}
to look up the <frontend_route> of the frontend service. Then use
curl
or a similar tool to request the /api/health
endpoint at
that address.
Console for public:
oc get route frontend --output jsonpath={.spec.host}
curl http://<frontend_route>:8080/api/health
Sample output:
$ oc get route frontend --output jsonpath={.spec.host}
<frontend_route>%
$ curl http://<frontend_route>/api/health
OK
If everything is in order, you can now access the web interface by
navigating to http://<frontend_route/
in your browser.
Try creating some random appointments to see the DB logs.
And finally pay some bills for the patient=1 to visualize all the flow.
To remove Skupper and the other resources from this exercise, use the following commands.
Console for public:
podman stop database
skupper gateway delete
skupper delete
oc delete project public
Console for private:
skupper delete
oc delete project private
Check 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.