{"id":19969069,"url":"https://github.com/pwright/skupper-example-annotation","last_synced_at":"2026-06-09T03:03:12.979Z","repository":{"id":103346731,"uuid":"548379813","full_name":"pwright/skupper-example-annotation","owner":"pwright","description":"A minimal multi-service HTTP application deployed across sites using Kubernetes annotations","archived":false,"fork":false,"pushed_at":"2022-11-03T15:17:31.000Z","size":74,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-01T17:48:36.404Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pwright.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-10-09T12:59:04.000Z","updated_at":"2022-10-12T18:05:04.000Z","dependencies_parsed_at":"2023-07-09T13:16:32.543Z","dependency_job_id":null,"html_url":"https://github.com/pwright/skupper-example-annotation","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/pwright/skupper-example-annotation","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pwright%2Fskupper-example-annotation","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pwright%2Fskupper-example-annotation/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pwright%2Fskupper-example-annotation/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pwright%2Fskupper-example-annotation/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pwright","download_url":"https://codeload.github.com/pwright/skupper-example-annotation/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pwright%2Fskupper-example-annotation/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286079811,"owners_count":27282121,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-11-27T02:00:05.795Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-13T02:48:37.110Z","updated_at":"2025-11-27T05:02:22.110Z","avatar_url":"https://github.com/pwright.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Skupper Hello World\n\n[![main](https://github.com/skupperproject/skupper-example-hello-world/actions/workflows/main.yaml/badge.svg)](https://github.com/skupperproject/skupper-example-hello-world/actions/workflows/main.yaml)\n\n#### A minimal HTTP application deployed across Kubernetes clusters using Skupper\n\nThis example is part of a [suite of examples][examples] showing the\ndifferent ways you can use [Skupper][website] to connect services\nacross cloud providers, data centers, and edge sites.\n\n[website]: https://skupper.io/\n[examples]: https://skupper.io/examples/index.html\n\n#### Contents\n\n* [Overview](#overview)\n* [Prerequisites](#prerequisites)\n* [Step 1: Install the Skupper command-line tool](#step-1-install-the-skupper-command-line-tool)\n* [Step 2: Configure separate console sessions](#step-2-configure-separate-console-sessions)\n* [Step 3: Access your clusters](#step-3-access-your-clusters)\n* [Step 4: Set up your namespaces](#step-4-set-up-your-namespaces)\n* [Step 5: Install Skupper in your namespaces](#step-5-install-skupper-in-your-namespaces)\n* [Step 6: Check the status of your namespaces](#step-6-check-the-status-of-your-namespaces)\n* [Step 7: Link your namespaces](#step-7-link-your-namespaces)\n* [Step 8: Deploy the frontend and backend services](#step-8-deploy-the-frontend-and-backend-services)\n* [Step 9: Expose the backend service](#step-9-expose-the-backend-service)\n* [Step 10: Expose the frontend service](#step-10-expose-the-frontend-service)\n* [Step 11: Test the application](#step-11-test-the-application)\n* [Accessing the web console](#accessing-the-web-console)\n* [Cleaning up](#cleaning-up)\n* [Summary](#summary)\n* [About this example](#about-this-example)\n\n## Overview\n\nThis example is a very simple multi-service HTTP application\ndeployed across Kubernetes clusters using Skupper.\n\nIt contains two services:\n\n* A backend service that exposes an `/api/hello` endpoint.  It\n  returns greetings of the form `Hi, \u003cyour-name\u003e.  I am \u003cmy-name\u003e\n  (\u003cpod-name\u003e)`.\n\n* A frontend service that sends greetings to the backend and\n  fetches new greetings in response.\n\nWith Skupper, you can place the backend in one cluster and the\nfrontend in another and maintain connectivity between the two\nservices without exposing the backend to the public internet.\n\n\u003cimg src=\"images/entities.svg\" width=\"640\"/\u003e\n\n## Prerequisites\n\n* The `kubectl` command-line tool, version 1.15 or later\n  ([installation guide][install-kubectl])\n\n* Access to at least one Kubernetes cluster, from [any provider you\n  choose][kube-providers]\n\n[install-kubectl]: https://kubernetes.io/docs/tasks/tools/install-kubectl/\n[kube-providers]: https://skupper.io/start/kubernetes.html\n\n## Step 1: Install the Skupper command-line tool\n\nThe `skupper` command-line tool is the entrypoint for installing\nand configuring Skupper.  You need to install the `skupper`\ncommand only once for each development environment.\n\nOn Linux or Mac, you can use the install script (inspect it\n[here][install-script]) to download and extract the command:\n\n~~~ shell\ncurl https://skupper.io/install.sh | sh\n~~~\n\nThe script installs the command under your home directory.  It\nprompts you to add the command to your path if necessary.\n\nFor Windows and other installation options, see [Installing\nSkupper][install-docs].\n\n[install-script]: https://github.com/skupperproject/skupper-website/blob/main/docs/install.sh\n[install-docs]: https://skupper.io/install/index.html\n\n## Step 2: Configure separate console sessions\n\nSkupper is designed for use with multiple namespaces, usually on\ndifferent clusters.  The `skupper` command uses your\n[kubeconfig][kubeconfig] and current context to select the\nnamespace where it operates.\n\n[kubeconfig]: https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/\n\nYour kubeconfig is stored in a file in your home directory.  The\n`skupper` and `kubectl` commands use the `KUBECONFIG` environment\nvariable to locate it.\n\nA single kubeconfig supports only one active context per user.\nSince you will be using multiple contexts at once in this\nexercise, you need to create distinct kubeconfigs.\n\nStart a console session for each of your namespaces.  Set the\n`KUBECONFIG` environment variable to a different path in each\nsession.\n\n_**Console for west:**_\n\n~~~ shell\nexport KUBECONFIG=~/.kube/config-west\n~~~\n\n_**Console for east:**_\n\n~~~ shell\nexport KUBECONFIG=~/.kube/config-east\n~~~\n\n## Step 3: Access your clusters\n\nThe procedure for accessing a Kubernetes cluster varies by\nprovider. [Find the instructions for your chosen\nprovider][kube-providers] and use them to authenticate and\nconfigure access for each console session.\n\n[kube-providers]: https://skupper.io/start/kubernetes.html\n\n## Step 4: Set up your namespaces\n\nUse `kubectl create namespace` to create the namespaces you wish\nto use (or use existing namespaces).  Use `kubectl config\nset-context` to set the current namespace for each session.\n\n_**Console for west:**_\n\n~~~ shell\nkubectl create namespace west\nkubectl config set-context --current --namespace west\n~~~\n\n_**Console for east:**_\n\n~~~ shell\nkubectl create namespace east\nkubectl config set-context --current --namespace east\n~~~\n\n## Step 5: Install Skupper in your namespaces\n\nThe `skupper init` command installs the Skupper router and service\ncontroller in the current namespace.  Run the `skupper init` command\nin each namespace.\n\n**Note:** If you are using Minikube, [you need to start `minikube\ntunnel`][minikube-tunnel] before you install Skupper.\n\n[minikube-tunnel]: https://skupper.io/start/minikube.html#running-minikube-tunnel\n\n_**Console for west:**_\n\n~~~ shell\nskupper init\n~~~\n\n_**Console for east:**_\n\n~~~ shell\nskupper init\n~~~\n\n_Sample output:_\n\n~~~ console\n$ skupper init\nWaiting for LoadBalancer IP or hostname...\nSkupper is now installed in namespace '\u003cnamespace\u003e'.  Use 'skupper status' to get more information.\n~~~\n\n## Step 6: Check the status of your namespaces\n\nUse `skupper status` in each console to check that Skupper is\ninstalled.\n\n_**Console for west:**_\n\n~~~ shell\nskupper status\n~~~\n\n_**Console for east:**_\n\n~~~ shell\nskupper status\n~~~\n\n_Sample output:_\n\n~~~ console\nSkupper is enabled for namespace \"\u003cnamespace\u003e\" in interior mode. It is connected to 1 other site. It has 1 exposed service.\nThe site console url is: \u003cconsole-url\u003e\nThe credentials for internal console-auth mode are held in secret: 'skupper-console-users'\n~~~\n\nAs you move through the steps below, you can use `skupper status` at\nany time to check your progress.\n\n## Step 7: Link your namespaces\n\nCreating a link requires use of two `skupper` commands in\nconjunction, `skupper token create` and `skupper link create`.\n\nThe `skupper token create` command generates a secret token that\nsignifies permission to create a link.  The token also carries the\nlink details.  Then, in a remote namespace, The `skupper link\ncreate` command uses the token to create a link to the namespace\nthat generated it.\n\n**Note:** The link token is truly a *secret*.  Anyone who has the\ntoken can link to your namespace.  Make sure that only those you\ntrust have access to it.\n\nFirst, use `skupper token create` in one namespace to generate the\ntoken.  Then, use `skupper link create` in the other to create a\nlink.\n\n_**Console for west:**_\n\n~~~ shell\nskupper token create ~/secret.token\n~~~\n\n_Sample output:_\n\n~~~ console\n$ skupper token create ~/secret.token\nToken written to ~/secret.token\n~~~\n\n_**Console for east:**_\n\n~~~ shell\nskupper link create ~/secret.token\n~~~\n\n_Sample output:_\n\n~~~ console\n$ skupper link create ~/secret.token\nSite configured to link to https://10.105.193.154:8081/ed9c37f6-d78a-11ec-a8c7-04421a4c5042 (name=link1)\nCheck the status of the link using 'skupper link status'.\n~~~\n\nIf your console sessions are on different machines, you may need\nto use `sftp` or a similar tool to transfer the token securely.\nBy default, tokens expire after a single use or 15 minutes after\ncreation.\n\n## Step 8: Deploy the frontend and backend services\n\nUse `kubectl create deployment` to deploy the frontend service\nin `west` and the backend service in `east`.\n\n_**Console for west:**_\n\n~~~ shell\nkubectl create deployment frontend --image quay.io/skupper/hello-world-frontend\n~~~\n\n_Sample output:_\n\n~~~ console\n$ kubectl create deployment frontend --image quay.io/skupper/hello-world-frontend\ndeployment.apps/frontend created\n~~~\n\n_**Console for east:**_\n\n~~~ shell\nkubectl create deployment backend --image quay.io/skupper/hello-world-backend --replicas 3\n~~~\n\n_Sample output:_\n\n~~~ console\n$ kubectl create deployment backend --image quay.io/skupper/hello-world-backend --replicas 3\ndeployment.apps/backend created\n~~~\n\n## Step 9: Expose the backend service\n\nWe now have two namespaces linked to form a Skupper network, but\nno services are exposed on it.  You can use the `skupper\nexpose` command to select a service from one namespace for\nexposure on all the linked namespaces, but in this example\nyou use annotations to expose the backend service to the\nfrontend service.\n\n_**Console for east:**_\n\n~~~ shell\nkubectl annotate deployment backend \"skupper.io/address=backend\" \"skupper.io/port=8080\" \"skupper.io/proxy=tcp\" \"skupper.io/target=backend\"\n~~~\n\n## Step 10: Expose the frontend service\n\nWe have established connectivity between the two namespaces and\nmade the backend in `east` available to the frontend in `west`.\nBefore we can test the application, we need external access to\nthe frontend.\n\nUse `kubectl expose` with `--type LoadBalancer` to open network\naccess to the frontend service.\n\n_**Console for west:**_\n\n~~~ shell\nkubectl expose deployment/frontend --port 8080 --type LoadBalancer\n~~~\n\n_Sample output:_\n\n~~~ console\n$ kubectl expose deployment/frontend --port 8080 --type LoadBalancer\nservice/frontend exposed\n~~~\n\n## Step 11: Test the application\n\nNow we're ready to try it out.  Use `kubectl get service/frontend`\nto look up the external IP of the frontend service.  Then use\n`curl` or a similar tool to request the `/api/health` endpoint at\nthat address.\n\n**Note:** The `\u003cexternal-ip\u003e` field in the following commands is a\nplaceholder.  The actual value is an IP address.\n\n_**Console for west:**_\n\n~~~ shell\nkubectl get service/frontend\ncurl http://\u003cexternal-ip\u003e:8080/api/health\n~~~\n\n_Sample output:_\n\n~~~ console\n$ kubectl get service/frontend\nNAME       TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)          AGE\nfrontend   LoadBalancer   10.103.232.28   \u003cexternal-ip\u003e   8080:30407/TCP   15s\n\n$ curl http://\u003cexternal-ip\u003e:8080/api/health\nOK\n~~~\n\nIf everything is in order, you can now access the web interface by\nnavigating to `http://\u003cexternal-ip\u003e:8080/` in your browser.\n\n## Accessing the web console\n\nSkupper includes a web console you can use to view the application\nnetwork.  To access it, use `skupper status` to look up the URL of\nthe web console.  Then use `kubectl get\nsecret/skupper-console-users` to look up the console admin\npassword.\n\n**Note:** The `\u003cconsole-url\u003e` and `\u003cpassword\u003e` fields in the\nfollowing output are placeholders.  The actual values are specific\nto your environment.\n\n_**Console for west:**_\n\n~~~ shell\nskupper status\nkubectl get secret/skupper-console-users -o jsonpath={.data.admin} | base64 -d\n~~~\n\n_Sample output:_\n\n~~~ console\n$ skupper status\nSkupper is enabled for namespace \"west\" in interior mode. It is connected to 1 other site. It has 1 exposed service.\nThe site console url is: \u003cconsole-url\u003e\nThe credentials for internal console-auth mode are held in secret: 'skupper-console-users'\n\n$ kubectl get secret/skupper-console-users -o jsonpath={.data.admin} | base64 -d\n\u003cpassword\u003e\n~~~\n\nNavigate to `\u003cconsole-url\u003e` in your browser.  When prompted, log\nin as user `admin` and enter the password.\n\n## Cleaning up\n\nTo remove Skupper and the other resources from this exercise, use\nthe following commands.\n\n_**Console for west:**_\n\n~~~ shell\nskupper delete\nkubectl delete service/frontend\nkubectl delete deployment/frontend\n~~~\n\n_**Console for east:**_\n\n~~~ shell\nskupper delete\nkubectl delete deployment/backend\n~~~\n\n## Summary\n\nThis example locates the frontend and backend services in different\nnamespaces, on different clusters.  Ordinarily, this means that they\nhave no way to communicate unless they are exposed to the public\ninternet.\n\nIntroducing Skupper into each namespace allows us to create a virtual\napplication network that can connect services in different clusters.\nAny service exposed on the application network is represented as a\nlocal service in all of the linked namespaces.\n\nThe backend service is located in `east`, but the frontend service\nin `west` can \"see\" it as if it were local.  When the frontend\nsends a request to the backend, Skupper forwards the request to the\nnamespace where the backend is running and routes the response back to\nthe frontend.\n\n\u003cimg src=\"images/sequence.svg\" width=\"640\"/\u003e\n\n## Next steps\n\nCheck out the other [examples][examples] on the Skupper website.\n\n## About this example\n\nThis example was produced using [Skewer][skewer], a library for\ndocumenting and testing Skupper examples.\n\n[skewer]: https://github.com/skupperproject/skewer\n\nSkewer provides utility functions for generating the README and\nrunning the example steps.  Use the `./plano` command in the project\nroot to see what is available.\n\nTo quickly stand up the example using Minikube, try the `./plano demo`\ncommand.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpwright%2Fskupper-example-annotation","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpwright%2Fskupper-example-annotation","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpwright%2Fskupper-example-annotation/lists"}