对另一个 Kubernetes 容器的 GET 请求的正确 URL 是多少?

What is the correct URL to use for GET requests to another Kubernetes container?

我正在尝试创建一个简单的微服务,其中一个 Docker 容器中的 JQuery 应用程序使用此代码从另一个(分析)应用程序获取 JSON 对象在不同的容器中运行:

<script type="text/javascript">
$(document).ready(function(){
$('#get-info-btn').click(function(){
  $.get("http://localhost:8084/productinfo", 
  function(data, status){          
    $.each(data, function(i, obj) {
      //some code
    });   
  });
});
});
</script> 

另一个应用程序将其用于 Deployment 容器端口。

  ports:
    - containerPort: 8082

这些用于 Service 端口。

  type: ClusterIP
  ports:
    - targetPort: 8082
      port: 8084   

'analytics' 应用程序是一个监听 8082 的 golang 程序。

func main() {
    http.HandleFunc("/productinfo", getInfoJSON)    
    log.Fatal(http.ListenAndServe(":8082", nil))
}

当 运行 在 Minikube 上执行此操作时,我遇到了 CORS 问题,当 return 将 JSON 对象作为响应时,通过在 golang 代码中使用此问题得到了解决:

w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type") 

所有这些在 Minikube 上运行良好(尽管在 Minikube 中我使用的是 localhost:8082)。第一个应用程序将向 http://localhost:8084/productinfo 发送 GET 请求,第二个应用程序将 return 一个 JSON 对象。

但是当我通过 : 访问第一个应用程序在云 Kubernetes 设置上尝试它时,当我打开浏览器控制台时,我不断收到错误 Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:8084/productinfo

问题: 为什么它在 Minikube 上工作而不在云 Kubernetes 工作节点上工作?使用 localhost 是访问另一个容器的正确方法吗?我怎样才能让它工作?实施微服务的人如何跨容器使用他们的 GET 和 POST 请求?我发现的所有微服务示例都是为 Minikube 上的简单演示而构建的,因此很难掌握这种细微差别。

@P.... 完全正确,我只是想提供一些关于 DNS for Services 和同一 Pod 中容器之间通信的更多细节。

服务的 DNS

正如我们在 documentation 中发现的那样,Kubernetes 服务被分配了一个 DNS A(或 AAAA)记录,其名称形式为 <serviceName>.<namespaceName>.svc.<cluster-domain>。这解析为服务的集群 IP。

"Normal" (not headless) Services are assigned a DNS A or AAAA record, depending on the IP family of the service, for a name of the form my-svc.my-namespace.svc.cluster-domain.example. This resolves to the cluster IP of the Service.

让我们将表格 <serviceName>.<namespaceName>.svc.<cluster-domain> 分解为各个部分:

  • <serviceName> - 您要连接的服务的名称。

  • <namespaceName> - 要连接的服务所在的命名空间的名称。

  • svc - 这不应更改 - svc 代表服务。

  • <cluster-domain> - 集群域,默认为cluster.local.

我们可以使用 <serviceName> 访问同一命名空间中的服务,但是我们也可以使用 <serviceName>.<namespaceName><serviceName>.<namespaceName>.svc 或 FQDN <serviceName>.<namespaceName>.svc.<cluster-domain>.

如果Service在不同的Namespace中,一个<serviceName>是不够的,我们需要使用<serviceName>.<namespaceName>(我们也可以使用:<serviceName>.<namespaceName>.svc<serviceName>.<namespaceName>.svc.<cluster-domain>).

在以下示例中,app-1app-2 位于同一命名空间中,并且 app-2 在端口 8084 上通过 ClusterIP 公开(如您的情况):

$ kubectl run app-1 --image=nginx
pod/app-1 created

$ kubectl run app-2 --image=nginx
pod/app-2 created

$ kubectl expose pod app-2 --target-port=80 --port=8084
service/app-2 exposed

$ kubectl get pod,svc
NAME        READY   STATUS    RESTARTS   AGE
pod/app-1   1/1     Running   0          45s
pod/app-2   1/1     Running   0          41s

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
service/app-2        ClusterIP   10.8.12.83   <none>        8084/TCP   36s

注意: app-2app-1 在同一个命名空间中,因此我们可以使用 <serviceName>app-1,您还可以注意到我们得到了 app-2 (app-2.default.svc.cluster.local) 的 FQDN:

$ kubectl exec -it app-1 -- bash
root@app-1:/# nslookup app-2
Server:         10.8.0.10
Address:        10.8.0.10#53

Name:   app-2.default.svc.cluster.local
Address: 10.8.12.83

注意: 我们需要提供端口号,因为 app-2 正在侦听 8084:

root@app-1:/# curl app-2.default.svc.cluster.local:8084
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...

让我们在不同的命名空间中创建 app-3,看看如何从 app-1:

连接到它
$ kubectl create ns test-namespace
namespace/test-namespace created

$ kubectl run app-3 --image=nginx -n test-namespace
pod/app-3 created

$ kubectl expose pod app-3 --target-port=80 --port=8084 -n test-namespace
service/app-3 exposed

注意: 使用app-3<serviceName>)是不够的,我们还需要提供[=45=所在的命名空间的名称] 驻留 (<serviceName>.<namespaceName>):

# nslookup app-3
Server:         10.8.0.10
Address:        10.8.0.10#53

** server can't find app-3: NXDOMAIN

# nslookup app-3.test-namespace
Server:         10.8.0.10
Address:        10.8.0.10#53

Name:   app-3.test-namespace.svc.cluster.local
Address: 10.8.12.250

# curl app-3.test-namespace.svc.cluster.local:8084
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...

同一 Pod 中容器之间的通信

我们可以使用localhost与其他容器通信,但是只能在同一个Pod(多容器pods)内。

我用两个容器创建了一个简单的多容器 Pod:nginx-containeralpine-container:

$ cat multi-container-app.yml
apiVersion: v1
kind: Pod
metadata:
  name: multi-container-app
spec:
  containers:
  - image: nginx
    name: nginx-container
  - image: alpine
    name: alpine-container
    command: ["sleep", "3600"]

$ kubectl apply -f multi-container-app.yml
pod/multi-container-app created

我们可以连接到 alpine-container 容器并检查我们是否可以使用 localhost:

访问位于 nginx-container 的 nginx 网络服务器
$ kubectl exec -it multi-container-app -c alpine-container -- sh

/ # netstat -tulpn
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      -
tcp        0      0 :::80                   :::*                    LISTEN      -

/ # curl localhost
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...

有关同一 Pod 中容器之间通信的更多信息,请参见