Open daniego opened 5 years ago
Hi, I'm seeing the same behavior as @daniego. Here is an example:
$ kubectl describe svc staging-consul-dns -n consul
Name: staging-consul-dns
Namespace: consul
Labels: app=consul
chart=consul-helm
heritage=Tiller
release=staging
Annotations: <none>
Selector: app=consul,hasDNS=true,release=staging
Type: ClusterIP
IP: 100.69.141.243
Port: dns-tcp 53/TCP
TargetPort: dns-tcp/TCP
Endpoints: 100.106.229.106:8600,100.114.45.206:8600,100.114.45.208:8600 + 6 more...
Port: dns-udp 53/UDP
TargetPort: dns-udp/UDP
Endpoints: 100.106.229.106:8600,100.114.45.206:8600,100.114.45.208:8600 + 6 more...
Session Affinity: None
Events: <none>
# curl localhost:8500/v1/catalog/service/staging-consul-dns
[
{
"ID": "",
"Node": "k8s-sync",
"Address": "127.0.0.1",
"Datacenter": "dc-staging",
"TaggedAddresses": null,
"NodeMeta": {
"external-source": "kubernetes"
},
"ServiceKind": "",
"ServiceID": "staging-consul-dns-4968a295cbbb",
"ServiceName": "staging-consul-dns",
"ServiceTags": [
"k8s"
],
"ServiceAddress": "100.116.16.124",
"ServiceWeights": {
"Passing": 1,
"Warning": 1
},
"ServiceMeta": {
"external-k8s-ns": "",
"external-source": "kubernetes",
"port-dns-tcp": "53",
"port-dns-udp": "53"
},
"ServicePort": 53,
"ServiceEnableTagOverride": false,
"ServiceProxyDestination": "",
"ServiceProxy": {},
"ServiceConnect": {},
"CreateIndex": 17130,
"ModifyIndex": 17130
},
{
"ID": "",
"Node": "k8s-sync",
"Address": "127.0.0.1",
"Datacenter": "dc-staging",
"TaggedAddresses": null,
"NodeMeta": {
"external-source": "kubernetes"
},
"ServiceKind": "",
"ServiceID": "staging-consul-dns-857593e28e5c",
"ServiceName": "staging-consul-dns",
"ServiceTags": [
"k8s"
],
"ServiceAddress": "100.106.229.106",
"ServiceWeights": {
"Passing": 1,
"Warning": 1
},
"ServiceMeta": {
"external-k8s-ns": "",
"external-source": "kubernetes",
"port-dns-tcp": "53",
"port-dns-udp": "53"
},
"ServicePort": 53,
"ServiceEnableTagOverride": false,
"ServiceProxyDestination": "",
"ServiceProxy": {},
"ServiceConnect": {},
"CreateIndex": 17117,
"ModifyIndex": 17117
},
{
"ID": "",
"Node": "k8s-sync",
"Address": "127.0.0.1",
"Datacenter": "dc-staging",
"TaggedAddresses": null,
"NodeMeta": {
"external-source": "kubernetes"
},
"ServiceKind": "",
"ServiceID": "staging-consul-dns-8917e803fbd6",
"ServiceName": "staging-consul-dns",
"ServiceTags": [
"k8s"
],
"ServiceAddress": "100.116.16.112",
"ServiceWeights": {
"Passing": 1,
"Warning": 1
},
"ServiceMeta": {
"external-k8s-ns": "",
"external-source": "kubernetes",
"port-dns-tcp": "53",
"port-dns-udp": "53"
},
"ServicePort": 53,
"ServiceEnableTagOverride": false,
"ServiceProxyDestination": "",
"ServiceProxy": {},
"ServiceConnect": {},
"CreateIndex": 17161,
"ModifyIndex": 17161
},
{
"ID": "",
"Node": "k8s-sync",
"Address": "127.0.0.1",
"Datacenter": "dc-staging",
"TaggedAddresses": null,
"NodeMeta": {
"external-source": "kubernetes"
},
"ServiceKind": "",
"ServiceID": "staging-consul-dns-92474e5d2418",
"ServiceName": "staging-consul-dns",
"ServiceTags": [
"k8s"
],
"ServiceAddress": "100.114.45.208",
"ServiceWeights": {
"Passing": 1,
"Warning": 1
},
"ServiceMeta": {
"external-k8s-ns": "",
"external-source": "kubernetes",
"port-dns-tcp": "53",
"port-dns-udp": "53"
},
"ServicePort": 53,
"ServiceEnableTagOverride": false,
"ServiceProxyDestination": "",
"ServiceProxy": {},
"ServiceConnect": {},
"CreateIndex": 17160,
"ModifyIndex": 17160
},
{
"ID": "",
"Node": "k8s-sync",
"Address": "127.0.0.1",
"Datacenter": "dc-staging",
"TaggedAddresses": null,
"NodeMeta": {
"external-source": "kubernetes"
},
"ServiceKind": "",
"ServiceID": "staging-consul-dns-b2d8e263de0c",
"ServiceName": "staging-consul-dns",
"ServiceTags": [
"k8s"
],
"ServiceAddress": "100.99.205.249",
"ServiceWeights": {
"Passing": 1,
"Warning": 1
},
"ServiceMeta": {
"external-k8s-ns": "",
"external-source": "kubernetes",
"port-dns-tcp": "53",
"port-dns-udp": "53"
},
"ServicePort": 53,
"ServiceEnableTagOverride": false,
"ServiceProxyDestination": "",
"ServiceProxy": {},
"ServiceConnect": {},
"CreateIndex": 17125,
"ModifyIndex": 17125
},
{
"ID": "",
"Node": "k8s-sync",
"Address": "127.0.0.1",
"Datacenter": "dc-staging",
"TaggedAddresses": null,
"NodeMeta": {
"external-source": "kubernetes"
},
"ServiceKind": "",
"ServiceID": "staging-consul-dns-cd67fdb76396",
"ServiceName": "staging-consul-dns",
"ServiceTags": [
"k8s"
],
"ServiceAddress": "100.120.187.109",
"ServiceWeights": {
"Passing": 1,
"Warning": 1
},
"ServiceMeta": {
"external-k8s-ns": "",
"external-source": "kubernetes",
"port-dns-tcp": "53",
"port-dns-udp": "53"
},
"ServicePort": 53,
"ServiceEnableTagOverride": false,
"ServiceProxyDestination": "",
"ServiceProxy": {},
"ServiceConnect": {},
"CreateIndex": 17131,
"ModifyIndex": 17131
},
{
"ID": "",
"Node": "k8s-sync",
"Address": "127.0.0.1",
"Datacenter": "dc-staging",
"TaggedAddresses": null,
"NodeMeta": {
"external-source": "kubernetes"
},
"ServiceKind": "",
"ServiceID": "staging-consul-dns-d893d20ed955",
"ServiceName": "staging-consul-dns",
"ServiceTags": [
"k8s"
],
"ServiceAddress": "100.114.45.206",
"ServiceWeights": {
"Passing": 1,
"Warning": 1
},
"ServiceMeta": {
"external-k8s-ns": "",
"external-source": "kubernetes",
"port-dns-tcp": "53",
"port-dns-udp": "53"
},
"ServicePort": 53,
"ServiceEnableTagOverride": false,
"ServiceProxyDestination": "",
"ServiceProxy": {},
"ServiceConnect": {},
"CreateIndex": 17164,
"ModifyIndex": 17164
},
{
"ID": "",
"Node": "k8s-sync",
"Address": "127.0.0.1",
"Datacenter": "dc-staging",
"TaggedAddresses": null,
"NodeMeta": {
"external-source": "kubernetes"
},
"ServiceKind": "",
"ServiceID": "staging-consul-dns-e672f0c6ce5c",
"ServiceName": "staging-consul-dns",
"ServiceTags": [
"k8s"
],
"ServiceAddress": "100.117.99.215",
"ServiceWeights": {
"Passing": 1,
"Warning": 1
},
"ServiceMeta": {
"external-k8s-ns": "",
"external-source": "kubernetes",
"port-dns-tcp": "53",
"port-dns-udp": "53"
},
"ServicePort": 53,
"ServiceEnableTagOverride": false,
"ServiceProxyDestination": "",
"ServiceProxy": {},
"ServiceConnect": {},
"CreateIndex": 17165,
"ModifyIndex": 17165
},
{
"ID": "",
"Node": "k8s-sync",
"Address": "127.0.0.1",
"Datacenter": "dc-staging",
"TaggedAddresses": null,
"NodeMeta": {
"external-source": "kubernetes"
},
"ServiceKind": "",
"ServiceID": "staging-consul-dns-f24c4cb3d420",
"ServiceName": "staging-consul-dns",
"ServiceTags": [
"k8s"
],
"ServiceAddress": "100.120.187.111",
"ServiceWeights": {
"Passing": 1,
"Warning": 1
},
"ServiceMeta": {
"external-k8s-ns": "",
"external-source": "kubernetes",
"port-dns-tcp": "53",
"port-dns-udp": "53"
},
"ServicePort": 53,
"ServiceEnableTagOverride": false,
"ServiceProxyDestination": "",
"ServiceProxy": {},
"ServiceConnect": {},
"CreateIndex": 17120,
"ModifyIndex": 17120
}
]
Hi, any update on this issue?
Hi Daniel, this is by design. We could make it configurable though.
Can you elaborate on your use-case as to why you want the clusterip registered rather than the individual endpoints?
DNS in Daniel's case, and statsd in my situation, are probably bad examples but generally I think it's safe to say that by sync'in endpoint addresses we lose out on all the affinity/balancing that the service ip address would do through kube-proxy and instead have to figure that out on the client side when we get 4 addresses back from Consul instead of just one.
It is also the case that by doing endpoint addresses it breaks the idea that a ClusterIP's Service's IP is fairly static and can be trusted to not disappear whereas the pods behind it can be ephemeral and disappear often. Why should discovering through Consul be different than the built-in records of my-svc.my-namespace.svc.cluster-domain.example
which return the single ClusterIP Service Address not all the pod addresses?
Perhaps introducing a new flag of --sync-clusterip-services-as-endpoints
with a default of true, and handling the logic when the flag is false here https://github.com/hashicorp/consul-k8s/blob/master/catalog/from-k8s/resource.go#L480 is the easiest and best approach to handle both use cases?
I like the idea of doing something like:
// annotationServiceAsEndpoints is valid only on ClusterIP services.
// It specifics whether or not to sync the service with each individual endpoint or
// as the singular IP of the service. If this isn't set then the
// default based on the syncer configuration is chosen.
annotationServiceAsEndpoints = "consul.hashicorp.com/service-as-endpoints"
as well.
But it looks like there is some of the resource.go
that tracks and watches endpoints which would need to be handled as well. Not sure if it's best to just by default track the IP and the endpoints or try to separate them.
Thanks for letting us know your use-case!
For background, the reason we sync Pod IPs instead of the ClusterIP is because we assumed the consumers of the synced services would not be running in Kubernetes and so wouldn't be able to use the Cluster IP (whereas Pod IPs might be routable in some clouds). This assumption is incorrect in your case 😄.
In my scenario I'm templating an HaProxy instance and need to use the cluster IP rather than the actual pods IPs to preserve the real client IP. Using the service DNS like my-svc.my-namespace.svc.cluster-domain.example
partially works. When haproxy starts it resolves the DNS and keep using the resolved IPs. If the service gets recreated the IP will change and HaProxy is not longer able to reach it.
There is any updated on this issue?
I think that @praymann described the use case very well. I would also like to see this implemented, in many scenarios service ips are also routable, same as pod ips. In that case it's preferable to use them as service endpoints for the same reasons services are implemented in k8s in the first place, to serve as persistent virtual ip l4 loadbalancers
Hi, I'm not sure if I missed something in my configuration but looks like that when a service is "ClusterIP" the sync-catalog synchronises the endpoint addresses rather than the actual clusterIP. Is that by design or there is a way to get the cluster IP and the ports?