首页 > 解决方案 > 从集群内部调用外部 API

问题描述

我想从集群内部调用一个外部 api,所以我遵循了 Kubernetes 文档

如下:

apiVersion: v1
kind: Service
metadata:
  name: my-service
  namespace: prod
spec:
  type: ExternalName
  externalName: https://api.github.com/

我能够得到一个带有外部名称的响应:

externalName: httpbin.org

但是当我使用 http 或 https 端点时,它会失败。

我知道文档说明了以下内容

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.

但我想知道如何从集群内部对外部 API 进行 http/https 调用?

标签: kuberneteskubernetes-ingresskong

解决方案


但我想知道如何从集群内部对外部 API 进行 http/https 调用?

我看不出你有什么理由不直接从集群调用外部 API 而不使用ExternalName. 您实际上并不需要那种类型的服务来做到这一点。除非有什么你没有在这里告诉我们的。

现在继续讨论您遇到错误的原因。使用ExternalName服务类型,请求到达您的目的地Host: my-service,他继承自您创建的服务。如果我们举一个api.github.com你提到的例子,一旦尝试到达它就会收到http带有标头的请求,Host: my-service他不知道如何处理它,也不会将它路由到哪里。因此,如果您预先确定要使用,api.github.com为什么不直接使用它呢?

请参阅此处的示例,该示例显示了header注入ExternalName(我将服务命名为 service my-service-test):

[root@cent /]# curl my-service-test -v
* About to connect() to my-service-test port 80 (#0)
*   Trying 183.36.108.201...
* Connected to my-service-test (183.36.108.201) port 80 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.29.0
> Host: my-service-test  
> Accept: */*
> 
< HTTP/1.1 400 Bad Request
< Server: nginx
< Date: Thu, 08 Apr 2021 07:44:38 GMT
< Content-Type: text/html
< Content-Length: 166
< Connection: close
< X-Proxy-Server: Sparta
< 
<html>
<head><title>400 Bad Request</title></head>
<body bgcolor="white">
<center><h1>400 Bad Request</h1></center>
<hr><center>nginx</center>
</body>
</html>
* Closing connection 0 

Nginx 收到了请求,但host标头是否与他的预期不符,因此他没有处理它。

解决方法可能是使用 nginx pod 作为代理,或者使用入口尝试在头部到达所需目标之前重写头部。


推荐阅读