{"id":20410305,"url":"https://github.com/kuadrant/api-quickstart","last_synced_at":"2025-09-24T04:31:35.948Z","repository":{"id":220314556,"uuid":"742469792","full_name":"Kuadrant/api-quickstart","owner":"Kuadrant","description":null,"archived":false,"fork":false,"pushed_at":"2024-04-26T13:16:20.000Z","size":200,"stargazers_count":0,"open_issues_count":1,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-11-15T05:45:24.087Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/Kuadrant.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}},"created_at":"2024-01-12T14:52:15.000Z","updated_at":"2024-01-31T14:50:35.000Z","dependencies_parsed_at":"2024-02-27T16:31:04.824Z","dependency_job_id":"38762604-94dc-468a-8c61-20c27be527ac","html_url":"https://github.com/Kuadrant/api-quickstart","commit_stats":null,"previous_names":["kuadrant/api-quickstart"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kuadrant%2Fapi-quickstart","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kuadrant%2Fapi-quickstart/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kuadrant%2Fapi-quickstart/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kuadrant%2Fapi-quickstart/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Kuadrant","download_url":"https://codeload.github.com/Kuadrant/api-quickstart/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":234037773,"owners_count":18769804,"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":[],"created_at":"2024-11-15T05:45:38.635Z","updated_at":"2025-09-24T04:31:30.486Z","avatar_url":"https://github.com/Kuadrant.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# API Quickstart\n\n## Introduction\n\nThis document details how to setup a local reference architecture, and design and deploy an API. This will show the following API management features in a kube native environment using Kuadrant and other open source tools:\n\n- API design\n- API security and access control\n- API monitoring\n- Traffic management and scalability\n\nThe sections in this document are grouped by the persona that is typically associated with the steps in that section. The 3 personas are:\n\n- The *platform engineer*, who provides and maintains a platform for application developers,\n- the *application developer*, who designs, builds and maintains applications and APIs,\n- and the *api consumer*, who makes API calls to the API\n\n\u003ciframe width=\"100%\" height=\"400\" src=\"https://www.youtube.com/embed/vbWM8st5PjM\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" allowfullscreen\u003e\u003c/iframe\u003e\n\n## Pre-requisities\n\n- `docker`: https://www.docker.com/products/docker-desktop/\n- `kind`: https://kind.sigs.k8s.io/\n- `kubectl`: https://kubernetes.io/docs/reference/kubectl/\n- `kustomize`: https://kustomize.io/\n- `helm`: https://helm.sh/docs/intro/install/\n- `operator-sdk`: https://sdk.operatorframework.io/docs/installation/\n- An [AWS account](https://aws.amazon.com/) with a Secret Access Key and Access Key ID. You will also need to a [Route 53](https://docs.aws.amazon.com/route53/) zone.\n\n## (Platform engineer) Platform Setup\n\nExport the following env vars:\n\n```bash\nexport KUADRANT_AWS_ACCESS_KEY_ID=\u003ckey_id\u003e\nexport KUADRANT_AWS_SECRET_ACCESS_KEY=\u003csecret\u003e\nexport KUADRANT_AWS_REGION=\u003cregion\u003e\nexport KUADRANT_AWS_DNS_PUBLIC_ZONE_ID=\u003czone\u003e\nexport KUADRANT_ZONE_ROOT_DOMAIN=\u003cdomain\u003e\n```\n\nClone the api-quickstart repo and run the quickstart script:\n\n```bash\ngit clone git@github.com:Kuadrant/api-quickstart.git \u0026\u0026 cd api-quickstart\n./quickstart.sh\n```\n\nThis will take several minutes as 3 local kind clusters are started and configured in a hub and spoke architecture.\nThe following components will be installed on the clusters:\n\n- Hub\n  - [Open Cluster Management](https://open-cluster-management.io/), as a 'hub' cluster\n  - [Kuadrant Multi Cluster Gateway Controller](https://docs.kuadrant.io/multicluster-gateway-controller/), for managing a Gateway in multiple clusters centrally\n  - [Gatekeeper](https://github.com/open-policy-agent/gatekeeper), for constraints on Gateway Policy requirements\n  - [Thanos](https://github.com/thanos-io/thanos), for receiving metrics centrally\n  - [Grafana](https://github.com/grafana/grafana), for visualising API \u0026 Gateway metrics\n- Spoke x2\n  - [Open Cluster Management](https://open-cluster-management.io/), as a 'spoke' cluster\n  - [Kuadrant Operator](https://docs.kuadrant.io/kuadrant-operator/), for auth and rate limiting policies attached to a HTTPRoute\n  - [Istio](https://istio.io/latest/docs/), with the Gateway API CRDs as the Gateway for ingress trafic\n  - [MetalLB](https://metallb.universe.tf/), for exposing the Gateway service on the local network\n  - [Prometheus](https://prometheus.io/), for scraping and federating metrics to the hub\n\n### Verify the Gateway and configuration\n\nView the ManagedZone, Gateway and TLSPolicy. The ManagedZone and TLSPolicy should have a Ready status of true. The Gateway should have a Programmed status of True.\n\n```bash\nkubectl --context kind-api-control-plane get managedzone,tlspolicy,gateway -n multi-cluster-gateways\n```\n\n### Guard Rails: Constraint warnings about missing policies ( DNS, TLS)\n\nRunning the quick start script above will bring up [Gatekeeper](https://open-policy-agent.github.io/gatekeeper/website/docs) and the following constraints: \n\n* Gateways must have a TLSPolicy targeting them\n* Gateways must have a DNSPolicy targeting them\n\nTo view the above constraints in kubernetes, run this command:\n```bash\nkubectl --context kind-api-control-plane get constraints\n```\n\n!!! info\n\n    Since a gateway has been created automatically, along with a `TLSPolicy`, the violation for a missing `DNSPolicy` will be active until one is created.\n\n### Grafana dashboard view\n\nTo get a top level view of the constraints in violation, the `Stitch: Platform Engineer Dashboard` can be used. This can be accessed by at [https://grafana.172.31.0.2.nip.io](https://grafana.172.31.0.2.nip.io)\n\nGrafana has a default username and password of `admin`.\nYou can find the `Stitch: Platform Engineer Dashboard` dashboard in the `Default` folder.\n\n### Create the missing DNSPolicy\n\nCreate a DNSPolicy that targets the Gateway with the following command:\n\n```bash\nkubectl --context kind-api-control-plane apply -f - \u003c\u003cEOF\napiVersion: kuadrant.io/v1alpha1\nkind: DNSPolicy\nmetadata:\n  name: prod-web\n  namespace: multi-cluster-gateways\nspec:\n  targetRef:\n    name: prod-web\n    group: gateway.networking.k8s.io\n    kind: Gateway\n  loadBalancing:\n    geo:\n      defaultGeo: EU\nEOF\n```\n\n### Platform Overview\n\nSince we have created all the policies that Gatekeeper had the guardrails around, you should no longer see any constraints in violation. This can be seen back in the `Stitch: Platform Engineer Dashboard` in Grafana at [https://grafana.172.31.0.2.nip.io](https://grafana.172.31.0.2.nip.io)\n\n## (Application developer) App setup\n\n### API Design\n\n[Fork](https://github.com/Kuadrant/api-petstore/fork) and/or clone the Petstore App at https://github.com/Kuadrant/api-petstore\n\n```bash\ngit clone git@github.com:kuadrant/api-petstore \u0026\u0026 cd api-petstore\n# Or if you forked the repository:\n# git clone git@github.com:\u003cyour_github_username\u003e/api-petstore \u0026\u0026 cd api-petstore\n```\n\nThen deploy it to the first workload cluster:\n\n```bash\nkustomize build ./resources/ | envsubst | kubectl --context kind-api-workload-1 apply -f-\n```\n\nThis will deploy:\n\n* A `petstore` Namespace\n* A `Secret`, containing a static API key that we'll use later for auth\n* A `Service` and `Deployment` for our petstore app\n* A Gateway API `HTTPRoute` for our petstore app\n\n#### Route 53 DNS Zone\n\nWhen the DNS Policy has been created, and the previously created `HTTPRoute` has been attached, a DNS record custom resource will also be created in the cluster resulting in records being created in your AWS Route53. Navigate to Route53 and you should see some new records in the zone.\n\n### Configuring the region label\n\nConfigure the app `REGION` to be `eu`:\n\n```bash\nkubectl --context kind-api-workload-1 apply -k ./resources/eu-cluster/\n```\n\n### Exploring the Open API Specification\n\nThe raw Open API spec can be found in the root of the repo:\n\n```bash\ncat openapi.yaml\n# ---\n# openapi: 3.0.2\n# info:\n#   title: Stitch API Petstore\n#   version: 1.0.18\n```\n\n## (Application developer) API security\n\nWe've included a number of sample `x-kuadrant` extensions in the OAS spec already:\n\n- At the top-level of our spec, we've defined an `x-kuadrant` extension to detail the Gateway API Gateway associated with our app:\n\n```yaml\n  x-kuadrant:\n    route:\n      name: petstore\n      namespace: petstore\n      labels:\n        deployment: petstore\n        owner: cferreir\n      hostnames:\n      - petstore.$KUADRANT_ZONE_ROOT_DOMAIN\n      parentRefs:\n      - name: prod-web\n        namespace: kuadrant-multi-cluster-gateways\n        kind: Gateway\n```\n\n- In `/user/login`, we have a Gateway API `backendRef` set and a `rate_limit` set. The rate limit policy for this endpoint restricts usage of this endpoint to 2 requests in a 10 second window:\n    ```yaml\n    x-kuadrant:\n      backendRefs:\n      - name: petstore\n        namespace: petstore\n        port: 8080\n      rate_limit:\n      rates:\n      - limit: 2\n        duration: 10\n        unit: second\n    ```\n- In `/store/inventory`, we have also have a Gateway API `backendRef`set and a `rate_limit` set. The rate limit policy for the endpoint restricts usage of this endpoint to 10 requests in a 10 second window:\n    ```yaml\n    x-kuadrant:\n      backendRefs:\n      - name: petstore\n        namespace: petstore\n        port: 8080\n      rate_limit:\n        rates:\n        - limit: 10\n          duration: 10\n          unit: second\n    ```\n- Finally, we have a `securityScheme` setup for apiKey auth, powered by Authorino. We'll show this in more detail a little later:\n  ```yaml\n  securitySchemes:\n    api_key:\n      type: apiKey\n      name: api_key\n      in: header\n  ```\n\nThese extensions allow us to automatically generate Kuadrant Kubernetes resources, including [AuthPolicies](https://docs.kuadrant.io/kuadrant-operator/doc/auth/), [RateLimitPolicies](https://docs.kuadrant.io/kuadrant-operator/doc/rate-limiting/) and [Gateway API resources](https://gateway-api.sigs.k8s.io/reference/spec/) such as HTTPRoutes.\n\n### kuadrantctl\n\n`kuadrantctl` is a cli that supports the generation of various Kubernetes resources via OAS specs.\nLet's run some commands to generate some of these resources.\nIf you forked the api-pestore repo, you can check them in also.\nLet's apply these to our running workload to implement rate limiting and auth.\n\n### Installing `kuadrantctl`\nDownload `kuadrantctl` from the `v0.2.0` release artifacts:\n\nhttps://github.com/Kuadrant/kuadrantctl/releases/tag/v0.2.0\n\nDrop the `kuadrantctl` binary somewhere into your $PATH (e.g. `/usr/local/bin/`).\n\nFor this next part of the tutorial, we recommend installing [`yq`](https://github.com/mikefarah/yq) to pretty-print YAML resources.\n\n### Generating Kuadrant resources with `kuadrantctl`\n\nWe'll generate an `AuthPolicy` to implement API key auth, per the `securityScheme` in our OAS spec:\n\n```bash\n# Generate this resource and save:\nkuadrantctl generate kuadrant authpolicy --oas openapi.yaml | yq -P | tee resources/authpolicy.yaml\n\n# Apply this resource to our cluster:\nkubectl --context kind-api-workload-1 apply -f ./resources/authpolicy.yaml\n```\n\nNext we'll generate a `RateLimitPolicy`, to protect our APIs with the limits we have setup in our OAS spec:\n\n```bash\n# Generate this resource and save:\nkuadrantctl generate kuadrant ratelimitpolicy --oas openapi.yaml | yq -P | tee resources/ratelimitpolicy.yaml\n\n# Apply this resource to our cluster:\nkubectl --context kind-api-workload-1 apply -f ./resources/ratelimitpolicy.yaml\n```\n\nLastly, we'll generate a Gateway API `HTTPRoute` to service our APIs:\n\n```bash\n# Generate this resource and save:\nkuadrantctl generate gatewayapi httproute --oas openapi.yaml | yq -P | tee resources/httproute.yaml\n\n# Apply this resource to our cluster, setting the hostname in via the KUADRANT_ZONE_ROOT_DOMAIN env var:\nkustomize build ./resources/ | envsubst | kubectl --context kind-api-workload-1 apply -f-\n```\n\n### Check our applied policies\n\nNavigate to your app's Swagger UI:\n\n```bash\necho https://petstore.$KUADRANT_ZONE_ROOT_DOMAIN/docs/\n```\n\n#### RateLimitPolicy\n\nLet's check that our `RateLimitPolicy` for the `/store/inventory` has been applied and works correctly. Recall, our OAS spec had the following limits applied:\n\n```yaml\nx-kuadrant:\n  ...\n  rate_limit:\n    rates:\n    - limit: 10\n      duration: 10\n      unit: second\n```\nNavigate to the `/store/inventory` API, click `Try it out`, and `Execute`.\n\nYou'll see a response similar to:\n\n```json\n{\n  \"available\": 10,\n  \"pending\": 5,\n  \"sold\": 3\n}\n```\n\nThis API has a rate limit applied, so if you send more than 10 requests in a 10 second window, you will see a `429` HTTP Status code from responses, and a \"Too Many Requests\" message in the response body. Click `Execute` quickly in succession to see your `RateLimitPolicy` in action.\n\n#### AuthPolicy\n\nLet's check that our `AuthPolicy` for the `/store/admin` endpoint has been applied and works correctly. Recall, our OAS spec had the following securitySchemes applied:\n\n```yaml\n  securitySchemes:\n    api_key:\n      type: apiKey\n      name: api_key\n      in: header\n```\n\nNavigate to the `/store/admin` API, click `Try it out`, and `Execute`.\nYou'll get a 401 response.\n\nYou can set a value for the `api_key` header by clicking `Authorize` at the top of the page. Set a value of `secret`.\nThis api key value is stored in the `petstore-api-key` Secret in the `petstore` namespace.\nTry the `/store/admin` endpoint again and you should get a 200 response with the following:\n\n```json\n{\"message\":\"You are an admin!\"}\n```\n\n### Policy Adjustments\n\nRun the Swagger UI editor to explore the OAS spec and make some tweaks:\n\n```bash\ndocker run -p 8080:8080 -v $(pwd):/tmp -e SWAGGER_FILE=/tmp/openapi.yaml swaggerapi/swagger-editor\n```\n\nYou should be able to access the Swagger Editor at [http://localhost:8080](http://localhost:8080).\nOur `/store/inventory` API needs some additonal rate limiting. This is one of our slowest, most expensive services, so we'd like to rate limit it further.\n\nIn your `openapi.yaml`, navigate to the `/store/inventory` endpoint in the `paths` block. Modify the rate_limit block to further restrict the amount of requests this endpoint can serve to 2 requests per 10 seconds:\n\n```yaml\nx-kuadrant:\n  ...\n  rate_limit:\n    rates:\n    - limit: 2\n      duration: 10\n      unit: second\n```\n\nSave your updated spec - `File` \u003e `Save as YAML` \u003e and update your existing `openapi.yaml`. You may need to copy the file from your Downloads folder to the location of the petstore repository.\n\nNext we'll re-generate our `RateLimitPolicy` with `kuadrantctl`:\n\n```bash\n# Generate this resource and save:\nkuadrantctl generate kuadrant ratelimitpolicy --oas openapi.yaml | yq -P | tee resources/ratelimitpolicy.yaml\n\n# Apply this resource to our cluster:\nkubectl --context kind-api-workload-1 apply -f ./resources/ratelimitpolicy.yaml\n```\n\nAt this stage you can optionally check in all the changes to the repo if you forked it.\n\n```bash\n# Optionally add, commit \u0026 push the changes to your fork\ngit add resources\ngit commit -am \"Generated AuthPolicy,RateLimitPolicy \u0026 HTTPRoute\"\ngit push # You may need to set an upstream as well\n```\n\nIn your app's Swagger UI:\n\n```bash\necho https://petstore.$KUADRANT_ZONE_ROOT_DOMAIN/docs/\n```\n\nNavigate to the `/store/inventory` API one more, click `Try it out`, and `Execute`.\n\nYou'll see the effects of our new `RateLimitPolicy` applied. If you now send more than 2 requests in a 10 second window, you'll be rate-limited.\n\n**Note:** :exclamation: It may take a few minutes for the updated RateLimitPolicy to be configured with the modified rate limit.\n\n## (Application developer) Scaling the application\n\nDeploy the petstore to the 2nd cluster:\n\n```bash\nkustomize build ./resources/ | envsubst | kubectl --context kind-api-workload-2 apply -f-\nkubectl --context kind-api-workload-2 apply -f ./resources/authpolicy.yaml\nkubectl --context kind-api-workload-2 apply -f ./resources/ratelimitpolicy.yaml\n```\n\nConfigure the app `REGION` to be `us`:\n\n```bash\nkubectl --context kind-api-workload-2 apply -k ./resources/us-cluster/\n```\n\n## (Platform engineer) Scaling the gateway and traffic management\n\nDeploy the Gateway to the 2nd cluster:\n\n```bash\nkubectl --context kind-api-control-plane patch placement http-gateway --namespace multi-cluster-gateways --type='json' -p='[{\"op\": \"replace\", \"path\": \"/spec/numberOfClusters\", \"value\":2}]'\n```\n\nLabel the 1st cluster as being in the 'EU' region,\nand the 2nd cluster as being in the 'US' region.\nThese labels are used by the DNSPolicy for configuring geo DNS.\n\n```bash\nkubectl --context kind-api-control-plane label managedcluster kind-api-workload-1 kuadrant.io/lb-attribute-geo-code=EU --overwrite\nkubectl --context kind-api-control-plane label managedcluster kind-api-workload-2 kuadrant.io/lb-attribute-geo-code=US --overwrite\n```\n\n## (API consumer) Accessing the API from multiple regions\n\n!!! info\n\n    This section is **optional**. If you'd rather skip this part, you can skip forward to the \"(App developer) API traffic monitoring\" section.\n\n![Geosight Image](images/geosight.png)\n\n### Pre-requisites\n\n- `python3` and `pip3`: these are required for this part of the walkthrough\n\nTo demonstrate traffic management by geographical region, we'll use a tool called 'geosight'. This tool resolves hostnames from different regions, fetches a website from the resulting DNS record address and takes a screenshot. The petstore app has been configured to serve a flag image based on which region it is running in. In the 1st cluster, the EU flag is used. In the 2nd cluster, the US flag is used.\n\nTo install 'geosight', run the following commands:\n\n```bash\ngit clone git@github.com:jasonmadigan/geosight.git \u0026\u0026 cd geosight\npip3 install -r requirements.txt\nplaywright install\n```\n\nThen run it using:\n\n```bash\npython3 app.py\n```\n\nAccess the webapp at [http://127.0.0.1:5001/](http://127.0.0.1:5001/).\nIn the input box, type the address from below and click the `Fetch` button:\n\n```bash\necho https://petstore.$KUADRANT_ZONE_ROOT_DOMAIN/server/details\n```\n\nAfter a moment you should see dns results for different regions, and a corresponding screenshot.\n\nIf you want to experiment with other regions, check out the [Configuration section](https://github.com/jasonmadigan/geosight?tab=readme-ov-file#configuration) for geosight and the [Kuadrant docs](https://docs.kuadrant.io/multicluster-gateway-controller/docs/how-to/multicluster-loadbalanced-dnspolicy/#configuring-cluster-geo-locations) for geo loadbalancing.\n\n## (App developer) API traffic monitoring\n\nTo view the App developer dashboard, the same Grafana will be used from the platform engineer steps above:\n`https://grafana.172.31.0.2.nip.io`\n\nThe most relevant for a app developer is `Stitch: App Developer Dashboard`\nYou should see panels about API's including:\n\n* Request and error rates\n* API summaries\n* API request summaries\n* API duration\n\nAll corresponding to our HTTPRoute coming from our OAS spec\n\n## (Platform Engineer) APIs summary view\n\nNow that the app developer has deployed their app, new metrics and data is now available in the platform engineer dashboard seen in the previous step `https://grafana.172.31.0.2.nip.io`:\n\n* Gateways, routes and policies\n* Constraints \u0026 Violations (there should be no violations present)\n* APIs Summary\n\n## Summary\n\nYou now have a local environment with a reference architecture to design and deploy an API in a kube native way, using Kuadrant and other open source tools.\n\n\n## Cleanup\n\nTo destroy the previously created `kind` clusters, run:\n\n```bash\n./cleanup.sh\n```\n\n!!! info\n\n    DNS records in AWS will remain after cleanup - you can remove these from your zone manually.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkuadrant%2Fapi-quickstart","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkuadrant%2Fapi-quickstart","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkuadrant%2Fapi-quickstart/lists"}