nginx - Ingress 不转发请求 - 适用于 Windows 和 kubernetes 的 Docker 桌面

标签 nginx kubernetes nginx-ingress docker-desktop

编辑:

我删除了 minikube,在适用于 Windows 的 Docker 桌面中启用了 kubernetes,并手动安装了 ingress-nginx

$helm upgrade --install ingress-nginx ingress-nginx --repo https://kubernetes.github.io/ingress-nginx --namespace ingress-nginx --create-namespace
Release "ingress-nginx" does not exist. Installing it now.
Error: rendered manifests contain a resource that already exists. Unable to continue with install: ServiceAccount "ingress-nginx" in namespace "ingress-nginx" exists and cannot be imported into the current release: invalid ownership metadata; annotation validation error: missing key "meta.helm.sh/release-name": must be set to "ingress-nginx"; annotation validation error: missing key "meta.helm.sh/release-namespace": must be set to "ingress-nginx"

它给了我一个错误,但我认为这是因为我之前已经这样做过,因为:

$kubectl get svc -n ingress-nginx
NAME                                 TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-controller             LoadBalancer   10.106.222.233   localhost     80:30199/TCP,443:31093/TCP   11m
ingress-nginx-controller-admission   ClusterIP      10.106.52.106    <none>        443/TCP                      11m

然后再次应用我的所有 yaml 文件,但这次 ingress 没有获取任何地址:

$kubectl get ing
NAME                CLASS    HOSTS       ADDRESS   PORTS   AGE
myapp-ingress       <none>   myapp.com             80      10m

我正在使用 docker 桌面(Windows)并通过 minikube addons enable 命令安装了 nginx-ingress Controller :

$kubectl get pods -n ingress-nginx
NAME                                        READY   STATUS      RESTARTS   AGE
ingress-nginx-admission-create--1-lp4md     0/1     Completed   0          67m
ingress-nginx-admission-patch--1-jdkn7      0/1     Completed   1          67m
ingress-nginx-controller-5f66978484-6mpfh   1/1     Running     0          67m

并应用了我所有的 yaml 文件:

$kubectl get svc --all-namespaces -o wide
NAMESPACE       NAME                                 TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE   SELECTOR
default         event-service-svc                    ClusterIP      10.108.251.79    <none>        80/TCP                       16m   app=event-service-app
default         kubernetes                           ClusterIP      10.96.0.1        <none>        443/TCP                      16m   <none>
default         mssql-clusterip-srv                  ClusterIP      10.98.10.22      <none>        1433/TCP                     16m   app=mssql
default         mssql-loadbalancer                   LoadBalancer   10.109.106.174   <pending>     1433:31430/TCP               16m   app=mssql
default         user-service-svc                     ClusterIP      10.111.128.73    <none>        80/TCP                       16m   app=user-service-app
ingress-nginx   ingress-nginx-controller             NodePort       10.101.112.245   <none>        80:31583/TCP,443:30735/TCP   68m   app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx
ingress-nginx   ingress-nginx-controller-admission   ClusterIP      10.105.169.167   <none>        443/TCP                      68m   app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx
kube-system     kube-dns                             ClusterIP      10.96.0.10       <none>        53/UDP,53/TCP,9153/TCP       72m   k8s-app=kube-dns

所有 Pod 和服务似乎都运行正常。检查 Pod 日志,所有迁移等均已生效,并且应用程序已启动并运行。但是当我尝试发送 HTTP 请求时,出现套接字挂断错误。我检查了所有 Pod 的所有日志,找不到任何有用的内容。

$kubectl get ingress
NAME                CLASS   HOSTS           ADDRESS     PORTS   AGE
myapp-ingress   nginx   myapp.com       localhost   80      74s

这个也有点奇怪,我期望 ADRESS 设置为 IP,而不是本地主机。因此,在/etc/hosts 中添加 myapp.com 的 127.0.0.1 条目似乎也不那么正确。

我的问题是我可能做错了什么?或者我怎样才能追踪我的请求被转发到哪里?

入口-svc.yaml

  apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: myapp-ingress
    spec:
      rules:
      - host: myapp.com
        http:
          paths:
          - path: /api/Users
            pathType: Prefix
            backend:
              service:
                name: user-service-svc
                port:
                  number: 80
          - path: /api/Events
            pathType: Prefix
            backend:
              service:
                name: event-service-svc
                port:
                  number: 80

事件-depl.yaml:

  apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: event-service-app
      labels:
        app: event-service-app
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: event-service-app
      template:
        metadata:
          labels:
            app: event-service-app
        spec:
          containers:
            - name: event-service-app
              image: ghcr.io/myapp/event-service:master
              imagePullPolicy: Always
              ports:
                - containerPort: 80
          imagePullSecrets:
            - name: myapp
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: event-service-svc
    spec:
      selector:
        app: event-service-app
      ports:
        - protocol: TCP
          port: 80
          targetPort: 80

最佳答案

复制

我使用 minikube v1.24.0 重现了该案例, Docker 桌面 4.2.0 ,发动机20.10.10

首先,localhost ingress 由于逻辑而出现,/etc/hosts 中的域后面的 IP 地址是什么并不重要。 ,我添加了一个不同的测试,但它仍然显示 localhost。仅metallb将提供来自设置网络的 IP 地址。

发生了什么

当 minikube 驱动程序为 docker 时,minikube 创建一个大容器(VM),在其中运行 kubernetes 组件。可以通过运行 docker ps 来检查主机系统中的命令:

$ docker ps

CONTAINER ID   IMAGE                                 COMMAND                  CREATED          STATUS          PORTS                                                                                                                                  NAMES
f087dc669944   gcr.io/k8s-minikube/kicbase:v0.0.28   "/usr/local/bin/entr…"   16 minutes ago   Up 16 minutes   127.0.0.1:59762->22/tcp, 127.0.0.1:59758->2376/tcp, 127.0.0.1:59760->5000/tcp, 127.0.0.1:59761->8443/tcp, 127.0.0.1:59759->32443/tcp   minikube

然后minikube ssh进入此容器并运行 docker ps查看所有 kubernetes 容器。

继续前进。介绍之前ingress ,已经很清楚即使 NodePort不按预期工作。我们来检查一下。

有两种方式获取minikube VM IP :

  1. 运行minikube IP
  2. kubectl get nodes -o wide并找到节点的IP

NodePort 接下来会发生什么请求应发送至 minikube_IP:Nodeport虽然它不起作用。发生这种情况是因为 minikube VM 内的 docker 容器没有暴露在集群之外,而集群是另一个 docker 容器。

关于 minikube要访问集群内的服务,有一个特殊命令 - minikube service %service_name% 这将创建一个到 minikube VM 内的服务的直接隧道(您可以看到它包含 service URLNodePort 应该可以工作):

$ minikube service echo

|-----------|------|-------------|---------------------------|
| NAMESPACE | NAME | TARGET PORT |            URL            |
|-----------|------|-------------|---------------------------|
| default   | echo |        8080 | http://192.168.49.2:32034 |
|-----------|------|-------------|---------------------------|
* Starting tunnel for service echo.
|-----------|------|-------------|------------------------|
| NAMESPACE | NAME | TARGET PORT |          URL           |
|-----------|------|-------------|------------------------|
| default   | echo |             | http://127.0.0.1:61991 |
|-----------|------|-------------|------------------------|
* Opening service default/echo in default browser...
! Because you are using a Docker driver on windows, the terminal needs to be open to run it

现在它可以在主机上使用:

$ curl http://127.0.0.1:61991/

StatusCode        : 200
StatusDescription : OK

添加入口

继续前进并添加入口。

$ minikube addons enable ingress
$ kubectl get svc -A

NAMESPACE       NAME                                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
default         echo                                 NodePort    10.111.57.237   <none>        8080:32034/TCP               25m
ingress-nginx   ingress-nginx-controller             NodePort    10.104.52.175   <none>        80:31041/TCP,443:31275/TCP   2m12s

尝试从 ingress 获取任何响应点击 minikube_IP:NodePort运气不佳:

$ curl 192.168.49.2:31041

curl : Unable to connect to the remote server
At line:1 char:1
+ curl 192.168.49.2:31041

尝试使用 minikube service 创建隧道命令:

$ minikube service ingress-nginx-controller -n ingress-nginx

|---------------|--------------------------|-------------|---------------------------|
|   NAMESPACE   |           NAME           | TARGET PORT |            URL            |
|---------------|--------------------------|-------------|---------------------------|
| ingress-nginx | ingress-nginx-controller | http/80     | http://192.168.49.2:31041 |
|               |                          | https/443   | http://192.168.49.2:31275 |
|---------------|--------------------------|-------------|---------------------------|
* Starting tunnel for service ingress-nginx-controller.
|---------------|--------------------------|-------------|------------------------|
|   NAMESPACE   |           NAME           | TARGET PORT |          URL           |
|---------------|--------------------------|-------------|------------------------|
| ingress-nginx | ingress-nginx-controller |             | http://127.0.0.1:62234 |
|               |                          |             | http://127.0.0.1:62235 |
|---------------|--------------------------|-------------|------------------------|
* Opening service ingress-nginx/ingress-nginx-controller in default browser...
* Opening service ingress-nginx/ingress-nginx-controller in default browser...
! Because you are using a Docker driver on windows, the terminal needs to be open to run it.

并且得到404来自ingress-nginx这意味着我们可以向 ingress 发送请求:

$ curl http://127.0.0.1:62234

curl : 404 Not Found
nginx
At line:1 char:1
+ curl http://127.0.0.1:62234

解决方案

上面我解释了会发生什么。以下是如何使其发挥作用的三种解决方案:

  1. 使用另一个minikube driver (例如 virtualbox。我使用 hyperv 因为我的笔记本电脑有 Windows 10 Pro)

minikube ip将返回虚拟机的“正常”IP 地址,并且所有网络功能都将正常工作。您需要将此 IP 地址添加到 /etc/hosts对于入口规则中使用的域

注意!即使localhost显示于 kubectl get ing ingress输出 ADDRESS .

  • 使用适用于 Windows 的 Docker 桌面中的内置 kubernetes 功能。
  • 您需要manually install ingress-nginx 并更改ingress-nginx-controller服务类型来自NodePortLoadBalancer所以它将在 localhost 上可用并将继续工作。请查找my another answer about Docker desktop for Windows

  • (仅测试)- 使用端口转发
  • minikube service 的想法几乎完全相同命令。但有更多的控制。您将从主机 VM 端口 80 打开隧道至ingress-nginx-controller端口 80 上的服务(最终是 pod)以及。 /etc/hosts应包含127.0.0.1 test.domain实体。

    $ kubectl port-forward service/ingress-nginx-controller -n ingress-nginx 80:80
    
    Forwarding from 127.0.0.1:80 -> 80
    Forwarding from [::1]:80 -> 80
    

    并测试它是否有效:

    $ curl test.domain
    
    StatusCode        : 200
    StatusDescription : OK
    

    Windows 和 ingress 上 docker 桌面中的 kubernetes 更新:

    论现代ingress-nginx版本 .spec.ingressClassName应添加到入口规则中。请参阅last updates ,因此入口规则应如下所示:

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    ...
    spec:
      ingressClassName: nginx # can be checked by kubectl get ingressclass
      rules:
      - host: myapp.com
        http:
          ...
    

    关于nginx - Ingress 不转发请求 - 适用于 Windows 和 kubernetes 的 Docker 桌面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70011639/

    相关文章:

    ubuntu - 无法安装 Composer - php-fpm

    kubernetes - 我可以将 NGINX Ingress 身份验证与 oidc 一起使用吗?

    kubernetes-ingress - SPA 应用程序(Vue、React、Angular)在 Kubernetes 上的 Nginx 入口 Controller 后面无法正常工作

    clojure - 为从 nginx 反向代理转发的请求添加唯一 id

    ubuntu - 在 Ubuntu 12.04 上的 Nginx 中设置 iRedMail 管理站点

    ubuntu - 上传大于10mb的文件时"Connection Interrupted"

    amazon-web-services - 如何从 kubernetes pod 中识别主机云提供商?

    kubernetes - Ingress-controller-nginx领导人选举-为什么?

    kubernetes - NFS卷装入会导致Kubernetes上的退出代码为32?

    使用非根路径时 Kubernetes Ingress 上的 Angular 应用