Repository navigation
Pre-RFC: running cluster mode on Kubernetes without hostNetwork and TLS shenanigans #4487
Replies: 3 comments
|
hello, |
|
overall, i like this direction. separating the replica listener’s bind address from the address peers dial would address the restriction behind the current an optional replica bind IP, independent of DNS support needs to cover stored peer endpoints, validation, reconnects, internal HTTP forwarding, and the fallback address advertised to clients. the connector currently stores numeric i’d start with compio’s existing resolver on each connection attempt, without adding another DNS cache. temporary resolution failures should follow the reconnect path. we also need to define how timeouts work across multiple answers so a blackholed first result doesn’t consume every attempt before another address gets tried. the HTTP certificate concern is valid. forwarding pins the local leaf certificate, so distinct per-node certificates and mixed old/new certificates fail verification on new forwarding connections. an opt-in CA mode with normal verification of the configured peer name makes sense, retaining pinning when absent. once every node uses that mode, valid certificates under the trusted CA could be renewed through rolling restarts. the initial migration needs its own compatibility plan: nodes still using pins reject new leaves, and existing shared certificates may lack the required DNS names. live certificate reload is separate. readiness needs a clear definition before we can call the rolling update safe. #4438, with a fix proposed in #4483, gives a concrete example: it reports a replica serving a stale prefix while state transfer remains stuck after rolling crash-restarts. the readiness definition should also align with #4266, which asks what evidence a recovered replica needs before it can resume participation under if readiness requires quorum, default
i’d suggest a short RFC, following the process discussed in #4410, covering the address model, compatibility, TLS migration, and readiness behavior, followed by the small implementation PRs you proposed. we can settle field naming there, keeping one authoritative replica dial address. tests should cover cold bootstrap, temporary DNS failure, changed pod IPs, multiple DNS answers, certificate migration and renewal, and a recovering replica holding up the next planned replacement. |
|
one more thing that i remembered, interaction between #4055 and this proposal also needs to be analyzed. right now i dont have time to do that. |
Uh oh!
There was an error while loading. Please reload this page.
Hi all. We'd like feedback on a direction before writing any code. If the maintainers are on board, we'd like to build it ourselves as a series of small PRs.
Summary
We want to run a 3-node Iggy cluster on Kubernetes as a StatefulSet, without
hostNetwork. As far as we can tell, the one thing in the way is how the replica plane usescluster.nodes[*].ip. The PSK handshake, replica TLS and VSR look fine as they are. Below are three opt-in server changes and a chart mode, plus some open questions we'd value your view on.Where we are
We run Iggy 0.9.0 on Kubernetes (Kubernetes 1.36 with Calico) with the Rust SDK and the connectors runtime. Today that's a single node, and we'd like to move to cluster mode now that it has shipped. The chart's cluster mode (#4035) explains why it needs
hostNetworkplus one release pinned to each node: the consensus listener binds the rosteripverbatim, pods don't have stable addresses, and a Service ClusterIP can't be bound.For us that costs the following:
nodeSelectorand rolled out withRecreate.ipas the server name, so node certificates need IP SANs. cert-manager can issue those, but per-pod Kubernetes certificates are normally issued for DNS names.What already works in our favour
This is from reading the code; we haven't tested it yet.
ReplicaHelloand, with auth on, proves PSK membership. Replica traffic should therefore work through a Service VIP or NAT.ip. They bind their ownaddressand take only the port from the roster, and the chart README notes that the replica listener is the exception.advertised_addressaccepts hostnames (feat(server-ng): add cluster.nodes.advertised_address for clients #3757), and feat(server-ng): add per-client-network advertised address selectors #3818 added advertised-address selectors for clients behind NAT and in Kubernetes. Only the replica side needs work.Proposal
Each item below would be its own issue and PR, in this order. All of them are opt-in, so existing configs keep their current behaviour.
1. A bind address for the replica listener
Today the replica listener binds
node.ip:tcp_replica. We'd add an optional bind IP for it, for examplecluster.replica_bind_address(name open).<that ip>:<roster tcp_replica port>. When it's unset, nothing changes.ipremains the address peers dial and the TLS server name.[tcp].addressthe way fix(server-ng): bind cluster TCP to [tcp].address, not the roster ip #3783 did. It defaults to0.0.0.0, so a multi-homed host would silently start accepting replica traffic on every interface. That would break the trusted-L2 deployments the handshake docs describe.This change alone removes the need for
hostNetwork:spec.clusterIP.0.0.0.0.That works, but operators have to choose Service IPs in advance, which leads to the next item.
2. DNS names for the replica plane
Allow a hostname as a node's replica address. It could go in
ipor in a new field so thatipkeeps its meaning; we'd follow your preference.With a headless Service, the roster becomes
iggy-0.iggy-headless.<ns>.svc,iggy-1.…, which fits a StatefulSet and per-pod cert-manager certificates.This partly reverses #3923, which made a non-IP roster
ipa startup error. As far as we can tell, that check exists because the replica listener binds the value, which (1) makes unnecessary. If it protects something else, we'd like to know.Open points:
ToSocketAddrsAsync(getaddrinfoon the blocking pool) on every dial, or cache results?3. CA verification for HTTP forwarding
As an option, verify the primary's HTTP certificate against a CA (for example a new
http.tls.ca_file) and the target node's name, instead of the exact-DER pin. The pin stays the default. We agree it's the stronger check when the roster is fixed. The CA option is there so nodes can hold their own certificates and renew them independently.4. A StatefulSet cluster mode in the chart
replicas: 3, a headless Service, and a roster of DNS names generated from the replica count.--replica-idcomes from theapps.kubernetes.io/pod-indexlabel via the downward API (Kubernetes 1.28+), so identity needs no server change.maxUnavailable: 1protects quorum.Out of scope
No changes to the PSK handshake, TLS channel binding, wire protocol or VSR.
Questions for the maintainers
ipverbatim that we've missed?ipversus adding a new field?If you're on board, we'll open the issues and send PRs one at a time. Each will include tests and be run locally and checked on our own cluster.
Disclosure: I used Claude Code to help trace the code paths and PR history behind this post.
All reactions