{"id":13702745,"url":"https://github.com/janosmiko/hetzner-k3s","last_synced_at":"2026-01-16T15:49:18.949Z","repository":{"id":57764842,"uuid":"527556564","full_name":"janosmiko/hetzner-k3s","owner":"janosmiko","description":"This is a CLI tool to quickly create and manage Kubernetes clusters in Hetzner Cloud using the lightweight Kubernetes distribution k3s from Rancher.","archived":false,"fork":false,"pushed_at":"2023-11-10T14:44:14.000Z","size":119,"stargazers_count":31,"open_issues_count":1,"forks_count":4,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-11-13T10:37:45.070Z","etag":null,"topics":["autoscaling","golang","hcloud","hetzner","hetzner-cloud","kubernetes","kubernetes-cluster"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/janosmiko.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/funding.yml","license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null},"funding":{"github":"janosmiko"}},"created_at":"2022-08-22T12:33:36.000Z","updated_at":"2024-11-08T09:10:46.000Z","dependencies_parsed_at":"2023-11-10T15:50:43.022Z","dependency_job_id":null,"html_url":"https://github.com/janosmiko/hetzner-k3s","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janosmiko%2Fhetzner-k3s","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janosmiko%2Fhetzner-k3s/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janosmiko%2Fhetzner-k3s/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janosmiko%2Fhetzner-k3s/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/janosmiko","download_url":"https://codeload.github.com/janosmiko/hetzner-k3s/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252451949,"owners_count":21750008,"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":["autoscaling","golang","hcloud","hetzner","hetzner-cloud","kubernetes","kubernetes-cluster"],"created_at":"2024-08-02T21:00:41.793Z","updated_at":"2026-01-16T15:49:18.923Z","avatar_url":"https://github.com/janosmiko.png","language":"Go","funding_links":["https://github.com/sponsors/janosmiko"],"categories":["Tools"],"sub_categories":["Rust"],"readme":"# Create production grade Kubernetes clusters in Hetzner Cloud in a couple of minutes or less\n\n[![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=janosmiko_hetzner-k3s\u0026metric=ncloc)](https://sonarcloud.io/dashboard?id=janosmiko_hetzner-k3s)\n[![Go Report Card](https://goreportcard.com/badge/github.com/rewardenv/reward)](https://goreportcard.com/report/github.com/janosmiko/hetzner-k3s)\n[![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=janosmiko_hetzner-k3s\u0026metric=security_rating)](https://sonarcloud.io/dashboard?id=janosmiko_hetzner-k3s)\n[![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=janosmiko_hetzner-k3s\u0026metric=vulnerabilities)](https://sonarcloud.io/dashboard?id=janosmiko_hetzner-k3s)\n[![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=janosmiko_hetzner-k3s\u0026metric=sqale_rating)](https://sonarcloud.io/dashboard?id=janosmiko_hetzner-k3s)\n\nThis is a CLI tool to quickly create and manage Kubernetes clusters in [Hetzner Cloud](https://www.hetzner.com/cloud)\nusing the lightweight Kubernetes distribution [k3s](https://k3s.io/) from [Rancher](https://rancher.com/).\n\nHetzner Cloud is an awesome cloud provider which offers a truly great service with the best performance/cost ratio in\nthe market. With Hetzner's Cloud Controller Manager and CSI driver you can provision load balancers and persistent\nvolumes very easily.\n\nk3s is my favorite Kubernetes distribution now because it uses much less memory and CPU, leaving more resources to\nworkloads. It is also super quick to deploy because it's a single binary.\n\nUsing this tool, creating a highly available k3s cluster with 3 masters for the control plane and worker nodes (with\nautoscaling support) takes about **a couple of minutes** only. This includes\n\n- creating the infra resources (servers, private network, firewall, load balancer for the API server for HA clusters)\n- deploying k3s to the nodes\n- installing the [Hetzner Cloud Controller Manager](https://github.com/hetznercloud/hcloud-cloud-controller-manager) to\n  provision load balancers right away\n- installing the [Hetzner CSI Driver](https://github.com/hetznercloud/csi-driver) to provision persistent volumes using\n  Hetzner's block storage\n- installing the [Rancher System Upgrade Controller](https://github.com/rancher/system-upgrade-controller) to make\n  upgrades to a newer version of k3s easy and quick\n- installing the [Kubernetes Cluster Autoscaler](https://github.com/kubernetes/autoscaler) to make the cluster\n  autoscaling possible\n\nSee roadmap [here](https://github.com/users/janosmiko/projects/1) for the features planned or in progress.\n\nAlso see this [wiki page](https://github.com/vitobotta/hetzner-k3s/wiki/Tutorial:---Setting-up-a-cluster) for a tutorial\non how to set up a cluster with the most common setup to get you started.\n\n## Requirements\n\nAll that is needed to use this tool is\n\n- an Hetzner Cloud account\n- an Hetzner Cloud token: for this you need to create a project from the cloud console, and then an API token with **\n  both read and write permissions** (sidebar \u003e Security \u003e API Tokens); you will see the token only once, so ensure you\n  take note of it somewhere safe\n- (optional) Github token: if you reach the rate limiting to query the available K3s releases\n\n## Installation\n\n### Dependency\n\nIf you use these binaries please make sure to install `kubectl` in your PATH before using `hetzner-k3s`.\n\n### MacOS\n\n```bash\n$ brew install janosmiko/tap/hetzner-k3s\n```\n\n#### Binary Download\n\n```bash\n$ curl -fsSLO \"https://github.com/janosmiko/hetzner-k3s/releases/latest/download/hetzner-k3s_`uname -s`_`uname -m`.tar.gz\"\n$ tar -zxvf \"hetzner-k3s_`uname -s`_`uname -m`.tar.gz\" -C /usr/local/bin/\n$ rm -f \"hetzner-k3s_`uname -s`_`uname -m`.tar.gz\"\n$ chmod +x /usr/local/bin/hetzner-k3s\n```\n\n### Linux\n\n#### Ubuntu\n\n```\n$ curl -fsSLO \"https://github.com/janosmiko/hetzner-k3s/releases/latest/download/hetzner-k3s_`uname -s`_`uname -m`.deb\"\n$ sudo dpkg -i \"hetzner-k3s_`uname -s`_`uname -m`.deb\"\n```\n\n##### CentOS and Fedora\n\n```\n$ yum install -y \"https://github.com/janosmiko/hetzner-k3s/releases/latest/download/hetzner-k3s_`uname -s`_`uname -m`.rpm\"\n```\n\n##### Binary Download\n\n```\n$ curl -fsSLO \"https://github.com/janosmiko/hetzner-k3s/releases/latest/download/hetzner-k3s_`uname -s`_`uname -m`.tar.gz\"\n$ tar -zxvf \"hetzner-k3s_`uname -s`_`uname -m`.tar.gz\" -C /usr/local/bin/\n$ rm -f \"hetzner-k3s_`uname -s`_`uname -m`.tar.gz\"\n$ chmod +x /usr/local/bin/hetzner-k3s\n```\n\n\n```bash\n$ curl -fsSLO \"https://github.com/janosmiko/hetzner-k3s/releases/latest/download/hetzner-k3s-`uname -s`-`uname -m`.tar.gz\"\n$ tar -zxvf \"hetzner-k3s-`uname -s`-`uname -m`.tar.gz\" hetzner-k3s\n$ sudo mv hetzner-k3s /usr/local/bin/hetzner-k3s\n```\n\n### Windows\n\nDownload and extract the [latest](https://github.com/janosmiko/hetzner-k3s/releases/latest/) binary to your PATH.\n\n### With Docker\n\nAlternatively, if you don't want to install the binary but have Docker installed, you can use a container. Run the\nfollowing from inside the directory where you have the config file for the cluster (described in the next section):\n\n```bash\ndocker run --rm -it \\\n  -v ${PWD}:/cluster \\\n  -v ${HOME}/.ssh:/tmp/.ssh \\\n  janosmiko/hetzner-k3s:v0.1.10 \\\n  create-cluster \\\n  --config-file /cluster/test.yaml\n```\n\nReplace `test.yaml` with the name of your config file.\n\n## Creating a cluster\n\nThe tool requires a simple configuration file in order to create/upgrade/delete clusters, in the YAML format like in the\nexample below:\n\n```yaml\n---\nhetzner_token: \u003cyour token\u003e\n#github_token: \u003cyour token\u003e # Optional\ncluster_name: test\nkubeconfig_path: \"/cluster/kubeconfig\"\nk3s_version: v1.21.3+k3s1\npublic_ssh_key_path: \"/root/.ssh/id_rsa.pub\"\nprivate_ssh_key_path: \"/root/.ssh/id_rsa\"\n#\n# Using these fields you can apply various firewall restrictions for SSH and Kubernetes API access.\n# Defaults to ALLOW ANY IP address (0.0.0.0/0)\n#\n#ssh_allowed_networks:\n#  - 0.0.0.0/0\n#api_allowed_networks:\n#  - 0.0.0.0/0\n\nverify_host_key: false\nlocation: nbg1\nschedule_workloads_on_masters: false\nmasters:\n  instance_type: cpx21\n  instance_count: 3\n#\n# Define static worker pools\n#\nworker_node_pools:\n  - name: small\n    instance_type: cpx21\n    instance_count: 4\n  - name: big\n    instance_type: cpx31\n    instance_count: 2\n#\n# Cluster Autoscaler is automatically enabled when any autoscaling_node_pools are defined. \n#\nautoscaling_node_pools:\n  - name: small\n    instance_type: cx41\n    instance_min: 3\n    instance_max: 5\n  - name: big\n    instance_type: cpx51\n    instance_max: 10\n#\n# Pass additional parameters to the Cluster Autoscaler.\n# https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/FAQ.md#what-are-the-parameters-to-ca\n#\n#cluster_autoscaler_args:\n#  - --scan-interval=2s\n#  - --scale-down-delay-after-add=1h0s\n#  - --scale-down-unneeded-time=1h0s\n#  - --scale-down-unready-time=10m0s\n#  - --scale-down-utilization-threshold=0.5\n#  - --ignore-daemonsets-utilization\n#  - --ignore-mirror-pods-utilization\n#  - --v=4\n\n# Specify the version of the Cluster Autoscaler to use.\n#cluster_autoscaler_version: \"v1.24.1\"\n\nadditional_packages:\n  - somepackage\npost_create_commands:\n  - apt update\n  - apt upgrade -y\n  - apt autoremove -y\n  - shutdown -r now\nenable_encryption: true\n#\n# Configure various arguments for kubernetes components\n#\n#kube_api_server_args:\n#  - arg1\n#  - ...\n#kube_scheduler_args:\n#  - arg1\n#  - ...\n#kube_controller_manager_args:\n#  - arg1\n#  - ...\n#kube_cloud_controller_manager_args:\n#  - arg1\n#  - ...\n#kubelet_args:\n#  - arg1\n#  - ...\n#kube_proxy_args:\n#  - arg1\n#  - ...\n#\n# Specify if you want to use an existing network, otherwise one will be created for this cluster.\n# existing_network: \u003cnetwork-name\u003e or \u003cnetwork-id\u003e\n# This setting allows you to override the default nameservers (1.1.1.1 and 1.0.0.1)\n# \n#default_nameservers:\n#  - 8.8.8.8\n#  - 1.1.1.1\n#  - 1.0.0.1\n#\n# Enabling this will blacklist longhorn devices in multipathd config (required for longhorn storage)\n# https://longhorn.io/kb/troubleshooting-volume-with-multipath/\n#\n#fix_multipath: true\n#\n# Running the create-cluster command always overrides the default Kubernetes Storage Class to hcloud-volume.\n# By disabling this setting you can disable this behaviour leaving the default Kubernetes Storage Class as it is.\n#\n#hcloud_volume_is_default_storage_class: false\n#\n# Hcloud CSI Controller Deployment is scheduled on workers by default. If you enable this setting, the deployment will\n# be upgraded to run on \n#\n#schedule_csi_controller_on_master: false\n#\n```\n\nIt should hopefully be self-explanatory; you can run `hetzner-k3s releases` to see a list of the available releases from\nthe most recent to the oldest available. You can also filter the list using `hetzner-k3s releases --filter v1.24` and\nfetch the latest tag using `hetzner-k3s releases --latest` (be careful: this can show release candidate releases too).\nYou can also combine them eg: `hetzner-k3s releases --filter v1.21 --latest`.\n\nIf you are using Docker, then set `kubeconfig_path` to `/cluster/kubeconfig` so that the kubeconfig is created in the\nsame directory where your config file is. Also set the config file path to `/cluster/\u003cfilename\u003e`.\n\nIf you don't want to specify the Hetzner token in the config file (for example if you want to use the tool with CI),\nthen you can use the `HCLOUD_TOKEN` environment variable instead, which has predecence. This also works for any possible\nconfiguration variable.\n\n**Important**: The tool assignes the label `cluster` to each server it creates, with the cluster name you specify in the\nconfig file, as the value. So please ensure you don't create unrelated servers in the same project having\nthe label `cluster=\u003ccluster name\u003e`, because otherwise they will be deleted if you delete the cluster. I recommend you\ncreate a separate Hetzner project for each cluster, see note at the end of this README for more details.\n\nThe Servers which are created by the Cluster Autoscaler use a different label `hcloud/node-group`.\n\nIf you set `masters.instance_count` to 1 then the tool will create a non highly available control plane; for production\nclusters you may want to set it to a number greater than 1. This number must be odd to avoid split brain issues with\netcd and the recommended number is 3.\n\nYou can specify any number of worker node pools for example to have mixed nodes with different specs for different\nworkloads.\n\nAt the moment Hetzner Cloud has four locations: two in Germany (`nbg1`, Nuremberg and `fsn1`, Falkenstein), one in\nFinland (`hel1`, Helsinki) and two in the USA (`ash`, Ashburn, Virginia and `hil`, Hillsboro, Oregon). Please note that the Ashburn, Virginia\nlocation has just been announced and it's limited to AMD instances for now.\n\nFor the available instance types and their specs, either check from inside a project when adding a server manually or\nrun the following with your Hetzner token:\n\n```bash\ncurl \\\n\t-H \"Authorization: Bearer $API_TOKEN\" \\\n\t'https://api.hetzner.cloud/v1/server_types'\n```\n\nBy default, the image in use is Ubuntu 20.04, but you can specify an image to use with the `image` config option. This\nmakes it also possible to use a snapshot that you have already created from and existing server (for example to\npreinstall some tools). If you want to use a custom snapshot you'll need to specify the **ID** of the snapshot/image,\nnot the description you gave when you created the template server. To find the ID of your custom image/snapshot, run:\n\n```bash\ncurl \\\n\t-H \"Authorization: Bearer $API_TOKEN\" \\\n\t'https://api.hetzner.cloud/v1/images'\n```\n\nNotes:\n\n- if you use a custom image, the creation of the servers may take longer than when using the default image\n- the option `verify_host_key` is by default set to `false` to disable host key verification. This is because sometimes\n  when creating new servers, Hetzner may assign IP addresses that were previously used by other servers you owned in the\n  past. Therefore the host key verification would fail. If you set this option to `true` and this happens, the tool\n  won't be able to continue creating the cluster until you resolve the issue with one of the suggestions it will give\n  you\n- the setting `api_allowed_networks` allows specifying which networks can access the Kubernetes API, but this only works\n  with single master clusters currently. Multi-master HA clusters require a load balancer for the API, but load\n  balancers are not yet covered by Hetzner's firewalls.\n\nFinally, to create the cluster run:\n\n```bash\nhetzner-k3s create-cluster --config-file cluster_config.yaml\n```\n\nThis will take a couple of minutes or less depending on the number of masters and worker nodes.\n\nIf you are creating an HA cluster and see the following in the output you can safely ignore it - it happens when\nadditional masters are joining the first one:\n\n```\nJob for k3s.service failed because the control process exited with error code.\nSee \"systemctl status k3s.service\" and \"journalctl -xe\" for details.\n```\n\n### Idempotency\n\nThe `create-cluster` command can be run any number of times with the same configuration without causing any issue, since\nthe process is idempotent. This means that if for some reason the create process gets stuck or throws errors (for\nexample if the Hetzner API is unavailable or there are timeouts etc), you can just stop the current command, and re-run\nit with the same configuration to continue from where it left.\n\n### Adding nodes\n\nTo add one or more nodes to a node pool, just change the instance count in the configuration file for that node pool and\nre-run the create command.\n\n### Scaling down a node pool\n\nTo make a node pool smaller:\n\n- decrease the instance count for the node pool in the configuration file so that those extra nodes are not recreated in\n  the future\n- delete the nodes from Kubernetes (`kubectl delete node \u003cname\u003e`)\n- delete the instances from the cloud console (make sure you delete the correct ones :p)\n\nIn a future relese I will add some automation for the cleanup.\n\n### Replacing a problematic node\n\n- delete the node from Kubernetes (`kubectl delete node \u003cname\u003e`)\n- delete the correct instance from the cloud console\n- re-run the create script. This will re-create the missing node and have it join to the cluster\n\n### Converting a non-HA cluster to HA\n\nIt's easy to convert a non-HA with a single master cluster to HA with multiple masters. Just change the masters instance\ncount and re-run the create command. This will create a load balancer for the API server and update the kubeconfig so\nthat all the API requests go through the load balancer.\n\n## Upgrading to a new version of k3s\n\nIf it's the first time you upgrade the cluster, all you need to do to upgrade it to a newer version of k3s is run the\nfollowing command:\n\n```bash\nhetzner-k3s upgrade-cluster --config-file cluster_config.yaml\n```\n\nSo you just need to specify the new k3s version as an additional parameter and the configuration file will be updated\nwith the new version automatically during the upgrade. To see the list of available k3s releases run the\ncommand `hetzner-k3s releases`.\n\nNote that the API server will briefly be unavailable during the upgrade of the controlplane.\n\nTo check the upgrade progress, run `watch kubectl get nodes -owide`. You will see the masters being upgraded one per\ntime, followed by the worker nodes.\n\n### What to do if the upgrade doesn't go smoothly\n\nIf the upgrade gets stuck for some reason, or it doesn't upgrade all the nodes:\n\n1. Clean up the existing upgrade plans and jobs, and restart the upgrade controller\n\n```bash\nkubectl -n system-upgrade delete job --all\nkubectl -n system-upgrade delete plan --all\n\nkubectl label node --all plan.upgrade.cattle.io/k3s-server- plan.upgrade.cattle.io/k3s-agent-\n\nkubectl -n system-upgrade rollout restart deployment system-upgrade-controller\nkubectl -n system-upgrade rollout status deployment system-upgrade-controller\n```\n\nI recommend running the above commands also when upgrading a cluster that has already been upgraded at least once\npreviously, since the upgrade leaves some stuff behind that needs to be cleaned up.\n\n2. Re-run the `upgrade-cluster` command with an additional parameter.\n\nI have noticed that sometimes I need to re-run the upgrade command a couple of times to complete an upgrade\nsuccessfully. Must be some bug in the system upgrade controller but I haven't investigated further.\n\nYou can also check the logs of the system upgrade controller's pod:\n\n```bash\nkubectl -n system-upgrade \\\n  logs -f $(kubectl -n system-upgrade get pod -l pod-template-hash -o jsonpath=\"{.items[0].metadata.name}\")\n```\n\nA final note about upgrades is that if for some reason the upgrade gets stuck after upgrading the masters and before\nupgrading the worker nodes, just cleaning up the resources as described above might not be enough. In that case also try\nrunning the following to tell the upgrade job for the workers that the masters have already been upgraded, so the\nupgrade can continue for the workers:\n\n```bash\nkubectl label node \u003cmaster1\u003e \u003cmaster2\u003e \u003cmaster2\u003e plan.upgrade.cattle.io/k3s-server=upgraded\n```\n\n## Upgrading the OS on nodes\n\n- consider adding a temporary node during the process if you don't have enough spare capacity in the cluster\n- drain one node\n- update etc\n- reboot\n- uncordon\n- proceed with the next node\n\n## Deleting a cluster\n\nTo delete a cluster, running\n\n```bash\nhetzner-k3s delete-cluster --config-file cluster_config.yaml\n```\n\nThis will delete all the resources in the Hetzner Cloud project for the cluster being deleted.\n\n## Additional info\n\n### Load balancers\n\nOnce the cluster is ready, you can already provision services of type LoadBalancer for your workloads (such as the Nginx\ningress controller for example) thanks to the Hetzner Cloud Controller Manager that is installed automatically.\n\nThere are some annotations that you can add to your services to configure the load balancers. I personally use the\nfollowing:\n\n```yaml\n  service:\n    annotations:\n      load-balancer.hetzner.cloud/hostname: \u003ca valid fqdn\u003e\n      load-balancer.hetzner.cloud/http-redirect-https: 'false'\n      load-balancer.hetzner.cloud/location: nbg1\n      load-balancer.hetzner.cloud/name: \u003clb name\u003e\n      load-balancer.hetzner.cloud/uses-proxyprotocol: 'true'\n      load-balancer.hetzner.cloud/use-private-ip: \"true\"\n```\n\nI set `load-balancer.hetzner.cloud/hostname` to a valid hostname that I configure (after creating the load balancer)\nwith the IP of the load balancer; I use this together with the\nannotation `load-balancer.hetzner.cloud/uses-proxyprotocol: 'true'` to enable the proxy protocol. Reason: I enable the\nproxy protocol on the load balancers so that my ingress controller and applications can \"see\" the real IP address of the\nclient. However when this is enabled, there is a problem where [cert-manager](https://cert-manager.io/docs/) fails\nhttp01 challenges; you can find an explanation of why [here](https://github.com/compumike/hairpin-proxy) but the easy\nfix provided by some providers - including Hetzner - is to configure the load balancer so that it uses a hostname\ninstead of an IP. Again, read the explanation for the reason but if you care about seeing the actual IP of the client\nthen I recommend you use these two annotations.\n\nThe annotation `load-balancer.hetzner.cloud/use-private-ip: \"true\"` ensures that the communication between the load\nbalancer and the nodes happens through the private network, so we don't have to open any ports on the nodes (other than\nthe port 6443 for the Kubernetes API server).\n\nThe other annotations should be self explanatory. You can find a list of the available\nannotations [here](https://pkg.go.dev/github.com/hetznercloud/hcloud-cloud-controller-manager/internal/annotation).\n\n## Persistent volumes\n\nOnce the cluster is ready you can create persistent volumes out of the box with the default storage\nclass `hcloud-volumes`, since the Hetzner CSI driver is installed automatically. This will use Hetzner's block storage (\nbased on Ceph so it's replicated and highly available) for your persistent volumes. Note that the minimum size of a\nvolume is 10Gi. If you specify a smaller size for a volume, the volume will be created with a capacity of 10Gi anyway.\n\n## Keeping a project per cluster\n\nI recommend that you create a separate Hetzner project for each cluster, because otherwise multiple clusters will\nattempt to create overlapping routes. I will make the pod cidr configurable in the future to avoid this, but I still\nrecommend keeping clusters separated from each other. This way, if you want to delete a cluster with all the resources\ncreated for it, you can just delete the project.\n\n## Contributing and support\n\nPlease create a PR if you want to propose any changes, or open an issue if you are having trouble with the tool - I will\ndo my best to help if I can.\n\n## License\n\nThe project is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).\n\n## Code of Conduct\n\nEveryone interacting in the hetzner-k3s project's codebases, issue trackers, chat rooms and mailing lists is expected to\nfollow the [code of conduct](https://github.com/janosmiko/hetzner-k3s/blob/main/CODE_OF_CONDUCT.md).\n\n## Acknowledgement\n\nThis project was inspired by the awesome [project](https://github.com/vitobotta/hetzner-k3s)\nby [Vito Botta](https://github.com/vitobotta).\n\n## Stargazers over time\n\n[![Stargazers over time](https://starchart.cc/janosmiko/hetzner-k3s.svg)](https://starchart.cc/janosmiko/hetzner-k3s)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjanosmiko%2Fhetzner-k3s","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjanosmiko%2Fhetzner-k3s","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjanosmiko%2Fhetzner-k3s/lists"}