【问题标题】:Sending http request from kubernetes pod through ingress service to another pod in Minikube通过入口服务从 kubernetes pod 发送 http 请求到 Minikube 中的另一个 pod
【发布时间】:2021-01-23 08:44:59
【问题描述】:

我在 Oracle VM Virtualbox 中使用 Minikube 单节点 Kubernetes 集群。节点中的一个 pod 是基于 Next.js 的客户端,其余的 pod 是不同的微服务。假设我的客户端 (Pod1) 在渲染之前需要向身份验证微服务 (Pod2) 发送 HTTP 请求 - 参见图表: Minikube Cluster

下面是我的 ingress-service.yaml 文件:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-service
  annotations: 
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/use-regex: 'true'
spec:
  rules:
    - host: dummyweb.info
      http:
        paths:
          - path: /api/users/?(.*)
            backend:
              serviceName: auth-srv
              servicePort: 3000
          - path: /?(.*)
            backend:
              serviceName: client-srv
              servicePort: 3000

您可以看到每个服务都有一个特定的路径。因此,我想将 HTTP 请求从客户端(Pod1)发送到 Ingress Service,然后 Ingress 将请求重新路由到适当的服务,具体取决于路径。换句话说,居住在 Pod1 中的客户端将使用以下 URL 通过 Ingress Service 向居住在 Pod2 中的身份验证服务发送 HTTP GET 请求: http://<ingress-service-url>/api/users/.... 我需要弄清楚 Ingress 服务的 URL 是什么。

我启用了 NGINX Ingress 控制器:

minikube addons enable ingress

我验证了 NGINX Ingress 控制器正在运行:

kubectl get pods -n kube-system

NAME                                       READY   STATUS      RESTARTS   AGE
coredns-f9fd979d6-hfnfj                    1/1     Running     5          45h
etcd-minikube                              1/1     Running     5          45h
ingress-nginx-admission-create-dkthv       0/1     Completed   0          23h
ingress-nginx-admission-patch-4gtth        0/1     Completed   0          23h
ingress-nginx-controller-789d9c4dc-qdqxv   1/1     Running     3          23h
kube-apiserver-minikube                    1/1     Running     5          45h
kube-controller-manager-minikube           1/1     Running     5          45h
kube-proxy-sr6pt                           1/1     Running     5          45h
kube-scheduler-minikube                    1/1     Running     5          45h
storage-provisioner                        1/1     Running     11         45h

然后,我正在检查 kube-system 命名空间中有哪些服务可用:

kubectl get services -n kube-system

NAME                                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGE
ingress-nginx-controller-admission   ClusterIP   10.97.5.35   <none>        443/TCP                  24h
kube-dns                             ClusterIP   10.96.0.10   <none>        53/UDP,53/TCP,9153/TCP   45h

我假设 Ingress 服务的内部 URL 是:

http://ingress-nginx-controller-admission.kube-system.svc.cluster.local

正如我们在上面看到的,ingress-nginx-controller-admission 服务只公开了 443 端口,所以在 HTTP 请求中我收到以下错误:

Server Error
Error: connect ETIMEDOUT 10.97.5.35:80

