istio: 404 if VirtualService.spec.hosts is set to FQDN
Describe the bug
I tried to see how the basic examples in the official istio docs work. Everything works as prescribed but only as long as VirtualService.spec.hosts == "*"
. When I set it to fully qualified domain name (FQDN) envoy is giving me 404.
Expected behavior Get response from the configured service.
Steps to reproduce the bug
Set up local hosts
file:
# echo 'xxx.yyy.122.33 bookinfo.example.com' > /etc/hosts
Create custom Namespace
with enabled automatic istio sidecar injection:
---
apiVersion: v1
kind: Namespace
metadata:
name: bookinfo
labels:
istio-injection: enabled
---
Deploy bookinfo components in that Namespace
:
$ kubectl create -f https://raw.githubusercontent.com/istio/istio/release-1.0/samples/bookinfo/platform/kube/bookinfo.yaml
service "details" created
deployment.extensions "details-v1" created
service "ratings" created
deployment.extensions "ratings-v1" created
service "reviews" created
deployment.extensions "reviews-v1" created
deployment.extensions "reviews-v2" created
deployment.extensions "reviews-v3" created
service "productpage" created
deployment.extensions "productpage-v1" created
$ kubectl get po
NAME READY STATUS RESTARTS AGE
details-v1-876bf485f-2d4sr 2/2 Running 0 16s
productpage-v1-8d69b45c-p7kmn 2/2 Running 0 15s
ratings-v1-7c9949d479-k55cb 2/2 Running 0 15s
reviews-v1-85b7d84c56-xgl8m 2/2 Running 0 15s
reviews-v2-cbd94c99b-79lx2 2/2 Running 0 15s
reviews-v3-748456d47b-kplrb 2/2 Running 0 15s
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
details ClusterIP 10.30.224.45 <none> 9080/TCP 20s
productpage ClusterIP 10.30.111.5 <none> 9080/TCP 19s
ratings ClusterIP 10.30.50.27 <none> 9080/TCP 20s
reviews ClusterIP 10.30.93.28 <none> 9080/TCP 19s
Declare Gateway
and VirtualService
:
---
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
namespace: bookinfo
name: bookinfo-gw
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
protocol: HTTP
name: http
hosts:
- bookinfo.example.com
---
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
namespace: bookinfo
name: bookinfo-virt-svc
spec:
gateways:
- bookinfo-gw
hosts:
- "*"
http:
- route:
- destination:
host: productpage.bookinfo.svc.cluster.local
port:
number: 9080
---
Deploy Gateway
and VirtualService
:
$ kubectl create -f istio-test.yaml
gateway.networking.istio.io "bookinfo-gw" created
virtualservice.networking.istio.io "bookinfo-virt-svc" created
Test connectivity:
$ curl -LsD- -o /dev/null bookinfo.example.com:31380
HTTP/1.1 200 OK
content-type: text/html; charset=utf-8
content-length: 1836
server: envoy
date: Mon, 18 Feb 2019 17:19:32 GMT
x-envoy-upstream-service-time: 25
Up to this point everything has been configured pretty much according to the book.
Now change VirtualService.spec.hosts
to bookinfo.example.com
:
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
namespace: bookinfo
name: bookinfo-virt-svc
spec:
gateways:
- bookinfo-gw
hosts:
- bookinfo.example.com
http:
- route:
- destination:
host: productpage.bookinfo.svc.cluster.local
port:
number: 9080
---
Deploy it:
$ kubectl replace -f istio-test.yaml
virtualservice.networking.istio.io "bookinfo-virt-svc" replaced
Test the connectivity:
$ curl -LsD- -o /dev/null bookinfo.example.com:31380
HTTP/1.1 404 Not Found
date: Mon, 18 Feb 2019 17:23:23 GMT
server: envoy
content-length: 0
Some debugging info:
$ istioctl proxy-config routes istio-ingressgateway-78c6d8b8d7-pdtb8 -n istio-system -o json
[
{
"name": "http.80",
"virtualHosts": [
{
"name": "bookinfo.example.com:80",
"domains": [
"bookinfo.example.com",
"bookinfo.example.com:80"
],
"routes": [
{
"match": {
"prefix": "/"
},
"route": {
"cluster": "outbound|9080||productpage.bookinfo.svc.cluster.local",
"timeout": "0.000s",
"maxGrpcTimeout": "0.000s"
},
"decorator": {
"operation": "productpage.bookinfo.svc.cluster.local:9080/*"
},
"perFilterConfig": {
"mixer": {
"forward_attributes": {
"attributes": {
"destination.service": {
"string_value": "productpage.bookinfo.svc.cluster.local"
},
"destination.service.host": {
"string_value": "productpage.bookinfo.svc.cluster.local"
},
"destination.service.name": {
"string_value": "productpage"
},
"destination.service.namespace": {
"string_value": "bookinfo"
},
"destination.service.uid": {
"string_value": "istio://bookinfo/services/productpage"
}
}
},
"mixer_attributes": {
"attributes": {
"destination.service": {
"string_value": "productpage.bookinfo.svc.cluster.local"
},
"destination.service.host": {
"string_value": "productpage.bookinfo.svc.cluster.local"
},
"destination.service.name": {
"string_value": "productpage"
},
"destination.service.namespace": {
"string_value": "bookinfo"
},
"destination.service.uid": {
"string_value": "istio://bookinfo/services/productpage"
}
}
}
}
}
}
]
}
],
"validateClusters": false
},
{
"virtualHosts": [
{
"name": "backend",
"domains": [
"*"
],
"routes": [
{
"match": {
"prefix": "/stats/prometheus"
},
"route": {
"cluster": "prometheus_stats"
}
}
]
}
]
}
]
Version
$ kubectl version --short
Client Version: v1.12.4
Server Version: v1.12.4
$ istioctl version
Version: 1.0.5
GitRevision: c1707e45e71c75d74bf3a5dec8c7086f32f32fad
User: root@6f6ea1061f2b
Hub: docker.io/istio
GolangVersion: go1.10.4
BuildStatus: Clean
Installation
#! /bin/bash --
helm template install/kubernetes/helm/istio\
--name istio\
--namespace istio-system\
--set kiali.enabled=true\
--set grafana.enabled=true\
--set tracing.enabled=true\
--set servicegraph.enabled=true |\
sed 's/type: LoadBalancer/type: NodePort/'
Environment Bare-metal server
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Comments: 20 (7 by maintainers)
@narun4sk try to use authority match, instead of using host headers in your VirtualService
@zhongfox this stackoverflow question answers that: https://stackoverflow.com/questions/2142910/whats-the-difference-between-uri-host-and-uri-authority.
Authority -> host + port Host -> host
It’s also important to note that this question isn’t asking about FQDNs 😃. Any FQDN is a domain terminated with
.
indicating the domain root. Otherwise it’s a relative domain. This question is about domain + port matching.I have checked this issue on the istio version (1.4.6, 1.4.7, 1.5.2) and it’s still there. So if you are using a custom ports to connect to service - envoy will receive header as domain:port and it will cause a problem that envoy can not match expected domain name and received domain:port. As a temporary workaround - you can create a nginx proxy with config like:
http://nginx.org/en/docs/stream/ngx_stream_core_module.html
Another workaround might be to use the same port as your NodePort (31380) in your Istio ingressgateway service port and target port and then setup the Gateway with port 31380.
This will ensure that Host:31380 is accepted by the ingress proxy as the Gateway port will be added to the host declared in the VirtualService resource.
I also tried the following configuration but it too is giving me 404:
It’s a very basic use case, so I’m assuming there must be a workaround. Can I somehow configure istio to accept traffic on the NodePort?
It seems I cannot set
VirtualService.spec.hosts
like this:Istio returns validation error:
Currently I confirm that I have to explicitly set the
Host
header, to make it work…By default, the host in header is
bookinfo.example.com:31380
As can be seen from above, the routable domains are "
domains": [ "bookinfo.example.com", "bookinfo.example.com:80" ],
so this is expected, you can access by specify -H"host: bookinfo.example.com"