Ingress 未转发请求 - Docker 桌面 Windows 和 kubernetes

Ingress not forwarding the requests - Docker desktop for Windows and kubernetes

编辑:

我删除了 minikube,在 Docker 桌面中为 Windows 启用了 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 文件,但这次入口没有获得任何地址:

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

我正在使用 docker 桌面(windows)并通过 minikube 插件启用命令安装了 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

并应用了我所有的 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

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

$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 in ingress 由于逻辑出现,/etc/hosts 中域后面的 IP 地址是什么并不重要,我添加了一个不同的用于测试,但它仍然显示本地主机。只有 metallb 会提供来自设置网络的 IP 地址。

会发生什么

当 minikube 驱动程序为 docker 时,minikube 创建一个大容器 (VM),其中 kubernetes 组件为 运行。这可以通过主机系统中的 运行ning 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

尝试通过点击 minikube_IP:NodePort 获得 ingress 的任何回应,但没有成功:

$ 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.

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

$ 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 将 return 虚拟机的“正常”IP 地址和所有网络功能都可以正常工作。您需要将此 IP 地址添加到 /etc/hosts 中用于入口规则

的域

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

  1. 在 Docker 桌面中为 Windows 使用内置的 kubernetes 功能。

您将需要manually install ingress-nginx and change ingress-nginx-controller service type from NodePort to LoadBalancer so it will be available on localhost and will be working. Please find

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

这与minikube service命令几乎完全相同。但是有了更多的控制。您还将在端口 80 上打开从主机 VM 端口 80ingress-nginx-controller 服务(最终是 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

docker 桌面 windows 和入口中的 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:
      ...