我已经定义了一个ExternalName类型的服务
kind: Service
apiVersion: v1
metadata:
name: my-service
spec:
type: ExternalName
externalName: 'lstest.free.example.com'
当我运行curl -v http://my-service.default.svc.cluster.local/path我得到了一个错误,因为某些原因它解析为"domain.com"而不是"lstest.free.example.com"。这是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>
显然,如果我像这样运行
curl -v -H "Host: lstestfree.domain.com "My-service.default.svc.cluster.local/path -工作正常
如果我运行dig my-service.default.svc.cluster.local或网路资讯查询my-service.default.svc.cluster.local
都正确解析为' lstestfree.domain.com '
我可以让它在我的代码中工作,我手动解析服务和手动创建Uri,但它不能与第三方代码一起工作-像curl不工作。
从Kubernetes的角度来看,这个行为是正常的。
如果您将检查Kubernetes Documentation Service
关于Type ExternalName,您将发现警告信息。
警告:对于某些常见协议,包括HTTP和HTTPS,使用ExternalName可能会遇到问题。如果您使用ExternalName,则集群内客户端使用的主机名与ExternalName引用的名称不同。
对于使用主机名的协议,此差异可能导致错误或意外响应。HTTP请求将有一个主机:标头,源服务器不能识别;TLS服务器将无法提供与客户端连接到的主机名匹配的证书。
简而言之,从你的问题的行为是预期的工作。Curl
用Host header
中的service name
发送请求,远程主机不知道该服务名称,也没有这样的资源。您可以在curl响应中找到这些信息:
> GET /path HTTP/1.1
> Host: my-service.default.svc.cluster.local
> User-Agent: curl/7.64.0
Curl
不能扩展CNAMEs
,因此使用-H "Host: yuorhost"
或——resolve命令是不可避免的。
要实现您想要的,您需要将Host header
更改为远程web服务器所期望的内容。
您可以使用反向代理实现这一点。这样,你需要将ExternalName
指向本地reverse-proxy
(nginx pod),这将改变/重写Host header
。它应该被远程web服务器识别,并允许您连接到后端。
这个想法在这个ProxyPass和主机头重写指南中提出。
在这个Stackoverflow线程中,您可以找到一些额外的信息,如何使用proxy_pass
和proxy_set_header
将Nginx
pod配置为reverse-proxy
你也可以查看Nginx文档中有关反向代理的内容。