Open cam-stitt opened 7 years ago
Hey @cam-stitt and @peterbourgon! I'd like to get involved. Would you guys mind if I take a crack at this? 🙏
Please do! Before starting in with the code properly, I'd suggest doing a design phase, either just as a narrative in this issue or with a bit of pseudocode.
Guys apologies this took a while. Actually thinking about it a bit more, in this specific use-case go-kit
is performing the role of an ELB (or an ALB). So to get the ball rolling...
The EC2 implementation would generally follow the style of the implementations in package sd
.
Implementation Details (assume the new package is called ec2
)
There would be an internal method in ec2
for fetching instance host:port
(EC2 instance IPs in this case, using aws-sdk-go
) which updates sd.Cache
. Like what @cam-stitt mentioned, that would mean AWS API calls.
There will be no concrete implementation of the sd.Registrar
interface (similar to dnssrv
). It is assumed that the EC2 instance tagging (for newly provisioned instances) will be handled by a mechanism such as CloudFormation (which auto-tags instances if they're in an autoscaling group) or by some other means. We merely query the set of instances using a tag.
EC2 instance tag name:value
pair would be a constructor parameter.
Questions
Getting port
will be a bit tricky because there's no way to get which service is mapped to a given port (in the context of AWS that is). It can be inferred from the list of allowed ingress ports (via the security groups) but that could be error-prone. We could just pass that in as constructor parameter to this new SD. 🤔 WDYT?
Do we need to accomodate for the case where different EC2 instances are tagged the same name:value
pair are part of different CloudFormation stacks?
(a follow up from question #1
) if port
was passed as a constructor parameter, would we need to check if that port is reachable for all instances (i.e. the instance is healthy and there's no security group rule that's blocking access) before adding it to the list of instances.
💭 In case we get rate limited by the AWS API endpoint, would the best thing to do in this case is return stale data from sd.Cache
?
Your thoughts @peterbourgon, @cam-stitt?
My two cents:
service: addsvc
) on their instances. The CFN stacks should not concern us at all.Great feedback @peterbourgon, @cam-stitt!
OK, so taking into account your suggestions, here's a rough plan:
port
would be a constructor argument.service: addsvc
(customizable; could be a constructor argument as well i.e. tagName
).With that I'll get cracking with the implementation. PR coming 🔜 !
Just playing devils-advocate during your design phrase, given the functionality AWS has been delivering at the ALB layer (ssl certs, waf, dynamic port mapping of ecs services etc), under what sorts of scenarios would you expect to want to do service discovery at the ec2-instance level, over the alb-fronting-a-service level?
Hey thanks for the feedback @wyaeld. I've also mentioned this before:
Actually thinking about it a bit more, in this specific use-case go-kit is performing the role of an ELB (or an ALB).
I do agree that the current feature set of an ALB is enough to cover the majority of use cases. I'm happy to drop this task unless @peterbourgon and/or @cam-stitt can think of other scenarios where such a discovery functionality would be useful.
One issue with ALB is that it cannot be used in conjunction with GRPC (from all my tests and research). If you want to use GRPC, you have to still use ELB. Due to the popularity of GRPC in microservices, it seems like this still has a very valid use case.
We could add an EC2 service discovery package. EC2 allows for searching instances via tags. We could again use
aws-sdk-go
and manage fetching instances viaec2.DescribeInstances
.