terraforming Hetzner, dynamische IPs
Fri 03 June 2022kubernetes–API in der Firewall beschränken
Auf den kubernetes–Nodes lauscht auf Port 6443/tcp die kube–api, über die
beispielsweise unser kubectl
von zuhaus mit dem Cluster kommuniziert.
In den bisheringen Beispielen für die Firewall haben wir Ports immer fürs
gesamte Internet geöffnet (0.0.0.0/0
& ::/0
als Quellen).
Ist für die kube–api natürlich nicht wirklich notwendig, zumindest in meinem Setup will erstmal nur ich von zuhause aus kubectl nutzen.
Da der Cluster dank rke nur per legacy IPv4 erreichbar ist ändert sich meine Adresse alle paar Monate, denn mein ISP weist mir leider keine statische zu. Ich habe aber einen DNS-Eintrag der immer auf die aktuelle IPv4 zeigt, über afraid.org.
Die Hetzner-Firewall kann (natürlich) nichts mit Hostnames anfangen, sondern verlangt nach IPs, der hcloud–Provider will sogar zwingend ein Netzbereich.
Ich muss also per terraform zum einen die IPv4 zu meinem Hostname herausfinden, zum anderen das in ein Netz wandeln, und das dann der Firewall übergeben.
DNS–Auflösung in terraform
Um die IP(s) zu einem Hostname herauszufinden gibt es — einen
terraform–Provider! Und zwar nutze ich hashicorp/dns
in Version 3.2.3.
Diesen in terraform.tf wie gewohnt definiert lädt `terraform init ihn wie
gewohnt herunter.
Mit dem installierten Provider erweitere ich dann den Plan für die Firewall:
firewall.tf
data "dns_a_record_set" "kubectl" {
host = "zknt-hh3.trantuete.net"
}
So ein data
–Block (statt wie üblich resource
) steht für Operationen in
denen wir etwas nachschlagen, aber nichts verändern.
terraform löst hier also den Hostname auf und speichert die Liste der IPs.
Die Antwort ist immer eine Liste, auch wenn ich weiß das ich nur eine IPv4
habe…
Nun möchte der hcloud–Provider ja Netze, nicht IPs, es muss also "/32" dahinter stehen. Dazu gehe ich einfach die Liste durch und hänge den String hinter jeden Eintrag:
locals {
host_cidr = flatten([
for ip in data.dns_a_record_set.ctl.addrs :
"${ip}/32"
])
}
Damit steckt die gewünschte Liste von Netzen in der Variable host_cidr
die
ich in der Firewall–Rule direkt nutzen kann:
rule {
direction = "in"
protocol = "tcp"
port = "6443"
source_ips = local.host_cidr
}
Und damit ist die API nach dem nächsten plan && apply
nur noch von mir
aus nutzbar. Ändert mein ISP mal wieder meine IPv4 muss ich terraform halt
nochmal ausführen…