Skip to content

Latest commit

 

History

History
187 lines (139 loc) · 6.95 KB

service-external-name.md

File metadata and controls

187 lines (139 loc) · 6.95 KB

WARNING WARNING WARNING WARNING WARNING

PLEASE NOTE: This document applies to the HEAD of the source tree

If you are using a released version of Kubernetes, you should refer to the docs that go with that version.

Documentation for other releases can be found at releases.k8s.io.

Service externalName

Author: Tim Hockin (@thockin), Rodrigo Campos (@rata)

Date: July 2016

Status: Waiting LGTM

Goal

Allow a service to have a CNAME record in the cluster internal DNS service. For example, a db service can have a CNAME to something.rds.aws.amazon.com pointing to an RDS resource.

Motivation

There were tons of issues about this, I'd try to summarize motivation here. More info is on github issues/PRs: #13748, #11838, #13358, #23921

One motivation is to present as cluster services, services that are hosted by some provider. Some cloud providers, like AWS, give a hostname (IPs are not static) and the user wants to refer using regular kubernetes tools to these services. This was asked in bugs, at least for AWS in RedShift, RDS, Elasticsearch Service, ELB, etc.

Some others just want an external service, for example "oracle", with dns name "oracle-1.testdev.mycompany.com", without having to keep DNS in sync, and just want a CNAME.

Another use case is to "integrate" some services to local development. For example, I have a search service running in kubernetes in staging, let's say search-1.stating.mycompany.com. Let's say it's on AWS, so it's behind an ELB (which doesn't have a static IP, it has a hostname). I'm building an app that consumes search-1 and I don't want to run it on my local PC (before kubernetes I didn't). I can just create a service that has a CNAME to the search-1 endpoint in staging and be happy like I was before.

Also, openshift needs this for "service refs". Service ref is really just the three use cases mentioned above, but in the future a way to automatically inject "service ref"s into namespaces via "service catalog"1 might be considered. And service ref is the natural way to integrate an external service, since it takes advantage of native DNS capabilities already in wide use.

Alternatives considered

In the issues linked above, there is also some alternatives considered. I will try to sum them up here, but the list might not be complete or have all the discussion.

One option is to add the hostname to endpoints. This was proposed in: #11838. This is problematic as endpoints are used in tons of places and users assume the required fields (like IP, for example) are always present and a valid IP (and check that). If the field is not required anymore, they can break, or if there is a hostname instead of the IP, they can break too. But assuming that can be solved, it was also discussed that the hostname will have to be resolved, with a timeout, sync/async and the DNS entry has a TTL and presents other problems. One option, not perfect, was to only resolve the hostname on creation. But this was considered not a good idea. The best thing was to do this at a higher level, maybe a service type.

There are more ideas on how to approach this problem on #13748, but all pointed to some problem. Ranging from using another upstream DNS server to creating a Name object assoaciated with DNSs.

Proposed solution

The proposed solution is to add this at the service layer by adding a new externalName type to the service. This will create a CNAME record in the internal cluster DNS service.

Using a CNAME avoids having to do the lookup, decide a timeout for it, and having to lookup for it when the TTL expires. It's way simpler to implement, while solving the right problem. And doing it at the service layer avoids all the problem discussed with doing the change at the endpoints layer.

The proposed solution is the one by Tim Hockin here: #13748 (comment)

Currently a ServiceSpec looks like this (comments stripped down):

type ServiceSpec struct {
    Ports []ServicePort

    // If not specified, the associated Endpoints object is not automatically managed
    Selector map[string]string

    // "", a real IP, or "None".  If not specified, this is default allocated.  If "None", this Service is not load-balanced
    ClusterIP string

    // ClusterIP, NodePort, LoadBalancer.  Only applies if clusterIP != "None"
    Type ServiceType

    // Only applies if clusterIP != "None"
    ExternalIPs []string
    SessionAffinity ServiceAffinity

    // Only applies to type=LoadBalancer
    LoadBalancerIP string
    LoadBalancerSourceRanges []string

So, the proposal is to change it to:

type ServiceSpec struct {
    Ports []ServicePort

    // If not specified, the associated Endpoints object is not automatically managed
+   // Only applies if type is ClusterIP, NodePort, or LoadBalancer.  If type is ExternalName, this is ignored.
    Selector map[string]string

    // "", a real IP, or "None".  If not specified, this is default allocated.  If "None", this Service is not load-balanced.
+   // Only applies if type is ClusterIP, NodePort, or LoadBalancer.  If type is ExternalName, this is ignored.
    ClusterIP string

-   // ClusterIP, NodePort, LoadBalancer.  Only applies if clusterIP != "None"
+   // ExternalName, ClusterIP, NodePort, LoadBalancer.  Only applies if clusterIP != "None"
    Type ServiceType

+   // Only applies if type is ExternalName
+   ExternalName string

    // Only applies if clusterIP != "None"
    ExternalIPs []string
    SessionAffinity ServiceAffinity

    // Only applies to type=LoadBalancer
    LoadBalancerIP string
    LoadBalancerSourceRanges []string

So, for example, it can be used like this:

apiVersion: v1
kind: Service
metadata:
  name: my-rds
spec:
  ports:
  - port: 12345
type: ExternalName
externalName: myapp.rds.whatever.aws.says

There is one thing to take into account (that no other alternative considered fixes either): TLS. If the service is a CNAME for an endpoint that uses TLS, connecting with another name may fail cert validation. This is acknowledged and left for future consideration.

Analytics