I deployed Istio in a Kubernetes cluster hosted in AWS EKS. That created a Kubernetes service of type LoadBalancer named istio-ingressgateway with an external hostname of [redacted]-redacted.us-west-2.elb.amazonaws.com
, and automatically provisioned an AWS ELB, type classic. That's great. (Note: in AWS console I do not see a hosted zone for this elb hostname, it doesn't look like I can configure aliases or whatnot)
I've been able to connect a gRPC client running outside the cluster, to a gRPC server running in the cluster by defining an istio gateway which opens port 80 to host:"*"
, and defining an istio virtual service which routes port 80 to my destination (some port of some kubernetes service). So far so good.
Now I would like to do this for a second gRPC endpoint in the cluster. As far as I know, my choices are: either route by opening a second port (say 81) on the ingress (which I'm choosing not to do for now). Or route by defining subdomains of [redacted]-redacted.us-west-2.elb.amazonaws.com
, or route by implementing "virtual hosting", i.e. two services on the same domain where the client sends host:"svc1"
in a header.
This is where I'm stuck. I don't know how do define subdomains to this ELB domain name, and I don't know if I can do virtual hosting with TLS, and if so, can I still use the "passthrough" tls mode of Istio so as not to TLS-terminate on the gateway.
1- Using subdomains: When on my developer machine I try getent hosts svc1.[redacted]-redacted.us-west-2.elb.amazonaws.com
it does not map to an IP, whereas if remove the svc1
prefix DNS returns 3 IPs (guessing the 3 availability zones in us-west-2). So I can't prefix svc1 to the domain without some work.
Can I define subdomains svc1
and svc2
for a domain created by classic AWS ELB automatically provisioned by deploying Istio, and if so how? Can I do this with kubectl/istioctl
to configure Istio, or do I need to do this with the AWS CLI? Can this be done without registering a domain, i'm fine with that user-unfriendly elb.amazonaws.com hostname?
2- Virtual Hosting: Alternatively I could add a host=svc1 in the gRPC metadata. I tried adding ctx := metadata.AppendToOutgoingContext(context.Background(), "Host", "svc1")
to my Go client, that did not work.
Some guidance would be great.
Update 1, and one solution for plaintext
I'm reading on List of HTTP header fields the "Host" header should not be used in HTTP2. Given this is gRPC it is HTTP2 and as such I should not add this as a custom header in my gRPC client requests. The solution when doing virtual hosting, in a gRPC client instead of sending a "host" header, you send an ":Authority" header, the value must correspond to the host specified in istio's gateway+virtualservice. This works for me. In my Go client I had to add dialOptions = append(dialOptions, grpc.WithAuthority("[my-service-1]"))
.
That solution won't work for TLS according to GoDoc grpc.WithAuthority. So I still need to find how to route 2 services from the same external IP and port when TLS is used.
Update 1.1:
In virtual hosting, when TLS is used, the SNI can be passed in the CLIENT HELLO message, instead of being a gRPC header like in plaintext . Depending on your language the exact API is going to vary, but in Go I was able to pass the host name by setting the ServerName
field in tls.Config. You can then gate on that hostname in your istio gateway configuration, and route based on that value in your istio virtualservice.
Update 2: I tried, and failed, to create the subdomain on AWS Route53. First I create a public hosted zone for domain:[redacted]-redacted.us-west-2.elb.amazonaws.com. Next, in that hosted zone I create an A record with name=svc1.
[redacted]-redacted.us-west-2.elb.amazonaws.com, route=Alias to Classic Load Balancer, region=us-west-2, load balancer=dualstack.[redacted]-redacted.us-west-2.elb.amazonaws.com.
I later test the svc1.[redacted]-redacted.us-west-2.elb.amazonaws.com A record exists with dig
, which does not return an answer. However dig does return 3 A records for [redacted]-redacted.us-west-2.elb.amazonaws.com (without the svc1 prefix),with the IPs of 3 load balancers.