This error happened while generating the page. Any console logs will be displayed in the terminal window.
Call Stack
<unknown> (Error: connect ETIMEDOUT
10.97.5.35 (80)
TCPConnectWrap.afterConnect [as oncomplete]
net.js (1145:16)
  1. 这是在 Minikube 中访问 Ingress 服务的正确内部 URL 吗?
  2. 如果是,如何打开80端口?

我对直接连接到身份验证服务不感兴趣。

【问题讨论】:

    标签: kubernetes kubernetes-ingress minikube


    【解决方案1】:

    上面描述的问题有一个非常简单的解决方案:

    1. 我假设您已经启用了入口插件。如果没有:minikube addons enable ingress
    2. 您需要 Helm 来安装 NGINX 入口控制器:
    helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
    helm install my-release ingress-nginx/ingress-nginx
    

    您可以将my-release 替换为您喜欢的任何内容。就我而言,这是dimi

    1. 检查默认命名空间中的可用服务:
    kubectl get services
    
    NAME                                      TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
    auth-mongo-srv                            ClusterIP      10.110.44.53     <none>        27017/TCP                    46m
    auth-srv                                  ClusterIP      10.106.154.84    <none>        3000/TCP                     46m
    client-srv                                ClusterIP      10.108.31.36     <none>        3000/TCP                     46m
    dimi-ingress-nginx-controller             LoadBalancer   10.102.12.127    <pending>     80:31599/TCP,443:32639/TCP   34m
    dimi-ingress-nginx-controller-admission   ClusterIP      10.102.171.116   <none>        443/TCP                      34m
    kubernetes                                ClusterIP      10.96.0.1        <none>        443/TCP                      58m
    nats-srv                                  ClusterIP      10.110.239.15    <none>        4222/TCP,8222/TCP            46m
    orders-mongo-srv                          ClusterIP      10.101.67.81     <none>        27017/TCP                    46m
    orders-srv                                ClusterIP      10.103.29.63     <none>        3000/TCP                     46m
    tickets-mongo-srv                         ClusterIP      10.107.137.160   <none>        27017/TCP                    46m
    tickets-srv                               ClusterIP      10.106.203.231   <none>        3000/TCP                     46m
    
    1. 现在我们有 dimi-ingress-nginx-controller 类型的 LoadBalancer 服务。因此,如果您需要处理服务器端渲染 (SSR) 并将 HTTP 请求从一个 pod(运行 Next.js 应用程序的地方)发送到您的一个微服务(即在不同的 pod 中运行),请在页面之前甚至呈现,您可以将请求发送到http://dimi-ingress-nginx-controller.default.svc.cluster.local/&lt;path_set_in_the_Ingress_Resource&gt;。 例如,如果我的 Next.js 应用程序需要向我的 Auth 微服务发送请求,则 URL 将为:http://dimi-ingress-nginx-controller.default.svc.cluster.local/api/users。这样一来,HTTP(S) 流量将由 Ingress Resource 处理,其中我们已经有一个与所有传入请求匹配的规则列表。

    【讨论】:

      【解决方案2】:

      请记住,Ingress 是一种单独的资源类型。它不是ServiceHere 您可以阅读 kubernetes 中获取 DNS 名称的内容,而 Ingress 不在其中。

      如果您想连接到您的应用,通过Ingress 公开,只需执行以下命令:

      kubectl get ingress
      

      它将向您显示其 IP 地址,您应该能够从您的 Pod 中以任何其他方式 curl 或发送 HTTP GET 请求。下面是我的示例的输出:

      $ kubectl get ingress
      NAME              HOSTS              ADDRESS     PORTS   AGE
      example-ingress   hello-world.info   10.0.2.15   80      5m54s
      

      现在我们可以将kubectl exec 连接到另一个Pod 并连接到我们在另一个Pod 中运行的应用程序,通过Ingress 公开:

      $ kubectl exec -ti static-web -- /bin/bash
      root@static-web:/# curl --header 'Host: hello-world.info' http://10.0.2.15
      Hello, world!
      Version: 1.0.0
      Hostname: web-9bbd7b488-qvg85
      root@static-web:/#
      

      如果您更愿意使用 DNS 名称,您可以随时将您的 dummyweb.info 域添加到您的 Pod/etc/hosts 文件中。你可以阅读如何做到这一点here

      如果您没有指定正确的主机名(正如您在上面看到的,我在 http 请求的标头中指定了它),您无论如何都会得到 404

      root@static-web:/# curl http://10.0.2.15
      <html>
      <head><title>404 Not Found</title></head>
      <body>
      <center><h1>404 Not Found</h1></center>
      <hr><center>openresty/1.15.8.1</center>
      </body>
      </html>
      

      【讨论】:

      • 感谢马里奥的回复。 kubectl get ingress 会给你 Ingress 的外部 IP 地址。您不能从 pod 向该 IP 地址发送 HTTP 请求。另外,使用kubectl exec 发送HTTP 请求到另一个pod 中的应用程序/微服务,我感觉很不对劲。我找到了一个解决方案,它非常“minikube”特定。我将发布一个单独的详细答案。
      • "kubectl get ingress 会给你 Ingress 的外部 IP 地址" - 好吧,我不会完全同意。正如您在我的 Minikube 实例中所看到的,它还可以为您提供一个内部 IP。我的答案中的输出是真实的。你能解释一下你在附加到Pod 时看到了什么错误,你需要从中测试到通过ingress 暴露的其他Pods 的连接性?没有人使用kubectl exec 发送 HTTP 请求。它仅用于附加到Pod。如您所见,curl 用于向ingress 地址发送HTTP 请求,这里是10.0.2.15
      • @DimitarGeorgiev 使 nginx 入口在内部可用(使用内部 IP)使用 kubectl expose deployment -n kube-system ingress-nginx-controller --port 80。它将创建一个 ClusterIP 类型的服务和一个域的 DNS 记录:ingress-nginx-controller。但请记住,如果您使用基于域的入口路由,则需要手动传递 Host 标头以进行请求。这可以解决您的问题吗?
      猜你喜欢
      • 1970-01-01
      • 2020-08-12
      • 1970-01-01
      • 2019-04-23
      • 2020-06-24
      • 1970-01-01
      • 2021-09-17
      • 2021-08-10
      • 2020-07-27
      相关资源
      最近更新 更多