{"id":20572172,"url":"https://github.com/mcaimi/servicemesh-demo","last_synced_at":"2026-04-25T05:39:26.582Z","repository":{"id":69446941,"uuid":"446478892","full_name":"mcaimi/servicemesh-demo","owner":"mcaimi","description":"Openshift ServiceMesh Demo ","archived":false,"fork":false,"pushed_at":"2023-03-15T08:49:20.000Z","size":1153,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-01-16T21:16:03.986Z","etag":null,"topics":["istio","openshift-v4","quarkus","redhat","servicemesh","tekton-pipelines"],"latest_commit_sha":null,"homepage":"","language":"Shell","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/mcaimi.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-01-10T15:30:47.000Z","updated_at":"2023-04-21T20:45:44.000Z","dependencies_parsed_at":"2023-05-10T17:45:12.082Z","dependency_job_id":null,"html_url":"https://github.com/mcaimi/servicemesh-demo","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcaimi%2Fservicemesh-demo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcaimi%2Fservicemesh-demo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcaimi%2Fservicemesh-demo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcaimi%2Fservicemesh-demo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mcaimi","download_url":"https://codeload.github.com/mcaimi/servicemesh-demo/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":242187809,"owners_count":20086224,"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","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":["istio","openshift-v4","quarkus","redhat","servicemesh","tekton-pipelines"],"created_at":"2024-11-16T05:18:39.068Z","updated_at":"2026-04-25T05:39:26.551Z","avatar_url":"https://github.com/mcaimi.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Openshift Service Mesh Demo\n\nThis is a simple example of how to build a service-mesh enabled application with Quarkus and Tekton.\n\nThis demo implements a small Quarkus App that connects to a PostgreSQL database that stores simple notes. An AngularJS frontend is provided as well as a REST API endpoint.\n\nOpenshift ServiceMesh acts as an additional network service overlay that enriches the application with additional observability, security and routing features.\n\nThe code contained in this repository shows a simple real-world application that implements the following features:\n\n- An application that is service-mesh enabled.\n- Traffic is optionally encrypted by configuring mTLS on the service mesh overlay\n- The application is built with Tekton Pipelines\n- Request routing to different service versions by uri matching.\n- Kustomize templates for deployment are provided in this repository\n\nThe application code is based on the Quarkus Application that is found [here](https://github.com/mcaimi/k8s-demo-app). That application (which is based on Quarkus 1.13.2) is deployed as \"v1\" inside the service mesh.\nAnother instance of the same application acts as \"v2\". The application has been rebased to the latest Quarkus release and can be found [here](https://github.com/mcaimi/quarkus-notes).\n\n## Building the container image using Tekton on Openshift Container Platform (or Kubernetes)\n\nThis example pipeline needs Openshift Pipelines Operator in order to run. Please use the deployment manifests stored in this [repo](https://github.com/mcaimi/ocp4-argocd) to deploy the pipeline operator or add the component directly from the Openshift Console:\n\n![Pipeline Operator Installation](/assets/tekton-operator.png)\n\n### Running the example on Minikube\n\nThis demo is openshift-specific but it can be run on Kubernetes/Minikube as well, although that has not been tested for now.\nTo run the demo on Minikube a local minikube cluster with at the very least 4vCPU and 8GB of RAM is required. Also, be sure to enable the ingress and OLM addons when deploying the instance.\n\nThere should be no issues in running the Quarkus application and all Tekton pipelines (install the upstream tekton operator from [here](https://operatorhub.io/operator/tektoncd-operator)). Expect some issues with upstream [istio](https://istio.io/latest/docs/setup/platform-setup/minikube/) however because the upstream version of Istio and Openshift ServiceMesh are different in many aspects.\n\nRefer [here](https://istio.io) and [here](https://docs.openshift.com/container-platform/4.9/service_mesh/v2x/ossm-about.html) for more information.\n\n### Install The Openshift Service Mesh Control Plane\n\n1. Deploy the ServiceMesh Operator\n\nDeploy the operator using the provided Kustomize templates:\n\n```bash\n$ kustomize build --reorder none servicemesh/1.operator | oc apply -f -\n```\n\nor add the operator from the Openshift Console:\n\n![ServiceMesh Operator](/assets/ossm-operator.png)\n\n2. Deploy the ServiceMesh Control Plane\n\nDeploy the control plane using the provided Kustomize templates:\n\n```bash\n$ kustomize build servicemesh/2.controlplane | oc apply -f -\n```\n\nThis will install a complete control plane with ingress and egress gateways, IstioD, jaeger and kiali (to save resources, no persistence for tracing data is configured).\n\nAfter a while, the control plane should be up and running:\n\n![ossm-controlplane](/assets/ossm-controlplane.png)\n\n### Install and run tekton pipeline manifests to build the application\n\n1. Create a new project:\n\n```bash\n$ oc new-project istio-demo\n```\n\n2. Install tekton pipeline objects:\n\nFor the container image build pipeline:\n\n```bash\nfor i in build-pvc pipeline-resources quarkus-maven-task quarkus-build-task cleanup-workspace-task quarkus-build-pipeline; do\n  oc create -f tekton/$i.yaml -n istio-demo\ndone\n```\n\n3. Run the pipeline for app versions 1 and 2\n\nfor v1:\n\n```bash\n$ oc create -f tekton/quarkus-build-pipelinerun-v1.yaml -n istio-demo\n```\n\nfor v2:\n\n```bash\n$ oc create -f tekton/quarkus-build-pipelinerun-v2.yaml -n istio-demo\n```\n\nMonitor the pipelines until completion:\n\n```bash\n@ \u003e\u003e tkn pipelinerun list\nNAME                           STARTED         DURATION    STATUS\nv1-container-build-run-wl99x   3 minutes ago   2 minutes   Succeeded\nv2-container-build-run-h8tv9   7 minutes ago   3 minutes   Succeeded\n```\n\n![PipelineRun](/assets/pipelinerun.png)\n\nOnce completed, two new ImageStreamTags should be ready to be used in new deployments:\n\n```bash\n^ \u003e\u003e oc get imagestreams\nNAME                IMAGE REPOSITORY                                                                TAGS           UPDATED\ndemo-app-frontend   image-registry.openshift-image-registry.svc:5000/istio-demo/demo-app-frontend   v2,v1          2 minutes ago\n```\n\n## Deploy the Demo Application\n\n1. Enroll the namespace into the Service Mesh:\n\n```bash\n$ oc create -f servicemesh/3.application/servicemesh-membership.yaml\n```\n\nthis ensures that the namespace is correctly linked to and managed by the ServiceMesh Control Plane:\n\n```bash\n^ \u003e\u003e oc get smm\nNAME      CONTROL PLANE                 READY   AGE\ndefault   istio-system/istio-ctlplane   True    17h\n```\n\n2. Deploy the application\n\nDeploy the backend database and all needed objects by using the provided Kustomize templates:\n\n```bash\n$ kustomize build deployments/postgres | oc apply -f -\n```\n\n```bash\n$ kustomize build deployments/quarkus-app-v1 | oc apply -f -\n```\n\n3. Create Istio Objects\n\nConfigure the ServiceMesh to manage the deployed application:\n\n```bash\n$ oc create -f servicemesh/3.application/istio-gateway.yaml # the istio ingress gateway\n$ oc create -f servicemesh/3.application/postgres-virtualservice.yaml # the istio virtual service that exposes the Postgres Database\n$ oc create -f servicemesh/3.application/quarkus-destinationrule.yaml # Destination rule that maps application version 1 to a specific k8s deployment\n$ oc create -f servicemesh/3.application/quarkus-virtualservice.yaml # Virtual Service that exposes the Quarkus Application\n```\n\nThe application (version1) is deployed and managed by Istio:\n\n```bash\nNAME                                                                  READY   STATUS      RESTARTS   AGE\npod/backend-postgres-v1-community-659f558995-tvlwg                    2/2     Running     0          17h\npod/frontend-java-runner-v1-d9cb5b647-8wwxt                           2/2     Running     0          100m\n\nNAME                                            TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)             AGE\nservice/backend-postgres-service-v1-community   ClusterIP   172.30.244.121   \u003cnone\u003e        5432/TCP,5433/TCP   17h\nservice/frontend-java-runner-service-v1         ClusterIP   172.30.75.56     \u003cnone\u003e        80/TCP              114m\n\nNAME                                                                        HOST                                    AGE\ndestinationrule.networking.istio.io/postgres-app-destination-v1-community   backend-postgres-service-v1-community   106m\ndestinationrule.networking.istio.io/quarkus-app-destination-v1              frontend-java-runner-service-v1         108m\n\nNAME                                                  GATEWAYS                   HOSTS                                       AGE\nvirtualservice.networking.istio.io/postgres-demo-vs                              [\"backend-postgres-service-v1-community\"]   17h\nvirtualservice.networking.istio.io/quarkus-demo-vs    [\"quarkus-demo-gateway\"]   [\"quarkus-notes.apps.lab01.gpslab.club\"]    94m\n\nNAME                                               AGE\ngateway.networking.istio.io/quarkus-demo-gateway   17h\n```\n\n![frontendv1](/assets/frontend-v1.png)\n\nIn Kiali, the application topology is automatically discovered and displayed:\n\n![kiali-app-v1](/assets/kiali-v1.png)\n\nAt this point, all requests are routed from the istio Ingress Gateway to the service exposing the quarkus app version 1, which in turn uses the backend DB.\n\n### Deploy Authorization Policies\n\nThe deployment application can be secured by deploying Istio AuthorizationPolicies. Policies will be sent to all envoy proxies and enforced by the Mesh.\n\nFor example, we may want to restrict access to the frontend application to only allow HTTP and API calls coming from the Istio Gateway:\n\n```yaml\n---\napiVersion: security.istio.io/v1beta1\nkind: AuthorizationPolicy\nmetadata:\n name: frontend-authz\n namespace: istio-demo\nspec:\n selector:\n   matchLabels:\n     app: k8s-quarkus-app\n action: ALLOW\n rules:\n - from:\n     - source:\n         principals: [\"cluster.local/ns/istio-system/sa/istio-ingressgateway-service-account\"]\n   to:\n     - operation:\n        method: [\"GET\", \"POST\"]\n        paths: [\"/notes/*\"]\n     - operation:\n        method: [\"GET\"]\n        paths: [\"/\", \"*png\", \"*js\"]\n```\nThe above manifest instructs Istio to only allow traffic coming from workloads running under the ingress gateway service account: the policy allows 'GET' and 'POST' http calls to the '/notes/' API endpoint and only 'GET' calls to static content.\n\nTo secure access to the background DB anoter manifest needs to be deployed:\n\n```yaml\n---\napiVersion: security.istio.io/v1beta1\nkind: AuthorizationPolicy\nmetadata:\n name: postgres-authz\n namespace: istio-demo\nspec:\n selector:\n   matchLabels:\n     app: k8s-postgres-app\n     version: v1-community\n action: ALLOW\n rules:\n - from:\n   - source:\n       principals:\n         - \"cluster.local/ns/istio-demo/sa/frontend-java-runner-sa-v1\"\n         - \"cluster.local/ns/istio-demo/sa/frontend-java-runner-sa-v2\"\n   to:\n     -  operation:\n          ports: [\"5432\"]\n```\n\nThe above manifest will only allow TCP traffic directed to port 5432/TCP and only from workloads running under application service accounts.\n\n```bash\n$ oc create -f servicemesh/4.authorization_policy/frontend-authz.yaml\n$ oc create -f servicemesh/4.authorization_policy/postgres-authz.yaml\n```\n\n### Encrypt traffic on the Mesh Overlay\n\nBy default, all traffic flowing between Envoy Proxies is not encrypted. Encryption can be enabled by using mTLS globally on the control plane or by setting up a Policy on a per-namespace basis.\n\nThis can be done by setting up a PeerAuthentication manifest with a STRICT tls policy:\n\n```yaml\n---\napiVersion: security.istio.io/v1beta1\nkind: PeerAuthentication\nmetadata:\n  name: mtls-enable-policy\n  namespace: istio-demo\nspec:\n  mtls:\n    mode: STRICT\n```\n\nThis ensures that all traffic to/from envoy proxies is tunneled trough TLS.\n\n```bash\n$ oc create -f servicemesh/5.mTLS/mtls-policy.yaml\n```\n\nTo set up mutual TLS for services, a DestinationRule needs to be declared for every service version:\n\n```yaml\n---\napiVersion: networking.istio.io/v1beta1\nkind: DestinationRule\nmetadata:\n  name: postgres-app-destination-v1-community\nspec:\n  host: backend-postgres-service-v1-community\n  trafficPolicy:\n    tls:\n      mode: ISTIO_MUTUAL\n```\n\nthis service declares an ISTIO_MUTUAL TLS policy which means that certificates are automatically generated and rotated by the Service Mesh control plane.\nA Destination Route is needed for both PostgreSQL and Quarkus App.\n\n```bash\n# PostgreSQL\n$ oc apply -f postgres-destinatiorule.yaml\n$ oc apply -f postgres-virtualservice.yaml\n# Quarkus App\n$ oc apply -f quarkus-destinationrule.yaml\n$ oc apply -f quarkus-virtualservice.yaml\n\n$ oc get vs,dr,peerauthentication -n istio-demo\nNAME                                                  GATEWAYS                   HOSTS                                       AGE\nvirtualservice.networking.istio.io/postgres-demo-vs                              [\"backend-postgres-service-v1-community\"]   93m\nvirtualservice.networking.istio.io/quarkus-demo-vs    [\"quarkus-demo-gateway\"]   [\"quarkus-notes.apps.lab01.gpslab.club\"]    93m\n\nNAME                                                                        HOST                                    AGE\ndestinationrule.networking.istio.io/postgres-app-destination-v1-community   backend-postgres-service-v1-community   14s\ndestinationrule.networking.istio.io/quarkus-app-destination-v1              frontend-java-runner-service-v1         3h27m\n\nNAME                                                      MODE     AGE\npeerauthentication.security.istio.io/mtls-enable-policy   STRICT   25s\n```\n\nTraffic is now encrypted between virtual services. On the Kiali interface, the application graph displays a keylock icon to show all encrypted data flows:\n\n![mtls-flow](/assets/kiali-tls.png)\n\n### Route traffic to multiple service versions\n\n1. Deploy quarkus application version 2 using the provided kustomize templates:\n\n```bash\n$ kustomize build deployments/quarkus-app-v2 | oc create -f -\n```\n\n2. Deploy Istio Manifests\n\nIn the current namespace there are now two distinct quarkus-app deployments (v1,v2). A new virtual service will route all API calls to the app version1 endpoint, while routing all requests to the frontend page to the app version2 deployment:\n\n```yaml\n---\napiVersion: networking.istio.io/v1beta1\nkind: VirtualService\nmetadata:\n  name: quarkus-demo-vs\nspec:\n  hosts:\n    - quarkus-notes.apps.lab01.gpslab.club\n  gateways:\n  - quarkus-demo-gateway\n  http:\n  - name: \"Frontend served by v2\"\n    match:\n    - uri:\n        exact: /\n    - uri:\n        regex: '^.*\\.(ico|png|jpg)$'\n    route:\n    - destination:\n        host: frontend-java-runner-service-v2\n        subset: app-v2\n        port:\n          number: 80\n  - name: \"API served by v1\"\n    match:\n    - uri:\n        prefix: /notes\n    route:\n    - destination:\n        host: frontend-java-runner-service-v1\n        subset: app-v1\n        port:\n          number: 80\n```\n\n```bash\n# create destinationrule that maps application version 2\n$ oc create -f servicemesh/6.versioning/quarkus-destinationrule-v2.yaml\n# update the virtual service to route traffic to both services\n$ oc apply -f servicemesh/6.versioning/quarkus-virtualservice.yaml\n\n$ oc get pod,deployment,vs,dr,gw -n istio-demo\nNAME                                                                  READY   STATUS      RESTARTS   AGE\npod/backend-postgres-v1-community-659f558995-tvlwg                    2/2     Running     0          19h\npod/frontend-java-runner-v1-d9cb5b647-8wwxt                           2/2     Running     0          3h30m\npod/frontend-java-runner-v2-7766c85574-sgrqs                          2/2     Running     0          3h36m\n\nNAME                                            READY   UP-TO-DATE   AVAILABLE   AGE\ndeployment.apps/backend-postgres-v1-community   1/1     1            1           19h\ndeployment.apps/frontend-java-runner-v1         1/1     1            1           3h45m\ndeployment.apps/frontend-java-runner-v2         1/1     1            1           3h36m\n\nNAME                                                  GATEWAYS                   HOSTS                                       AGE\nvirtualservice.networking.istio.io/postgres-demo-vs                              [\"backend-postgres-service-v1-community\"]   105m\nvirtualservice.networking.istio.io/quarkus-demo-vs    [\"quarkus-demo-gateway\"]   [\"quarkus-notes.apps.lab01.gpslab.club\"]    105m\n\nNAME                                                                        HOST                                    AGE\ndestinationrule.networking.istio.io/postgres-app-destination-v1-community   backend-postgres-service-v1-community   11m\ndestinationrule.networking.istio.io/quarkus-app-destination-v1              frontend-java-runner-service-v1         3h39m\ndestinationrule.networking.istio.io/quarkus-app-destination-v2              frontend-java-runner-service-v2         8s\n\nNAME                                               AGE\ngateway.networking.istio.io/quarkus-demo-gateway   19h\n```\nSubsequent visits to the public URL will show the new UI while routing all API calls to the original endpoint:\n\n![new-ui](/assets/frontend-v2.png)\n\nKiali now recomputes the service graph accordingly:\n\n![kiali-v2](/assets/kiali-v2.png)\n\n### Migrate API traffic to API v2 (Jaeger-enabled)\n\nTo redirect all traffic to the V2 endpoint even for API calls (which are instrumented by Jaeger), the virtualservice must be modified:\n\n```yaml\n---\napiVersion: networking.istio.io/v1beta1\nkind: VirtualService\nmetadata:\n  name: quarkus-demo-vs\nspec:\n  hosts:\n    - quarkus-notes.apps.lab01.gpslab.club\n  gateways:\n  - quarkus-demo-gateway\n  http:\n  - name: \"Frontend and API served by v2\"\n    route:\n    - destination:\n        host: frontend-java-runner-service-v2\n        subset: app-v2\n        port:\n          number: 80\n\n```\n\nThen, update the running manifests:\n\n```bash\n# update the virtualservice\n$ oc apply -f servicemesh/7.service_move/quarkus-virtualservice.yaml\n# remove old manifests that are no more needed\n$ oc delete dr quarkus-app-destination-v1 quarkus-app-destinations\ndestinationrule.networking.istio.io \"quarkus-app-destination-v1\" deleted\ndestinationrule.networking.istio.io \"quarkus-app-destinations\" deleted\n\n# remove quarkus-v1 deployment\n$ kustomize build deployments/quarkus-app-v1|oc delete -f -\n```\n\nThe new service graph is now updated in Kiali:\n\n![kiali-v3](/assets/kiali-v3.png)\n\nSince the API backend is now configured to send spans to the Jaeger collector, tracing info related to API calls are displayed in the Jaeger console:\n\n![jaeger](/assets/jaeger.png)\n\n## Multicluster Federation\n\nOpenshift ServiceMesh supports Federation between two or more meshes running locally on the same cluster or running across different cluster instances.\nFederation allows Administrators to manage and view two or more Istio Meshes as if they were one and allows applications to consume services from any of the federated evironments.\n\nThe example consists of:\n\n1. Two Istio Meshes running inside the same Openshift Cluster\n2. Peering is configured via ClusterIP services (if deploying on different clusters, LoadBalancer or NodePort type service are required)\n3. One mesh will expose the application frontend\n4. The other mesh will export the database as a federated service\n\n### Deploy Meshes\n\nDeploy both meshes with kustomize:\n\n```bash\n# Mesh One\n$ kustomize build --reorder none servicemesh/8.federation/mesh-one | oc apply -f -\n# Mesh Two\n$ kustomize build --reorder none servicemesh/8.federation/mesh-two | oc apply -f -\n```\n\nThis operation will create :\n\n1. Mesh One control plane + frontend-namespace as its member project\n2. Mesh Two control plane + backend-namespace as its member project\n\nControl Planes are already configured for federation (i.e. both meshes declare their own trust domain and ingress/egress pairs for federation)\n\n### Extract root-ca certificates and configure peering\n\nFor every mesh, save the istio root CA certificate in a configmap. This CA is valid for the trust domain specified in the SCMP manifests of both meshes:\n\n```bash\n# For peering mesh-one with mesh-two\n$ oc get cm istio-ca-root-cert -n mesh-two -o jsonpath='{.data.root-cert\\.pem}' \u003e /tmp/mesh-two.pem\n$ oc create configmap mesh-two-ca-root-cert -n mesh-one --from-file=root-cert.pem=/tmp/mesh-two.pem\n# For peering mesh-two with mesh-one\n$ oc get cm istio-ca-root-cert -n mesh-one -o jsonpath='{.data.root-cert\\.pem}' \u003e /tmp/mesh-one.pem\n$ oc create configmap mesh-one-ca-root-cert -n mesh-two --from-file=root-cert.pem=/tmp/mesh-one.pem\n```\n\nThis will allow discovery and mutual tls authentication between Istio deployments. Peering is configured by declaring ServiceMeshPeer manifests:\n\n```yaml\nkind: ServiceMeshPeer\napiVersion: federation.maistra.io/v1\nmetadata:\n  name: mesh-two\n  namespace: mesh-one\nspec:\n  remote:\n    addresses:\n    - mesh-one-ingress.mesh-two.svc.cluster.local\n    discoveryPort: 8188\n    servicePort: 15443\n  gateways:\n    ingress:\n      name: mesh-two-ingress\n    egress:\n      name: mesh-two-egress\n  security:\n    trustDomain: mesh-two.local\n    clientID: mesh-two.local/ns/mesh-two/sa/mesh-one-egress-service-account\n    certificateChain:\n      kind: ConfigMap\n      name: mesh-two-ca-root-cert\n```\n\nApply peering manifests:\n\n```bash\n$ oc apply -f servicemesh/8.federation/peering/peering-mesh-one.yaml\n$ oc apply -f servicemesh/8.federation/peering/peering-mesh-two.yaml\n```\n\nPeering is mutual, so configuration needs to be performed on both sides. After a while, peering should be up \u0026 running:\n\nFor Mesh One to Mesh Two:\n\n```yaml\n#  oc get servicemeshpeer mesh-two -o yaml -n mesh-one\nstatus:\n  discoveryStatus:\n    active:\n    - pod: istiod-mesh-one-6cbb95f8dc-khgs4\n      remotes:\n      - connected: true\n        lastConnected: \"2022-04-07T07:48:40Z\"\n        lastFullSync: \"2022-04-07T07:53:40Z\"\n        source: 10.131.1.99\n```\n\nAnd for Mesh Two to Mesh One:\n\n```yaml\n#  oc get servicemeshpeer mesh-one -o yaml -n mesh-two\nstatus:\n  discoveryStatus:\n    active:\n    - pod: istiod-mesh-two-74dd58d75-5ps47\n      remotes:\n      - connected: true\n        lastConnected: \"2022-04-07T07:48:42Z\"\n        lastFullSync: \"2022-04-07T07:52:54Z\"\n        source: 10.131.1.94\n```\n\n### Export Services Across Meshes\n\nFederation assumes that services running in either mesh are *exported* from their source environment explicitly. Federating two or more meshes together does not automatically allow services on one mesh to consume endpoints on other meshes.\n\n*MESH TWO*: Deploy the Database Service in Mesh Two\n\nDeploy a PostgreSQL instance in the backend-namespace:\n\n```bash\n# deploy postgres in mesh-two\n$ kustomize build --reorder none servicemesh/8.federation/workload/postgres-mesh-two | oc apply -f -\n```\nThe service is displayed in the Kiali Console for the backend-cluster mesh instance:\n\n![mesh-backend-cluster](/assets/mesh-backend-cluster.png)\n\nNow from this namespace, export the postgres service in order to be consumed from the service running in mesh-one:\n\n```yaml\nkind: ExportedServiceSet\napiVersion: federation.maistra.io/v1\nmetadata:\n  name: mesh-one\n  namespace: mesh-two\nspec:\n  exportRules:\n  # export services with the correct label set\n  - type: LabelSelector\n    labelSelector:\n      namespace: backend-namespace\n      selector:\n        matchLabels:\n          app: k8s-postgres-app\n      aliases:\n      - alias:\n          namespace: backend\n```\n\nthis manifest will match any service with the *app: k8s-postgres-app* label and re-export them to the mesh-one peer.\n\n```bash\n$ oc apply -f servicemesh/8.federation/federated-services/mesh-two/exported-service-set.yaml -n mesh-two\n```\n\nOnce exported, the service should be listed in the status field of the ExportedServiceSet object in mesh-two namespace:\n\n```json\n$ oc get exportedserviceset.federation.maistra.io/mesh-one -n mesh-two -o jsonpath='{.status}' | jq .\n{\n  \"exportedServices\": [\n    {\n      \"exportedName\": \"postgres-service.backend.svc.mesh-one-exports.local\",\n      \"localService\": {\n        \"hostname\": \"postgres-service.backend-namespace.svc.cluster.local\",\n        \"name\": \"postgres-service\",\n        \"namespace\": \"backend-namespace\"\n      }\n    }\n  ]\n}\n```\n\n*MESH ONE*: Deploy the Quarkus frontend in Mesh One\n\nThe Frontend Service will be built and deployed in the frontend-namespace, which is a member of Mesh One:\n\n```bash\n# Build the application\n$ for i in build-pvc pipeline-resources quarkus-maven-task quarkus-build-task cleanup-workspace-task quarkus-build-pipeline; do\n  oc create -f tekton/$i.yaml -n frontend-namespace\ndone\n$ oc replace -f servicemesh/8.federation/workload/tekton/pipeline-resources.yaml -n frontend-namespace\n$ oc create -f servicemesh/8.federation/workload/tekton/quarkus-build-pipelinerun-v2.yaml -n frontend-namespace\n```\n\nAs with the backend before, the application is visible in the Kiali console of the frontend-cluster mesh:\n\n![mesh-frontend-cluster](/assets/mesh-frontend-cluster.png)\n\nFinally, the exported service exposed from mesh-two needs to be imported locally in order to be consumed from mesh-one:\n\n```bash\n$ oc apply -n mesh-one -f servicemesh/8.federation/federated-services/mesh-one/imported-service-set.yaml\n```\n\nThis will deploy an Imported Service Set manifest:\n\n```yaml\nkind: ImportedServiceSet\napiVersion: federation.maistra.io/v1\nmetadata:\n  name: mesh-two\n  namespace: mesh-one\nspec:\n  importRules: # first matching rule is used\n  - type: NameSelector\n    importAsLocal: false\n    nameSelector:\n      namespace: backend\n      name: postgres-service\n      alias:\n        # service will be imported as postgres-service.backend.svc.mesh-two-imports.local\n        namespace: backend\n        name: postgres-service\n```\n\nOnce imported, the service should appear in the Imported Services List:\n\n```json\n$ oc get importedserviceset.federation.maistra.io/mesh-two -n mesh-one -o jsonpath='{.status}'|jq .\n{\n  \"importedServices\": [\n    {\n      \"exportedName\": \"postgres-service.backend.svc.mesh-one-exports.local\",\n      \"localService\": {\n        \"hostname\": \"postgres-service.backend.svc.mesh-two-imports.local\",\n        \"name\": \"postgres-service\",\n        \"namespace\": \"backend\"\n      }\n    }\n  ]\n}\n```\n\nWith the imported service name available locally, the frontend application may be deployed:\n\n```bash\n# deploy the application\n$ kustomize build --reorder none servicemesh/8.federation/workload/quarkus-app-mesh-one | oc apply -f -\n```\n\nNow for this deployment to work, a couple objects need to be created in the frontend-namespace project:\n\n```bash\n$ for i in istio-gateway quarkus-virtualservice quarkus-destinationrule; do\n    oc apply -f servicemesh/8.federation/federated-services/mesh-one/$i.yaml -n frontend-namespace\ndone\n```\n\n## Related Guides\n\n- RESTEasy JAX-RS ([guide](https://quarkus.io/guides/rest-json)): REST endpoint framework implementing JAX-RS and more\n- TektonCD ([docs](https://docs.openshift.com/container-platform/4.9/cicd/pipelines/understanding-openshift-pipelines.html)): Openshift Pipelines Documentation\n- Istio.io ([docs](https://istio.io/latest/docs/)): Upstream Istio API Docs\n- ServiceMesh ([docs](https://docs.openshift.com/container-platform/4.9/service_mesh/v2x/ossm-about.html)): Openshift ServiceMesh specific documentation\n\n###  Notes\n\nContainer image build pipelines currently require the privileged SCC to be attached to the 'pipeline' ServiceAccount in order to successfully run:\n\n```bash\noc adm policy add-scc-to-user privileged system:serviceaccount:\u003ctarget_namespace\u003e:pipeline\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmcaimi%2Fservicemesh-demo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmcaimi%2Fservicemesh-demo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmcaimi%2Fservicemesh-demo/lists"}