-
Notifications
You must be signed in to change notification settings - Fork 91
Conversation
Codecov Report
@@ Coverage Diff @@
## master #994 +/- ##
==========================================
+ Coverage 71.65% 72.07% +0.41%
==========================================
Files 43 47 +4
Lines 5067 5307 +240
==========================================
+ Hits 3631 3825 +194
- Misses 1278 1304 +26
- Partials 158 178 +20
Continue to review full report at Codecov.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ijsnellf can you add a readme under platform/eureka documenting how you map the eureka fields to our service model, limitations and any todos, requirements expected from end users?
@GregHanson can you do the same for Consul ?
We don't need elaborate docs. Just enough to get other devs started, if they want to contribute.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One comment on health
I'd like to see this use a client library like fargo in the future.
"hostName": "foo.bar.local", | ||
"app": "FOO_BAR_LOCAL", | ||
"ipAddr": "10.0.0.2", | ||
"status": "UP", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This normally indicates health as posted by local healthchecks or those embedded in clients like ribbon. Since this is updated by each application instance, I think we should filter out instances with status: "down".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that sounds reasonable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@cmluciano: filter out everything except for "UP", I assume? Possible values: UP, DOWN, STARTING, OUT_OF_SERVICE, UNKNOWN
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes everything except for up
@@ -0,0 +1,161 @@ | |||
package eureka |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing copyright
platform/eureka/controller.go
Outdated
"time" | ||
|
||
"reflect" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
kind of surprised this passed this goimports test, I believe "time" and "reflect" should be sorted alphabetically
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove extra line between the imports. Lines between imports are used to group imports together.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, they got added randomly. Surprised that goimports doesn't remove them automatically.
|
||
type application struct { | ||
Name string `json:"name"` | ||
Instances []*instance `json:"instance"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
json:"instance"
or json:"instances"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Eureka idiosyncrasies. instance
is correct.
@@ -191,7 +191,7 @@ func TestConvertService(t *testing.T) { | |||
} | |||
|
|||
if len(out.Ports) != 1 { | |||
t.Errorf("covnertService() incorrect # of ports => %v, want %v", | |||
t.Errorf("convertService() incorrect # of ports => %v, want %v", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: should this be moved to a new PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Technically, but if it has to be it won't happen.
platform/eureka/client.go
Outdated
Hostname string `json:"hostName"` | ||
App string `json:"app"` | ||
IPAddress string `json:"ipAddr"` | ||
Status string `json:"status"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I forget, does status mean health? If so do we already drop non-"UP" instances?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. We filter out the non-"UP" instances in the conversion logic (in conversion.go
).
const statusUp = "UP" | ||
|
||
const ( | ||
basePath = "/eureka/v2" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should note in docs that this is hardcoded to Eureka v2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this be made configurable in the future at least?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1. Can't we use a config file or something to take in all these params?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. We might move to a Eureka library in the future as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was wrong in my original interpretation of this. The v2 endpoint has no relation to the v2 release of Eureka.
data: readFile(t, "testdata/eureka-apps.json"), | ||
apps: []*application{ | ||
{ | ||
Name: appName("foo.bar.local"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: This is fine for testing, but I don't think it is common to place a full DNS entry in the Eureka application name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, makes sense. The app name shouldn't matter at all for any of the actual logic, but I can change it so it is less confusing.
platform/eureka/controller.go
Outdated
if !reflect.DeepEqual(apps, cachedApps) { | ||
cachedApps = apps | ||
// TODO: feed with real events. | ||
// The handlers are being feed dummy events. This is sufficient with simplistic |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/feed/fed
Can I ask how heartbeats are being handled (haven't had a chance to review yet)? |
I probably just answered my own question in my mind, clients still handle registration and heartbeats, this is just another client, is that right? |
@spencergibb Yes client libraries embedded in the application will normally do this. Is pilot responsible for handling health-checks on each application? |
No. We just do discovery. Registration and heartbeats are application/platform's responsibility |
Thanks for the comments everyone, I think I addressed them all. Should be ready to merge, pending an approval. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good for a first cut. Bunch of nits and a few important TODOs (esp the reading port protocols from a file).
platform/eureka/controller.go
Outdated
continue | ||
} | ||
|
||
if !reflect.DeepEqual(apps, cachedApps) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1. Since we don't control how the Eureka server handles the order of registered instances, we should make this comparison deterministic on our end by sorting the apps before caching/comparison.
|
||
// Convert Eureka applications to services. If provided, only convert applications in the hostnames whitelist, | ||
// otherwise convert all. | ||
func convertServices(apps []*application, hostnames map[string]bool) map[string]*model.Service { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason to have this special case for filtering hostnames in the white list?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only for convenience. There are several places where we filter hostnames.
platform/eureka/conversion.go
Outdated
} | ||
|
||
func convertPorts(instance *instance) model.PortList { | ||
out := make(model.PortList, 0, 2) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add a comment stating that eureka instances have only two ports
|
||
service.Ports = append(service.Ports, port) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't you need to delete the service from the map if it has no ports attached to it? Is this possible in Eureka?
}, | ||
services: map[string]*model.Service{ | ||
"foo.bar.local": makeService("foo.bar.local", []int{5000}, nil), | ||
"foo.biz.local": makeService("foo.biz.local", []int{5000}, nil), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
may be have the protocol also here, for completeness ?
platform/eureka/servicediscovery.go
Outdated
} | ||
services := convertServices(apps, nil) | ||
|
||
// TODO: canonical ordering? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is a requirement else Envoy will go crazy. Use stable sort or whatever and make sure that the return value is deterministic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, missed that I hadn't dealt with that TODO
return out | ||
} | ||
|
||
const protocolMetadata = "istio.protocol" // metadata key for port protocol |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand that Eureka does not support protocols. But this would require changes to existing eureka clients or require people to update instance info out of band.
As part of the effort to read Eureka configuration from a file (e.g., the server's IPs, API base URL, etc., one can also imagine that the user provides a list of ports and their protocols - which can be used during runtime to lookup the protocols associated with a port). I leave it up to you to do this in this PR or in a follow up PR to add the ability to read this info from a statically supplied config file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The metadata can be supplied via a config file for the Eureka clients. Do you think that is reasonable? It would have to be a config file change on each Eureka client in your env.
For the alternative that you are suggesting, are you imagining a config file that the Istio discovery server would read?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes.. Because odds are, someone already has bunch of apps running on VMs or wherever. For these folks, do you think its easy to update the Eureka server with metadata info out of band and will this info remain in tact despite heartbeats etc. from apps?
platform/eureka/client.go
Outdated
} | ||
|
||
type instance struct { | ||
Hostname string `json:"hostName"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to the docs, hostName is used during access (not sure if its AWS specific), while there is also a virtualHostName and secureVirtualHostName(). Question is, when I say http://reviews.foo.local/getReviews, is reviews.foo.local
coming from hostName or virtualHostName ?
@cmluciano ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Talked to @seh about these:
- hostName should refer to the machine where the application resides.
- virtualHostName is similar to a VIP (Virtual IP) that a client could add
platform/eureka/client.go
Outdated
Status string `json:"status"` | ||
Port *port `json:"port,omitempty"` | ||
SecurePort *port `json:"securePort,omitempty"` | ||
Metadata metadata `json:"metadata,omitempty"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to docs, https://github.com/Netflix/eureka/wiki/Eureka-REST-operations, the instance also has a vipAddress. Is this equivalent to our service VIP address in K8S ? If so, may be worthwhile to include it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Eureka's VIPs aren't the same as k8s service addresses. VIP address can be used to obtain hostname/port pairs using the Eureka client, but the requests themselves are made to the hostname, not the VIP address.
We may have it in the future, but until then our linters get mad because it is an unused variable, so I've left it out. :)
platform/eureka/client.go
Outdated
Hostname string `json:"hostName"` | ||
App string `json:"app"` | ||
IPAddress string `json:"ipAddr"` | ||
Status string `json:"status"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a TODO to parse the datacenter info from instance (https://github.com/Netflix/eureka/wiki/Eureka-REST-operations) - this is needed to populate Envoy's AZ info per instance.
@jhspaybar would appreciate any feedback you may have :). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code-wise I think it's alright. We need a short explanation of how we map Eureka model into our data model (things like two-ports, hostnames, labels). Also, an integration test for a dummy eureka setup would be great.
Metadata metadata `json:"metadata,omitempty"` | ||
} | ||
|
||
type port struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- This isn't going to work with older Eureka servers.
See Preserve an instance's enabled status for its two ports hudl/fargo#59 for precedent in handling the differences.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW, pivotal doesn't support the older eureka servers. Maybe a documentation not on minimum supported eureka version?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Basic Eureka support. Forthcoming:
Note that TCP services will not work with Eureka until headless TCP services are supported in our proxy generation logic.