Reputation: 19
I have defined an ExternalName type service
kind: Service
apiVersion: v1
metadata:
name: my-service
spec:
type: ExternalName
externalName: 'lstest.free.example.com'
when I run curl -v http://my-service.default.svc.cluster.local/path I got an error because for some reasons it resolved to 'domain.com' and not 'lstest.free.example.com' this is a response from curl
Connected to my-service.default.svc.cluster.local (165.227.26.218) port 80 (#0)
> GET /path HTTP/1.1
> Host: my-service.default.svc.cluster.local
> User-Agent: curl/7.64.0
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Server: nginx
< Date: Sat, 16 Jan 2021 00:23:05 GMT
< Content-Type: text/html
< Content-Length: 178
< Connection: keep-alive
< Location: https://example.com/path
<
<html>
<head><title>301 Moved Permanently</title></head>
<body bgcolor="white">
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx</center>
</body>
</html>
Obviously, if I run it like this
curl -v -H "Host:lstest.free.domain.com" my-service.default.svc.cluster.local/path - it works correctly.
If I run dig my-service.default.svc.cluster.local or nslookup my-service.default.svc.cluster.local
both are resolved correctly to 'lstest.free.domain.com'
I can make it work in my code where I resolve service manually and manually create Uri but it does not work with 3rd party code - like curl does not work.
Upvotes: 1
Views: 3088
Reputation: 14112
This behavior is working as intended from Kubernetes Point of view.
If you will check Kubernetes Documentation Service
about Type ExternalName you will find Warning information.
Warning: You may have trouble using ExternalName for some common protocols, including HTTP and HTTPS. If you use ExternalName then the hostname used by clients inside your cluster is different from the name that the ExternalName references.
For protocols that use hostnames this difference may lead to errors or unexpected responses. HTTP requests will have a Host: header that the origin server does not recognize; TLS servers will not be able to provide a certificate matching the hostname that the client connected to.
In short, behavior from your question is working as intended. Curl
sends request with a service name
in Host header
and remote host is not aware of that service name and doesn't have such resources. You can find this information in your curl response:
> GET /path HTTP/1.1
> Host: my-service.default.svc.cluster.local
> User-Agent: curl/7.64.0
Curl
can't expand CNAMEs
, so using -H "Host: yuorhost"
or --resolve command is inevitable.
To achieve what you want, you would need to change Host header
to something expected by a remote web server.
You could achieve that using reverse-proxy. In this way you would neet do point ExternalName
to local reverse-proxy
(nginx pod) which would change/rewrite Host header
. It should be recognized by a remote web server and allow you connect to the backend.
This idea was presented in this ProxyPass and Host Header Rewrite guide.
In this Stackoverflow thread you can find some additional information how you could configure Nginx
pod as reverse-proxy
using proxy_pass
and proxy_set_header
You can also check Nginx Docs regarding Reverse Proxy.
Upvotes: 2