docs(networking): publish Kubernetes API endpoint via external-dns with kuberture#539
docs(networking): publish Kubernetes API endpoint via external-dns with kuberture#539lexfrei wants to merge 1 commit into
Conversation
✅ Deploy Preview for cozystack ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
Warning Rate limit exceeded
You’ve run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThis PR introduces a comprehensive documentation page for the Changeskuberture DNS Publishing Documentation
Estimated Code Review Effort🎯 1 (Trivial) | ⏱️ ~3 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Code Review
This pull request introduces documentation for kuberture, a component designed to bridge the gap between Kubernetes EndpointSlices and external-dns by creating annotated headless Services. The review feedback identifies a potential compatibility issue regarding how standard external-dns instances handle custom annotation prefixes for data extraction. Additionally, a suggestion was made to improve the clarity of the configuration documentation by better explaining the default behavior when the annotation prefix is omitted.
|
|
||
| ## Routing to multiple external-dns instances | ||
|
|
||
| A single `kuberture` install can address any number of `external-dns` instances by varying `annotationPrefix` per output. Each `external-dns` instance is configured (via `--annotation-filter`) to act on a specific prefix; `kuberture` stamps the matching prefix on each Service: |
There was a problem hiding this comment.
Standard external-dns does not support custom prefixes for data annotations like hostname, target, or ttl. It typically expects these keys to be prefixed with external-dns.alpha.kubernetes.io/. While --annotation-filter can be used to filter which Services an instance processes, it does not change the prefix used for data extraction. If kuberture only stamps annotations with a custom prefix, standard external-dns instances will not find the required DNS data. Please clarify if this feature requires a specific external-dns configuration or if kuberture should also stamp the standard annotations alongside the filter annotation.
There was a problem hiding this comment.
Premise needs a small correction — external-dns does support custom prefixes via --annotation-prefix, which is exactly the flag the Split Horizon DNS pattern uses. Fixed in b9be839: the doc now uses --annotation-prefix=<your-prefix>/ instead of --annotation-filter, so each external-dns instance rebuilds every hostname/target/ttl annotation key under the supplied prefix at startup and reads only the matching Services.
|
|
||
| Each Service carries **only** its own prefix's annotations — there is no cross-pollution between outputs. | ||
|
|
||
| `annotationPrefix` accepts two forms: omit the field to inherit the controller default `external-dns.alpha.kubernetes.io/`, or set it to a non-empty string ending in `/`. The empty string `""` is rejected by the chart's values schema; omission is the only zero-prefix path. |
There was a problem hiding this comment.
The term "zero-prefix path" is confusing here. Since omitting the field results in the default prefix (external-dns.alpha.kubernetes.io/) being used, it is not actually a "zero" (empty) prefix. It would be clearer to state that omission is the way to use the default prefix.
| `annotationPrefix` accepts two forms: omit the field to inherit the controller default `external-dns.alpha.kubernetes.io/`, or set it to a non-empty string ending in `/`. The empty string `""` is rejected by the chart's values schema; omission is the only zero-prefix path. | |
| `annotationPrefix` accepts two forms: omit the field to inherit the controller default `external-dns.alpha.kubernetes.io/`, or set it to a non-empty string ending in `/`. The empty string `""` is rejected by the chart's values schema; omission is the only way to use the default prefix. |
There was a problem hiding this comment.
Done in b9be839 — "omission is the only zero-prefix path" is now "omission is the only way to fall back to the default prefix". Describes the resulting behaviour rather than the (admittedly confusing) "zero prefix" framing.
ad08b7b to
4b586a3
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@content/en/docs/next/networking/kuberture.md`:
- Line 40: The phrase "wants published" in the kuberture docs sentence is
awkward; update the sentence in content/en/docs/next/networking/kuberture.md
(the paragraph describing the operator DNS requirement for `kuberture`) to use
clearer wording such as "wants to publish" or "wants to be published" (e.g.,
replace "the DNS hostname the operator actually wants published" with "the DNS
hostname the operator actually wants to publish" or "the DNS hostname the
operator actually wants to be published") so the operator guidance reads
naturally.
- Around line 117-118: The docs incorrectly suggest using
--annotation-filter=internal-dns.example.com to match annotations like
internal-dns.example.com/hostname; update the text to use a full annotation key
(e.g., --annotation-filter=internal-dns.example.com/hostname) or note that
--annotation-filter requires exact annotation key matches, and reference the
example resource name kuberture-internal and the actual annotation keys
(internal-dns.example.com/hostname, internal-dns.example.com/target,
internal-dns.example.com/ttl) so readers know to pick one exact suffixed key for
the filter.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 783947a6-813d-4389-bb83-24d0682751be
📒 Files selected for processing (1)
content/en/docs/next/networking/kuberture.md
Arsolitt
left a comment
There was a problem hiding this comment.
Page is well-structured and aligned with the companion package PR. One blocker: the multi-instance routing recipe documents --annotation-filter where external-dns actually needs --annotation-prefix. Please also address the unresolved CodeRabbit/Gemini bot threads — note that the high-priority Gemini one is wrong on its premise (external-dns does support custom annotation prefixes via --annotation-prefix), but its underlying observation that the doc's current flag choice doesn't match standard external-dns behaviour is correct.
| This renders two headless Services in `cozy-kuberture`: | ||
|
|
||
| - `kuberture-public` carries the default `external-dns.alpha.kubernetes.io/*` annotations and is consumed by the platform `external-dns`. | ||
| - `kuberture-internal` carries `internal-dns.example.com/*` annotations and is invisible to the platform `external-dns`; a second `external-dns` instance configured with `--annotation-filter=internal-dns.example.com` consumes it. |
There was a problem hiding this comment.
The recipe says a second external-dns instance configured with --annotation-filter=internal-dns.example.com consumes kuberture-internal. That flag does not produce the documented behaviour.
--annotation-filter is a label-selector filter on which objects external-dns considers at all; it uses Kubernetes label-selector semantics with exact key matching (source/annotations/filter.go at v0.20.0). A bare key internal-dns.example.com does not match an annotation key internal-dns.example.com/hostname. Even rewriting it as --annotation-filter=internal-dns.example.com/hostname (an existence selector) only filters which services external-dns looks at; the instance still reads hostname/target/ttl under its configured --annotation-prefix (default external-dns.alpha.kubernetes.io/), so the suffixed annotations on kuberture-internal would be invisible to it.
The flag that does what the docs describe is --annotation-prefix=internal-dns.example.com/. external-dns calls annotations.SetAnnotationPrefix(cfg.AnnotationPrefix) on startup (controller/execute.go:66 at v0.20.0) and rebuilds all hostname/target/ttl annotation keys under the supplied prefix. The upstream Split Horizon DNS doc (docs/advanced/split-horizon.md in kubernetes-sigs/external-dns) states verbatim: "To enable split horizon DNS, configure each instance to use a different annotation prefix using the --annotation-prefix flag."
Same wording on line 85 ("via --annotation-filter"). Both occurrences should be --annotation-prefix=<your-prefix>/ (note the trailing slash, matching the chart's values.schema.json pattern: /$).
There was a problem hiding this comment.
Fixed in b9be839. Both occurrences (lines 85 and 117) now use --annotation-prefix=<your-prefix>/, with a link to the upstream Split Horizon DNS doc and an inline note distinguishing the two flags (--annotation-filter is a Kubernetes label-selector on which Services to consider; --annotation-prefix rebuilds the annotation key namespace external-dns reads from).
…th kuberture Document the kuberture system package: the EndpointSlice-to-Service bridge that lets external-dns publish the cluster's own API endpoint. Covers the problem (external-dns does not support EndpointSlice as a source), the kuberture flow, single-instance enabling against the platform external-dns, multi-instance routing via annotationPrefix, the four addressSource strategies, the disable path, and the maintainer-personal-namespace supply-chain caveat. Companion to cozystack/cozystack#2647 which adds the package. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Aleksei Sviridkin <f@lex.la>
4b586a3 to
b9be839
Compare
|
@Arsolitt addressed: the multi-instance recipe blocker is fixed in |
Addressed by author in b9be839; re-reviewing.
Arsolitt
left a comment
There was a problem hiding this comment.
Blocker resolved in b9be839 — both --annotation-filter occurrences (lines 85 and 117) now read --annotation-prefix=<your-prefix>/, with an inline note clarifying that --annotation-filter is a label-selector on which Services an external-dns instance considers, not which prefix it reads data from. The "zero-prefix path" wording flagged by Gemini is also cleaned up in this iteration.
Approving.
What this PR does
Adds documentation for the
kuberturesystem package being introduced in cozystack/cozystack#2647. New page atcontent/en/docs/next/networking/kuberture.md, weight 26 (slots in right afterhairpin-proxy-protocolat weight 25 in the networking section).The page covers:
kuberturesolves:external-dnsdoes not supportEndpointSliceas a source, so the canonical control-plane endpoint atdefault/kubernetescannot be published to DNS without a bridge.kubertureworks: a small in-cluster controller that watches EndpointSlice and stamps annotated headless Services (one per output) forexternal-dnsto consume.cozystack.external-dnswith a copy-pasteablePackageCR.kubertureinstall can serve multipleexternal-dnsinstances simultaneously by stamping a differentannotationPrefixper output, with the matchingexternal-dnsrunning with--annotation-filter. Includes a worked two-output example.addressSourcestrategies (endpointslice/node-internal/node-external/node-public) and when each fits.external-dnspolicy: upsert-onlyinteraction on record retraction.lexfrei/*registry namespace, are pinned by digest in the cozystack package, and air-gapped operators must mirror both into their internal registry.Style follows
networking/hairpin-proxy-protocol.md(the sibling system-addon doc forouroboros): handwritten, narrative, single-line markdown paragraphs.Release note
Summary by CodeRabbit