docs(gateway-api): clarify annotation placement (#5918)

Addresses #5901
Related: #4056

Add clear documentation on annotation placement for Gateway API sources
to prevent confusion about which annotations go on Gateway vs Route resources.

Changes:
- Add Gateway API Annotation Placement section to annotations.md
- Add Annotations section with examples to gateway-api.md
- Include Cloudflare and AWS provider examples
- Document common mistakes

Per review feedback, compressed annotations.md section to minimal size:
- Removed annotation placement matrix table
- Removed YAML examples
- Kept concise 2-line summary
- Kept link to comprehensive documentation

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Aleksei Sviridkin 2025-10-26 11:23:34 +03:00 committed by GitHub
parent 866afef3f8
commit effffb200e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 117 additions and 1 deletions

View File

@ -27,7 +27,7 @@ The following table documents which sources support which annotations:
[^1]: Unless the `--ignore-hostname-annotation` flag is specified. [^1]: Unless the `--ignore-hostname-annotation` flag is specified.
[^2]: Only behaves differently than `hostname` for `Service`s of type `ClusterIP` or `LoadBalancer`. [^2]: Only behaves differently than `hostname` for `Service`s of type `ClusterIP` or `LoadBalancer`.
[^3]: Also supported on `Pods` referenced from a headless `Service`'s `Endpoints`. [^3]: Also supported on `Pods` referenced from a headless `Service`'s `Endpoints`.
[^4]: The annotation must be on the `Gateway`. [^4]: For Gateway API sources, annotation placement differs by type. See [Gateway API Annotation Placement](#gateway-api-annotation-placement) for details.
[^5]: The annotation must be on the listener's `VirtualService`. [^5]: The annotation must be on the listener's `VirtualService`.
## external-dns.alpha.kubernetes.io/access ## external-dns.alpha.kubernetes.io/access
@ -210,3 +210,13 @@ Specifies the set identifier for DNS records generated by the resource.
A set identifier differentiates among multiple DNS record sets that have the same combination of domain and type. A set identifier differentiates among multiple DNS record sets that have the same combination of domain and type.
Which record set or sets are returned to queries is then determined by the configured routing policy. Which record set or sets are returned to queries is then determined by the configured routing policy.
## Gateway API Annotation Placement
When using Gateway API sources (`gateway-httproute`, `gateway-grpcroute`, `gateway-tlsroute`, etc.), annotations
are read from different resources: **Gateway resource** reads only `target` annotation, while **Route resources**
(HTTPRoute, GRPCRoute, TLSRoute, etc.) read all other annotations (`hostname`, `ttl`, `controller`, and
provider-specific annotations like `cloudflare-*`, `aws-*`, `scw-*`).
For more details and comprehensive examples, see the
[Gateway API documentation](../sources/gateway-api.md#annotations).

View File

@ -35,6 +35,112 @@ for HTTPRoutes and TLSRoutes by ExternalDNS, but it's _strongly_ recommended tha
specs to provide all intended hostnames, since the Gateway that ultimately routes their specs to provide all intended hostnames, since the Gateway that ultimately routes their
requests/connections won't recognize additional hostnames from the annotation. requests/connections won't recognize additional hostnames from the annotation.
## Annotations
### Annotation Placement
ExternalDNS reads different annotations from different Gateway API resources:
- **Gateway annotations**: Only `external-dns.alpha.kubernetes.io/target` is read from Gateway resources
- **Route annotations**: All other annotations (hostname, ttl, controller, provider-specific) are read from Route
resources (HTTPRoute, GRPCRoute, TLSRoute, TCPRoute, UDPRoute)
This separation aligns with Gateway API architecture where Gateway defines infrastructure (IP addresses, listeners)
and Routes define application-level DNS records.
### Examples
#### Example: Cloudflare Proxied Records
```yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: my-gateway
namespace: default
annotations:
# ✅ Correct: target annotation on Gateway
external-dns.alpha.kubernetes.io/target: "203.0.113.1"
spec:
gatewayClassName: cilium
listeners:
- name: https
hostname: "*.example.com"
protocol: HTTPS
port: 443
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: my-route
annotations:
# ✅ Correct: provider-specific annotations on HTTPRoute
external-dns.alpha.kubernetes.io/cloudflare-proxied: "true"
external-dns.alpha.kubernetes.io/ttl: "300"
spec:
parentRefs:
- name: my-gateway
namespace: default
hostnames:
- api.example.com
rules:
- backendRefs:
- name: api-service
port: 8080
```
#### Example: AWS Route53 with Routing Policies
```yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: aws-gateway
annotations:
# ✅ Correct: target annotation on Gateway
external-dns.alpha.kubernetes.io/target: "alb-123.us-east-1.elb.amazonaws.com"
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: weighted-route
annotations:
# ✅ Correct: AWS-specific annotations on HTTPRoute
external-dns.alpha.kubernetes.io/aws-weight: "100"
external-dns.alpha.kubernetes.io/set-identifier: "backend-v1"
spec:
parentRefs:
- name: aws-gateway
hostnames:
- app.example.com
```
### Common Mistakes
**Incorrect**: Placing provider-specific annotations on Gateway
```yaml
kind: Gateway
metadata:
annotations:
# ❌ These annotations are ignored on Gateway
external-dns.alpha.kubernetes.io/cloudflare-proxied: "true"
external-dns.alpha.kubernetes.io/ttl: "300"
```
**Incorrect**: Placing target annotation on HTTPRoute
```yaml
kind: HTTPRoute
metadata:
annotations:
# ❌ This annotation is ignored on Routes
external-dns.alpha.kubernetes.io/target: "203.0.113.1"
```
For a complete list of supported annotations, see the
[annotations documentation](../annotations/annotations.md#gateway-api-annotation-placement).
## Manifest with RBAC ## Manifest with RBAC
```yaml ```yaml