-
-
Notifications
You must be signed in to change notification settings - Fork 401
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature: allow the use of private networks #1567
base: master
Are you sure you want to change the base?
Feature: allow the use of private networks #1567
Conversation
15e7571
to
e187c93
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm super excited for this feature. So thank you very much for putting effort in this!
You mentioned this was the first time you used terraform... You did super well!
Welcome to Terraform world! :D
I attempted to switch to this implementation in an existing cookbook without making any other change to the kube.tf file. I’ve posted the current configuration here. However, I encountered several instances of the following error:
Maybe is it expecting to always find the network referenced as an input? If I have some time later today, I’ll try to debug the issue and add more info |
@nicolaracco I confirm that the network should always be defined. It must be created before your cluster, because you have to be connected to this network through a non-k8s server. |
@mysticaltech do you have an opinion on this PR ? 🙏 |
@xavierleune Thanks for this, will review it tonight |
Hey, any updates? |
Tested this today (along with NAT + Wireguard) and was able to successfully deploy a cluster with public ips disabled for the nodes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good! Will merge and try it before releasing.
@xavierleune Here's my test deploy, the one I usually use for everything. Please make sure it deploys, this is important. locals {
# You have the choice of setting your Hetzner API token here or define the TF_VAR_hcloud_token env
# within your shell, such as such: export TF_VAR_hcloud_token=xxxxxxxxxxx
# If you choose to define it in the shell, this can be left as is.
# Your Hetzner token can be found in your Project > Security > API Token (Read & Write is required).
hcloud_token = "xxxxxx"
}
module "kube-hetzner" {
providers = {
hcloud = hcloud
}
hcloud_token = var.hcloud_token != "" ? var.hcloud_token : local.hcloud_token
source = "../kube-hetzner"
cluster_name = "test12"
initial_k3s_channel = "v1.30"
ssh_public_key = file("/home/karim/.ssh/id_ed25519.pub")
ssh_private_key = file("/home/karim/.ssh/id_ed25519")
network_region = "eu-central"
control_plane_nodepools = [
{
name = "control-plane",
server_type = "cx22",
location = "fsn1",
labels = [],
taints = [],
count = 1
}
]
agent_nodepools = [
{
name = "agent-small",
server_type = "cx22",
location = "fsn1",
labels = [],
taints = [],
count = 1
}
]
autoscaler_nodepools = [
{
name = "autoscaled-small"
server_type = "cx22",
location = "fsn1",
min_nodes = 1
max_nodes = 2
}
]
load_balancer_type = "lb11"
load_balancer_location = "fsn1"
}
provider "hcloud" {
token = var.hcloud_token != "" ? var.hcloud_token : local.hcloud_token
}
terraform {
required_version = ">= 1.5.0"
required_providers {
hcloud = {
source = "hetznercloud/hcloud"
version = ">= 1.43.0"
}
}
}
output "kubeconfig" {
value = module.kube-hetzner.kubeconfig
sensitive = true
}
variable "hcloud_token" {
sensitive = true
default = ""
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@xavierleune The ball is in your camp. Please, let's make sure this is fully backward compatible. See above. Thanks!
@mysticaltech thanks for your feedback, I'll have a look ! |
This is something I am also really looking forward to. I have never done k8s cluster with publicly available nodes, and made me concerned. In fact, I was thinking about creating an own module because of that. But having this here would be way better :-) Big thanks for the implementation! |
@mysticaltech I think that should do the trick, your test file now works as expected |
Thanks @xavierleune, will try ASAP |
Super excited to get this live, when it's expected to merge this? |
Hello @xavierleune I have tried to run your branch and got some issues with post creation script as shown in the console
Since disabling the public interface will result in a missing eth0 So changes must be made to locals.tf line 844 script to take this case into consideration |
i think this block should be executed if eth0 do not exists.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for this code
Thanks @xavierleune, on it, will do one final review and we can merge this. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
General Review
Overall, this PR adds valuable functionality for running Kube-Hetzner clusters with private IPs or even purely private connectivity. The approach is sensible: it updates modules to handle disable_ipv4
and disable_ipv6
flags, modifies how the code retrieves the node address, and clarifies the user guide for NAT setups.
Below is a deeper review highlighting potential concerns:
-
Connectivity Checks & Fallbacks
- Various sections (e.g.,
modules/host/main.tf
) now usecoalesce(ipv4, ipv6, network ip)
. If both IPv4 and IPv6 are disabled, the module depends on a NAT or VPN for connectivity. You might want more explicit error handling for the scenario where even the private IP is unreachable.
- Various sections (e.g.,
-
Resiliency of SSH Wait-Loop
- The code that loops until the server is ready is set with a 600-second (or indefinite) wait. That might be okay, but in a worst-case scenario, it can stall a pipeline. Consider adding a strict timeout or additional checks to fail more gracefully.
-
Backwards Compatibility
- Changes appear backward compatible overall—existing setups that keep IPv4 enabled will continue to operate as before. Just ensure that users with older configurations do not break if they never define the new boolean flags.
-
Validation & Documentation
- For purely private setups, you now rely on user-managed NAT or VPN. That’s correct, but do consider adding more disclaimers about the need for a stable route, especially if both IPv4 and IPv6 are disabled.
-
Maintainability
- The repeated
coalesce
logic is absolutely correct, but if the code in future evolves to support multiple interfaces or custom hostnames, a small helper or a local variable to unify the address selection might help.
- The repeated
Given these changes, I have some specific line-by-line suggestions below.
Summary
You’re on the right track. I recommend a few improvements to handle the purely private case more robustly and to keep the code a bit more self-explanatory. Great job overall!
@xavierleune Almost there brother, thanks in advance 🚀 |
Hello there, sorry I've been away from this pull request for too long, I'll have a look at your feedbacks in the coming days ! |
51dbf30
to
c2bb343
Compare
This one might be the one 🤞 |
Hi all, in Hetzner Private Networks I think we should add the below command in the init As well as we did here I think we should add a condition when we get Network Manager up.
In this case I think we need to add default network gateway if public ip address is not enabled |
Thanks @xavierleune! What do you think about @amedeopalopoli's suggestion above? |
@amedeopalopoli thanks for the suggestion, however I'm not sure we should do that, actually without public ip we should add a route for 0.0.0.0/0 in hetzner to the private ip of your gateway ; I followed this tutorial as I pointed out in the readme. I think that trying to use hetzner gateway without public ip would fail. |
An example i have it working in my case. then on the instance (running ubuntu) that has only private interface i do this:
Not 100% sure if i missed something , but i am happy to help if needed |
@lefterisALEX thanks for the feedback, seems a lot like the approach I was talking about, BTW I think you might get rid of those steps by adding the route in hetzner routes for your subnet ; it should be automatic then, like this but with my gateway ^^ |
I'm sorry @xavierleune but if we have nodes with only private IPs they cannot reach out internet (0.0.0.0) unless you add am I wrong? |
You can, if you add your gateway in the routes for 0.0.0.0/0, like in my previous screenshot ; that will leverage nat masquerade |
i think you need both @xavierleune . If you see in the documentation you shared in Step 3 - Configuring NAT and Step 4 - Achieving a persistent configuration it says that configuration is needed on client side as well. |
@lefterisALEX ok I can see that but from my understanding 10.0.0.1 is already declared because it's the subnet gateway for hetzner. I think cloud-init already handles that part. Here is an example for
|
@aru-amedeo I'm curious, did you tried this branch ? Because as far as my tests goes, it's working just fine right now ; cloud init pulls the network config from hetzner api so the default route use the gateway subnet ; just like for servers with a public interface, without a route on |
Hi @xavierleune as far as I understood, when you create a private network, you should add #1567 (comment). This allows you to use the network route when the destination address is part of the internal network and when it does not (e.g. public ip like 8.8.8.8). This is why I said you this PR is not enough to achieve what you aim to do. It's missing the cloudinit stuff to configure the default gw when a public ip should be routable from nodes with no public interface attached to. |
Hi there,
First, thank you for this awesome project! 🙌
This feature allows you to deploy k3s using only private IPs on your servers. It requires a VPN and NAT configuration, which are out of scope for this deployment.
This is my very first time working with Terraform, so I'm open to any feedback on this pull request as it can probably be improved.
Have a nice day!
CF #282 #1255