Skip to content
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

Document the Service source #3913

Merged
merged 3 commits into from
Sep 15, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/sources/ingress.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ or the Ingress had an
or the Ingress had an
`external-dns.alpha.kubernetes.io/ingress-hostname-source: defined-hosts-only` annotation.

* If no endpoints were produced for an Ingress by the previous steps
* If no DNS entries were produced for an Ingress by the previous steps
or the `--combine-fqdn-annotation` flag was specified, then adds hostnames
generated from any`--fqdn-template` flag.

Expand Down
108 changes: 108 additions & 0 deletions docs/sources/service.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# Ingress source
johngmyers marked this conversation as resolved.
Show resolved Hide resolved

The service source creates DNS entries based on `Service` resources.

## Filtering the Services considered

The `--service-type-filter` flag filters Service resources by their `spec.type`.
The flag may be specified multiple times to allow multiple service types.

This source supports the `--label-filter` flag, which filters Service resources
by a set of labels.

## Domain names

The domain names of the DNS entries created from a Service are sourced from the following places:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The domain names of the DNS entries created from a Service are sourced from the following places:
The domain names of the DNS entries created from a Service are sourced following this plan:

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think "plan" is quite the right word. It is an algorithm, not a proposal. It does specify the locations where the data are sourced, so "places" isn't too far off, though the items do describe the act of adding instead of the data being added.


* Adds the domain names from any `external-dns.alpha.kubernetes.io/hostname` and/or
johngmyers marked this conversation as resolved.
Show resolved Hide resolved
`external-dns.alpha.kubernetes.io/internal-hostname` annotation.
This behavior is suppressed if the `--ignore-hostname-annotation` flag was specified.

* If no DNS entries were produced for a Service by the previous steps
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* If no DNS entries were produced for a Service by the previous steps
2. If no DNS entries were produced for a Service by the previous step

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't the only place where items in the list depend on previous items not producing outputs. If we're going to take this sort of order-dependency as requiring a numbered list, we should do it consistently.

and the `--compatibility` flag was specified, then adds DNS entries per the
selected compatibility mode.

* If no DNS entries were produced for a Service by the previous steps
johngmyers marked this conversation as resolved.
Show resolved Hide resolved
or the `--combine-fqdn-annotation` flag was specified, then adds domain names
generated from any`--fqdn-template` flag.

### Domain names for headless service pods

If a headless service (without an `external-dns.alpha.kubernetes.io/target` annotation) creates DNS entries with targets from
johngmyers marked this conversation as resolved.
Show resolved Hide resolved
a Pod that has a non-empty `spec.hostname` field, additional DNS entries are created for that Pod, containing the targets from that Pod.
For each domain name created for the Service, the additional DNS entry for the Pod has that domain name prefixed with
the value of the Pod's `spec.hostname` field and a `.`.

## Targets

If the Service has an `external-dns.alpha.kubernetes.io/target` annotation, uses
the values from that. Otherwise, the targets of the DNS entries created from a service are sourced depending
on the Service's `spec.type`:

### LoadBalancer

* If the hostname came from an `external-dns.alpha.kubernetes.io/internal-hostname` annotation, uses
the Service's `spec.clusterIP` field. If that field has the value `None`, does not generate
any targets for the hostname.

* Otherwise, if the Service has one or more `spec.externalIPs`, uses the values in that field.

* Otherwise, iterates over each `status.loadBalancer.ingress`, adding any non-empty `ip` and/or `hostname`.
If the `--resolve-service-load-balancer-hostname` flag was specified, any non-empty `hostname`
is instead queried through DNS and any resulting IP addresses are added instead.
A DNS query failure results in zero targets being added for that load balancer's ingress hostname.
johngmyers marked this conversation as resolved.
Show resolved Hide resolved

### ClusterIP (headless)

Iterates over all of the Service's Endpoints's `subsets.addresses`.
If the Service's `spec.publishNotReadyAddresses` is `true` or the `--always-publish-not-ready-addresses` flag is specified,
also iterates over the Endpoints's `subsets.notReadyAddresses`.

* If an address does not target a `Pod` that matches the Service's `spec.selector`, it is ignored.

* If the target pod has an `external-dns.alpha.kubernetes.io/target` annotation, uses
the values from that.

* Otherwise, if the Service has an `external-dns.alpha.kubernetes.io/endpoints-type: NodeExternalIP`
annotation, uses the addresses from the Pod's Node's `status.addresses` that are either of type
`ExternalIP` or IPv6 addresses of type `InternalIP`.

* Otherwise, if the Service has an `external-dns.alpha.kubernetes.io/endpoints-type: HostIP` annotation
or the `--publish-host-ip` flag was specified, uses the Pod's `status.hostIP` field.

* Otherwise uses the `ip` field of the address from the Endpoints.

### ClusterIP (not headless)

* If the `--publish-internal-services` flag is specified, uses the `spec.ServiceIP`.

* Otherwise, does not create any targets.

### NodePort

If `spec.ExternalTrafficPolicy` is `Local`, iterates over each Node that both matches the Service's `spec.selector`
and has a `status.phase` of `Running`. Otherwise iterates over all Nodes, of any phase.

Iterates over each relevant Node's `status.addresses`:

* If there is an `external-dns.alpha.kubernetes.io/access: public` annotation on the Service, uses both addresses with
a `type` of `ExternalIP` and IPv6 addresses with a `type` of `InternalIP`.

* Otherwise, if there is an `external-dns.alpha.kubernetes.io/access: private` annotation on the Service, uses addresses with
a `type` of `InternalIP`.

* Otherwise, if there is at least one address with a `type` of `ExternalIP`, uses both addresses with
a `type` of `ExternalIP` and IPv6 addresses with a `type` of `InternalIP`.

* Otherwise, uses addresses with a `type` of `InternalIP`.

Also iterates over the Service's `spec.ports`, creating a SRV record for each port which has a `nodePort`.
The SRV record has a service of the Service's `name`, a protocol taken from the port's `protocol` field,
a priority of `0` and a weight of `50`.
In order for SRV records to be created, the `--managed-record-types`must have been specified, including `SRV`
as one of the values.

### ExternalName

* Creates a target with the value of the Service's `externalName` field.

2 changes: 1 addition & 1 deletion docs/sources/sources.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@
| node | Node | Yes | |
| openshift-route | Route.route.openshift.io | Yes | Yes |
| pod | Pod | | |
| service | Service | Yes | Yes |
| [service](service.md) | Service | Yes | Yes |
| skipper-routegroup | RouteGroup.zalando.org | Yes | |
| traefik-proxy | IngressRoute.traefik.io IngressRouteTCP.traefik.io IngressRouteUDP.traefik.io | Yes | |
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ nav:
- Sources:
- About: sources/sources.md
- Ingress: sources/ingress.md
- Service: sources/service.md
- Registries:
- About: registry/registry.md
- TXT: registry/txt.md
Expand Down
2 changes: 1 addition & 1 deletion source/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -671,7 +671,7 @@ func (sc *serviceSource) extractNodePortEndpoints(svc *v1.Service, hostname stri
// _service._proto.name. TTL class SRV priority weight port
// see https://en.wikipedia.org/wiki/SRV_record

// build a target with a priority of 0, weight of 0, and pointing the given port on the given host
// build a target with a priority of 0, weight of 50, and pointing the given port on the given host
target := fmt.Sprintf("0 50 %d %s", port.NodePort, hostname)

// take the service name from the K8s Service object
Expand Down
Loading