-
Notifications
You must be signed in to change notification settings - Fork 40k
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
Service reorg ideas #2585
Comments
Copy/pasting comments from #2738.
|
In the last comment, I think @stp-ip was asking for what is essentially OpenShift's Route type:
Much like our service proxy watches endpoints, an HTTP reverse proxy, such as HAProxy, could watch routes. |
First of all, bikeshedding about the name. I think "service" is too overloaded and brings too much baggage. Also, if we decompose this into multiple objects, they'll need more specific names. For at least the "frontend" portion, I propose In terms of decomposing this, I think it divides nicely between the "frontend" parts and the "backend" target/endpoint specification, which could be inline but a separate object would make sense, too, in which case we could decouple production of the Endpoints list and consumption of it.
UPDATE 01/14/2015: The manual Endpoints list above doesn't work well for multiple ports on the same IP address. It probably just needs to be a list of hosts. The PodPorts could be generalized to work for manual targets. They'd have to be protocol+port pairs. |
We could distinguish internal vs. external portals by pool (i.e., have an I think |
I could also imagine a |
We should support an array of IP addresses rather than just a single address. This would permit DNS load balancing, such as in the case that the addresses don't map to Kubernetes backends. I'd also like to support a one-to-one option on the portals, to indicate a nominal service (#260). In that case, no load-balancing details, such as SessionAffinity, would be specified. Perhaps those could be alternative MappingOptions. I assume the portal names would be used to produce distinct DNS names for each portal. We may not support externally visible DNS yet, but I could imagine that we would in the future. In the pod port specifications, it would be useful to indicate whether http/https were supported, in addition to TCP vs. UDP. Or perhaps we could accept HTTP and HTTPS in addition to just TCP. We should add the ReadinessProbe spec to pods, also, which the Endpoints Controller could use. Since I've proposed we also target host:port, we might also need readiness probe spec in EndpointsSpec. |
Another thought on provider-specific behavior: Ideally, the user could enumerate all provider-specific options, and the system would select out the appropriate ones based on which provider the cluster was actually running on. That would facilitate config reuse across multiple providers. |
I thought of one difference between internal and external portals: For internal portals, we may want to add a whitelist of namespaces that could access the service and/or a selector to indicate which pods within the namespace should be permitted access. Note that the latter can't provide real protection until/unless we enforce application of labels by label namespace. |
It would also be useful for a service provider to publish fairly arbitrary metadata to be consumed by clients, such as client connection parameters, shard maps, keys to look up resource usage data, etc. Not exactly labels or annotations, but would be a map of string to string (cf. DNS TXT key-value data). Maybe "serviceParameters" or "clientConfiguration". If we wanted it to be customizable per pod, it would need to be pulled from the pods, or even from the containers themselves, perhaps similar to readiness. Our internal RPC, load balancing, sharding, and other communication libraries/components depend more and more on this type of thing. |
Starting with the easy part: the "backend". I think we have consensus that this is at least a logically separable part of the service. Certainly it's independently useful (#1607). My previous stab at this was here: #2585 (comment) The only thing I'd add is the key-value payload described here: #2585 (comment) An alternative name could be TargetController, TargetWatcher, .. See #3024 for general name ideas. But, if we change it, we should change "Endpoints" also, since the main job of this is to generate the Endpoints lists. In the future, we could add configurable policies about what to filter from the endpoints list, such as whether to use readiness (#620) or not. Like in the proposal to split out the pod template from ReplicationController (#170), we could support both an inline version of this in the other part of Service and a reference to a separate object. Will work on the other part(s) of Service now. |
An observation: If we went with an independent EndpointsController object, the different portals shown in @jbeda's example #2585 (comment) could be all separate objects referring to the same EndpointsController object. |
First stab at fully granular version (specs only):
Will explore alternatives next. |
Low-hanging consolidation/simplifications:
This would look like:
|
What is the current status of this issue? |
In progress. On Thu, Feb 19, 2015 at 10:25 PM, Yuki Yugui Sonoda <
|
To revisit the previously posted slides about how the final endpoints struct is factored... As I code it up, I find this factoring somewhat awkward. It's not a HUGE deal (it's just code) but what I realized is that the primary key I care about is the (service, port) tuple, not the (service, ip), which is what we have produced. In effect I have to pivot all the data into a different struct to use it. A snippet: type hostPortPair struct {
host string
port int
}
// Update endpoints for services.
for i := range allEndpoints {
svcEndpoints := &allEndpoints[i]
// We need to build a map of portname -> all ip:ports for that portname.
portsToEndpoints := map[string][]hostPortPair{}
// Explode the Endpoints.Endpoints[*].Ports[*] into the aforementioned map.
for j := range svcEndpoints.Endpoints {
ep := &svcEndpoints.Endpoints[j]
for k := range ep.Ports {
epp := &ep.Ports[k]
portsToEndpoints[epp.Name] = append(portsToEndpoints[epp.Name], hostPortPair{ep.IP, epp.Port})
// Ignore the protocol field for now.
}
}
for portname := range portsToEndpoints {
// Finally I can process the (service, port) -> endpoints data. I'm not sure this alone justifies revisting the proposed structure in #4370 but I wanted to put it out there - as the first consumer of my own work, I am not happy with it :) |
I think there's no escaping that some use cases will want all ports for each IP, other use cases will want all endpoints for a given port name, and other use cases will expect the same port for all IPs. Given that we expect the same ports for all IPs, would representing the ports and IPs separately be easier? |
I don't think this is horrible, it's just a bit tedious. It's only a few On Sun, Feb 22, 2015 at 10:23 PM, Brian Grant notifications@github.com
|
Was discussed in person. Use cases:
On a different topic, in #4440 I proposed using Endpoints for nodes and pods (not services) to replace ResourceLocation, which /proxy, /redirect, /bastion, etc. could be built on top of. This would suggest that we should change the service endpoints paths, to allow more flavors of endpoints. |
multiple ports is in. |
Removed from 1.0 and reduced priority. Will summarize later. |
@thockin and @bgrant0607 ... Trying to figure out the current state on "multiple ports", and am confused about what was removed from 1.0. Can you add clarification? |
This issue is largely obsolete. Service/LB changes continue to be discussed in other issues, such as #561. |
Access external database from inside K8SI have workers inside K8S that want to talk to an external database. I have created an external mapping to SQL server like so:
DNS seems to work and "database" resolves to a 10 net address which I think points to the external address. BUT pods can't seem to successfully access/login. Thoughts/suggestions? |
I think this is covered by referential services
#13748
|
@smarterclayton Yep! Thanks for sharing. That's why I posted here - I also saw your other thread that was circling around this concept. |
Forking from #2358 . Copying verbatim. Will follow with more concrete proposal.
/cc @smarterclayton @thockin @jbeda
v1beta3 service spec (which is very similar to v1beta1/2):
Naming (DNS and links variables) isn't currently configurable or optional, but should be, for things like non-Kubernetes services or headless services.
As discussed in #2319, exposed addresses (PortalIP, PublicIPs) should be unified into a single list from which the system can allocate. We may want to be able to allocate multiple IPs, for DNS load balancing. For headless services, it should also be possible to disable IP allocation. I need to think more about how/whether nominal services (#260) would fit in.
As in #2358, these IPs may even map to non-Kubernetes resources.
These IPs may be intra-cluster, accessible via tunnels/proxies, externally visible but ephemeral (dynamically allocated for lifetime of the service), or fully externally visible and stable. #2209 proposed "every node" services for an authentication daemon, and we've discussed using magic nonroutable IP addresses like 169.254.169.253 (DNS) and 169.254.169.254 (metadata) for system services.
We should support ipv6 as well as ipv4.
For external IP resources, they may or may not map to specific nodes, would have firewall port ranges, and may have other auth policies attached (e.g., who is allowed to use them). Addresses that map to specific nodes will require reserving the specific requested ports from those nodes.
#2738 proposed multiple IP address "portals", where the addresses could be drawn from pools of addresses that were either internally or externally visible. Portal types could be pluggable, like volumes are intended to be.
IP addresses should be entirely optional in order to support headless services #1607.
As per #1802, we should support multiple ports -- a list of (Port, ContainerPort, Protocol) tuples. And, it should be possible to specify no ports and just deal with addresses. Note that it's useful to specify higher-level protocols, such as HTTP/HTTPS, for proxies, UIs, etc.
Target IPs should be specifiable by selector, inline IP and/or name list, and external source, by POSTing/PUTting them to the endpoints API and/or by telling the system to watch an external endpoints API (which I'd like to standardize beyond just K8s).
I expect in the future that we may want to differentiate the single-target "routing" case (e.g., singleton services, master-elected services, nominal services) from the load-balancing case, for at least 2 reasons:
For a case where someone plugs in their own load balancer, that would require 2 services with the current approach, I think, one to target the load balancer and another to generate the endpoint list of its targets.
FWIW, in GCE, this is factored into forwarding rules and target pools/instances, with load balancing configuration associated with the target pool:
https://cloud.google.com/compute/docs/load-balancing/network/forwarding-rules
With all of the above, is just specifying an external load balancer enough for the case of cloud-provided L3 forwarding and/or balancing? Maybe.
L7 is #561. L7 balancers (HAProxy, nginx) should be able to consume endpoints and route directly to pod IPs.
For reference, OpenShift router: openshift/origin#514
As per #620, we need readiness checks, for lots of reasons (rolling updates, auto-scaling, disruptive minion management, ...) in addition to load balancing.
Sticky sessions were requested in #2867 and were added by #2875.
We should resolve #983 (port defaulting) in this, also.
The text was updated successfully, but these errors were encountered: