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

osu*_*atu 2 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"
Run Code Online (Sandbox Code Playgroud)

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

$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
Run Code Online (Sandbox Code Playgroud)

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

$kubectl get ing
NAME                CLASS    HOSTS       ADDRESS   PORTS   AGE
myapp-ingress       <none>   myapp.com             80      10m
Run Code Online (Sandbox Code Playgroud)

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

$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
Run Code Online (Sandbox Code Playgroud)

并应用了我所有的 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
Run Code Online (Sandbox Code Playgroud)

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

$kubectl get ingress
NAME                CLASS   HOSTS           ADDRESS     PORTS   AGE
myapp-ingress   nginx   myapp.com       localhost   80      74s
Run Code Online (Sandbox Code Playgroud)

这也有点奇怪,我希望 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
Run Code Online (Sandbox Code Playgroud)

事件-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
Run Code Online (Sandbox Code Playgroud)

moo*_*tte 5

再生产

\n

v1.24.0我使用 minikube 、 Docker 桌面4.2.0、 引擎重现了这个案例20.10.10

\n

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

\n

会发生什么

\n

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

\n
$ docker ps\n\nCONTAINER ID   IMAGE                                 COMMAND                  CREATED          STATUS          PORTS                                                                                                                                  NAMES\nf087dc669944   gcr.io/k8s-minikube/kicbase:v0.0.28   "/usr/local/bin/entr\xe2\x80\xa6"   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\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

向前进。在介绍 之前ingress,已经很清楚 EvenNodePort无法按预期工作。让我们检查一下。

\n

有两种获取方式minikube VM IP

\n
    \n
  1. 跑步minikube IP
  2. \n
  3. kubectl get nodes -o wide并找到节点的IP
  4. \n
\n

接下来应该发生的事情是请求应该在它不起作用时NodePort进行。minikube_IP:Nodeport发生这种情况是因为 minikube VM 内的 docker 容器没有暴露在集群之外(另一个 docker 容器)。

\n

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

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

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

\n
$ curl http://127.0.0.1:61991/\n\nStatusCode        : 200\nStatusDescription : OK\n
Run Code Online (Sandbox Code Playgroud)\n

添加入口

\n

继续前进并添加入口。

\n
$ minikube addons enable ingress\n$ kubectl get svc -A\n\nNAMESPACE       NAME                                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE\ndefault         echo                                 NodePort    10.111.57.237   <none>        8080:32034/TCP               25m\ningress-nginx   ingress-nginx-controller             NodePort    10.104.52.175   <none>        80:31041/TCP,443:31275/TCP   2m12s\n
Run Code Online (Sandbox Code Playgroud)\n

ingress试图通过点击来获得任何响应,minikube_IP:NodePort但没有运气:

\n
$ curl 192.168.49.2:31041\n\ncurl : Unable to connect to the remote server\nAt line:1 char:1\n+ curl 192.168.49.2:31041\n
Run Code Online (Sandbox Code Playgroud)\n

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

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

404从中获取ingress-nginx意味着我们可以向 ingress 发送请求:

\n
$ curl http://127.0.0.1:62234\n\ncurl : 404 Not Found\nnginx\nAt line:1 char:1\n+ curl http://127.0.0.1:62234\n
Run Code Online (Sandbox Code Playgroud)\n

解决方案

\n

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

\n
    \n
  1. 使用另一个minikube 驱动程序(例如 virtualbox。我使用的hyperv是因为我的笔记本电脑有 windows 10 pro)
  2. \n
\n

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

\n

笔记!即使在输出中localhost显示。kubectl get ing ingressADDRESS

\n
    \n
  1. 使用适用于 Windows 的 Docker 桌面中的内置 kubernetes 功能。
  2. \n
\n

您需要手动安装ingress-nginxingress-nginx-controller服务类型并将其更改NodePortLoadBalancer,以便它可用localhost并正常工作。请找到我关于 Windows 的 Docker 桌面的另一个答案

\n
    \n
  1. (仅测试) - 使用端口转发
  2. \n
\n

这与minikube service命令的想法几乎完全相同。但有更多的控制。80您还将打开一条从主机 VM 端口到ingress-nginx-controller端口上的服务(最终是 pod)的隧道80/etc/hosts应包含127.0.0.1 test.domain实体。

\n
$ kubectl port-forward service/ingress-nginx-controller -n ingress-nginx 80:80\n\nForwarding from 127.0.0.1:80 -> 80\nForwarding from [::1]:80 -> 80\n
Run Code Online (Sandbox Code Playgroud)\n

并测试它的工作原理:

\n
$ curl test.domain\n\nStatusCode        : 200\nStatusDescription : OK\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

在现代ingress-nginx版本中.spec.ingressClassName应该添加到入口规则中。请参阅最新更新,因此入口规则应如下所示:

\n
apiVersion: networking.k8s.io/v1\nkind: Ingress\n...\nspec:\n  ingressClassName: nginx # can be checked by kubectl get ingressclass\n  rules:\n  - host: myapp.com\n    http:\n      ...\n
Run Code Online (Sandbox Code Playgroud)\n