{"id":24117313,"url":"https://github.com/traefik-workshops/traefik-hub-gitops","last_synced_at":"2025-09-18T06:32:11.838Z","repository":{"id":211416732,"uuid":"711843464","full_name":"traefik-workshops/traefik-hub-gitops","owner":"traefik-workshops","description":"Complete demo of Traefik Hub usage with FluxCD","archived":false,"fork":false,"pushed_at":"2024-09-16T06:40:48.000Z","size":577,"stargazers_count":1,"open_issues_count":0,"forks_count":9,"subscribers_count":11,"default_branch":"master","last_synced_at":"2024-09-16T08:05:36.101Z","etag":null,"topics":["api","api-gateway","api-management","ingress","kubernetes","openapi","openapi3","swagger","traefik-hub"],"latest_commit_sha":null,"homepage":"https://doc.traefik.io/traefik-hub","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/traefik-workshops.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2023-10-30T09:37:00.000Z","updated_at":"2024-09-16T06:40:52.000Z","dependencies_parsed_at":"2024-01-31T13:30:23.015Z","dependency_job_id":"9610c333-a380-4eca-abec-125f1693cc0d","html_url":"https://github.com/traefik-workshops/traefik-hub-gitops","commit_stats":null,"previous_names":["traefik-workshops/traefik-hub-gitops"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/traefik-workshops%2Ftraefik-hub-gitops","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/traefik-workshops%2Ftraefik-hub-gitops/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/traefik-workshops%2Ftraefik-hub-gitops/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/traefik-workshops%2Ftraefik-hub-gitops/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/traefik-workshops","download_url":"https://codeload.github.com/traefik-workshops/traefik-hub-gitops/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":233456070,"owners_count":18678963,"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":["api","api-gateway","api-management","ingress","kubernetes","openapi","openapi3","swagger","traefik-hub"],"created_at":"2025-01-11T07:39:07.458Z","updated_at":"2025-09-18T06:32:06.477Z","avatar_url":"https://github.com/traefik-workshops.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cbr/\u003e\n\n\u003e Since the end of May 2024, Traefik Hub tutorials has moved to [traefik/hub](https://github.com/traefik/hub) repository\n\n\u003cdiv align=\"center\" style=\"margin: 30px;\"\u003e\n\u003ca href=\"https://hub.traefik.io/\"\u003e\n  \u003cimg src=\"https://doc.traefik.io/traefik-hub/img/hub-logo-light.svg\" style=\"width:250px;\" align=\"center\" /\u003e\n\u003c/a\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\n\u003cdiv align=\"center\"\u003e\n    \u003ca href=\"https://hub.traefik.io\"\u003eLog In\u003c/a\u003e |\n    \u003ca href=\"https://doc.traefik.io/traefik-hub/\"\u003eDocumentation\u003c/a\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\n\u003cbr /\u003e\n\n\u003cdiv align=\"center\"\u003e\u003cstrong\u003eTraefik Hub - GitOps Complete Tutorial\u003c/strong\u003e\n\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003c/div\u003e\n\n\u003cdiv align=\"center\"\u003eWelcome to this tutorial!\u003c/div\u003e\n\n# About\n\nThis tutorial details how to deploy locally a Kubernetes cluster, with GitOps and observability components.\n\n# Prerequisites\n\nIf you'd like to follow along with this tutorial on your own machine, you'll need a few things first:\n\n1. [kubectl](https://github.com/kubernetes/kubectl) command-line tool installed and configured to access the cluster\n2. [gh](https://cli.github.com/) command-line tool installed and configured with your account\n3. [Flux CD](https://fluxcd.io/flux/cmd/) command-line tool installed.\n4. A Kubernetes cluster running.\n\nIn this tutorial, you'll use [kind](https://kind.sigs.k8s.io). You may also use alternatives like [k3d](https://k3d.io/), cloud providers, or others.\n\nkind requires some configuration to use an IngressController on localhost, see the following example:\n\n```shell\ncat kind.config\n```\n\n```yaml\nkind: Cluster\napiVersion: kind.x-k8s.io/v1alpha4\nname: traefik-hub-gitops\nnodes:\n- role: control-plane\n  extraPortMappings:\n  - containerPort: 30000\n    hostPort: 80\n    protocol: TCP\n  - containerPort: 30001\n    hostPort: 443\n    protocol: TCP\n```\n\n1. Clone this GitHub repository:\n\n```shell\ngit clone https://github.com/traefik-workshops/traefik-hub-gitops.git\ncd traefik-hub-gitops\n```\n\n2. Create the Kubernetes cluster:\n\n**Using kind**\n\nCreate the cluster:\n\n```shell\nkind create cluster --config=kind.config\nkubectl cluster-info\nkubectl wait --for=condition=ready nodes traefik-hub-gitops-control-plane\n```\n\nAdd a load balancer (LB) to this Kubernetes cluster:\n\n```shell\nkubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.11/config/manifests/metallb-native.yaml\nkubectl wait --namespace metallb-system --for=condition=ready pod --selector=app=metallb --timeout=90s\nkubectl apply -f clusters/kind/metallb-config.yaml\n```\n\n**Using k3d**\n\n```shell\nk3d cluster create traefik-hub-gitops --port 80:80@loadbalancer --port 443:443@loadbalancer --port 8000:8000@loadbalancer --k3s-arg \"--disable=traefik@server:0\"\n```\n\n# Fork the repo and deploy Flux CD\n\nFlux needs to be able to commit on the repository, this tutorial can only work on a fork that *you* own.\nYou will also need a [GitHub personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) (PAT) with administration permissions.\n\n```shell\ngh repo fork --remote\nkubectl apply -f clusters/kind/flux-system/gotk-components.yaml\n```\n\n# Configure Traefik Hub\n\nLogin to the [Traefik Hub UI](https://hub.traefik.io), open the page to [generate a new agent](https://hub.traefik.io/agents/new).\n**Do not install the agent, but copy your token.**\n\nNow, open a terminal and run these commands to create the secret needed for Traefik Hub.\n\n```shell\nexport TRAEFIK_HUB_TOKEN=xxx\nkubectl create namespace traefik-hub\nkubectl create secret generic hub-agent-token --namespace traefik-hub --from-literal=token=${TRAEFIK_HUB_TOKEN}\n```\n\n# Deploy the stack on the cluster\n\nThen, you can configure flux and launch it on the fork.\nYou'll need to create a [Personal Access Token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-personal-access-token-classic)(PAT) with repo access on your fork.\n\nFirst, export your GitHub username and your newly created PAT into a variable.\n\n```shell\nexport GITHUB_ACCOUNT=xxx\nexport GITHUB_TOKEN=yyy\n```\n\nSecond, configure Flux CD for your fork of this tutorial.\n\n```shell\nflux create secret git git-auth  --url=\"https://github.com/${GITHUB_ACCOUNT}/traefik-hub-gitops\" --namespace=flux-system -u git -p \"${GITHUB_TOKEN}\"\n```\n\nThird, adjust the repository on Flux to use your fork.\n\n```shell\nsed -i -e \"s/traefik-workshops/${GITHUB_ACCOUNT}/g\" clusters/kind/flux-system/gotk-sync.yaml\ngit commit -m \"feat: GitOps on my fork\" clusters/kind/flux-system/gotk-sync.yaml\ngit push origin\n```\n\nIn the next step, deploy the repository.\n\n```shell\nkubectl apply -f clusters/kind/flux-system/gotk-sync.yaml\n```\n\nThis will start the [Kustomization](https://fluxcd.io/flux/components/kustomize/kustomizations/).\nFlux will now sync, validate and deploy all components.\n\nThis process will take several minutes.\n\nYou can track the process from the CLI.\n\n```shell\nflux get ks\n```\n\n![Kustomizations are ready](./images/kustomizations-ready.png)\n\nIf any of the kustomizations are stuck just run the:\n\n```bash\nkubectl delete mutatingwebhookconfigurations hub-api\nkubectl delete mutatingwebhookconfigurations hub-acp\n```\n\n# Configure traffic generation\n\nTo generate traffic, create two users, an `admin` and a `support` user and their groups.\n\nThe `admin` user needs to be part of the `admin` group and the `support` user needs to be part of the `support` group.\n\n\u003cdetails\u003e\n  \u003csummary\u003eTraefik Hub UI\u003c/summary\u003e\n\nCreate the `admin` user in the Traefik Hub UI:\n\n![Create user admin](./images/create-user-admin.png)\n\nCreate the `support` user:\n\n![Create user support](./images/create-user-support.png)\n\n\u003c/details\u003e\n\nWhen the Kustomization is **ready**, you can open API Portal, following URL available in the UI or in the CRD:\n\n```shell\nkubectl get apiportal -n apps\n```\n\nLog in to the API Portal:\n\n![API Portal Login](./images/api-portal-login.png)\n\nNow, create API tokens for both users.\n\n![Create API Token](./images/create-api-token.png)\n\nCreate a [Kubernetes secret](https://kubernetes.io/docs/concepts/configuration/secret/) containing the tokens to enable the traffic app to generate load:\n\n```shell\nexport ADMIN_TOKEN=\"xxx\"\nexport SUPPORT_TOKEN=\"yyy\"\nkubectl create secret generic tokens -n traffic --from-literal=admin=\"${ADMIN_TOKEN}\" --from-literal=support=\"${SUPPORT_TOKEN}\"\n```\n\n# Use observability stack\n\nGrafana is accessible on http://grafana.docker.localhost\n\nPrometheus is on http://prometheus.docker.localhost\n\nDefault credentials are login: admin and password: admin.\n\nBy clicking on the left menu, you can access all dashboards:\n\n![Grafana Dashboards](./images/grafana-dashboards.png)\n\n## Enable event correlation\n\n**Flux events**:\n\n- Add a new Grafana service account with a new key at http://grafana.docker.localhost/org/serviceaccounts\n- Create a new Service Account with `Editor` role.\n- Add a Service account token and copy it to (starting with `glsa_`) to the `apps/base/monitoring/flux-grafana.yaml` file.\n- **NOTE**: You will need to apply or commit this to the repo, if it is a public repo beware that the secret will be public.\n\n```shell\nexport GRAFANA_TOKEN=\"xxx\"\nsed -i -e \"s/token:\\(.*\\)/token: \\\"\"${GRAFANA_TOKEN}\"\\\"/g\" apps/base/monitoring/flux-grafana.yaml\n```\n\nNow, Flux can create annotations of reconciliation events in the dashboards.\n\n**GitHub PR merges**: Add a new Grafana connection (GitHub data source) at http://grafana.docker.localhost/connections/datasources/grafana-github-datasource\nYou must add a Personal Access Token (PAT) to GitHub at https://github.com/settings/tokens/new, as explained in the Grafana connection creation wizard.\nWhen configured, edit the dashboards to add new annotations using the GitHub data source:\n- Show in: All panels\n- Query type: Pull Requests\n- Owner / Repository: your user and the repo name of the fork\n- Query: leave it empty\n- Time Field: MergedAt\n- Annotations:\n  - Time field: `merged_at (time)`\n  - Title: `title (string)`\n  - Text: `url (string)`\n  - End time + tags + id: leave them empty\n\n# Clean up\n\nEverything is installed in Kubernetes.\nYou can delete the Kubernetes cluster with the following command:\n\n```shell\n# kind\nkind delete cluster --name traefik-hub-gitops\n```\n\n```shell\n# k3d\nk3d delete cluster traefik-hub-gitops\n```\n\nYou may also want to delete the agent in Traefik Hub UI.\n\n## License\n\nThe content in this repository is licensed under the [Apache 2 License](https://www.apache.org/licenses/LICENSE-2.0 \"Link to Apache 2 license\").\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftraefik-workshops%2Ftraefik-hub-gitops","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftraefik-workshops%2Ftraefik-hub-gitops","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftraefik-workshops%2Ftraefik-hub-gitops/lists"}