如何在本地访问nginx ingress?

16

我无法连接到在nginx ingress(Docker Desktop win 10)中运行的应用程序。

nginx-ingress控制器pod正在运行,应用程序是健康的,并且我已创建了一个ingress。但是,当我尝试在本地主机上连接我的应用程序时,我收到“连接被拒绝”的错误消息。

我在日志中看到了这个错误:

[14:13:13.028][VpnKit            ][Info   ] vpnkit.exe: Connected Ethernet interface f6:16:36:bc:f9:c6

[14:13:13.028][VpnKit            ][Info   ] vpnkit.exe: UDP interface connected on 10.96.181.150

[14:13:22.320][GoBackendProcess  ][Info   ] Adding vpnkit-k8s-controller tcp forward from 0.0.0.0:80 to 10.96.47.183:80
[14:13:22.323][ApiProxy          ][Error  ] time="2019-12-09T14:13:22-05:00" msg="Port 443 for service ingress-nginx is already opened by another service"

我认为端口443被其他应用程序使用,可能是Zscaler安全或Skype。

netstat -a -b的摘录:

 [svchost.exe]
  TCP    0.0.0.0:443            0.0.0.0:0              LISTENING       16012
 [com.docker.backend.exe]
  TCP    0.0.0.0:443            0.0.0.0:0              LISTENING       8220

我不知道如何使Ingress工作,请帮忙!

我的Ingress:

$ kubectl describe ing kbvalues-deployment-dev-ingress
Name:             kbvalues-deployment-dev-ingress
Namespace:        default
Address:          localhost
Default backend:  default-http-backend:80 (<none>)
Rules:
  Host       Path  Backends
  ----       ----  --------
  localhost
             /   kbvalues-deployment-dev-frontend:28000 (10.1.0.174:8080)
Annotations:
  kubernetes.io/ingress.class:                     nginx
  nginx.ingress.kubernetes.io/cors-allow-headers:  X-Forwarded-For, X-app123-XPTO
Events:
  Type    Reason  Age               From                      Message
  ----    ------  ----              ----                      -------
  Normal  CREATE  42m               nginx-ingress-controller  Ingress default/kbvalues-deployment-dev-ingress
  Normal  UPDATE  6s (x5 over 42m)  nginx-ingress-controller  Ingress default/kbvalues-deployment-dev-ingress

我的服务:

$ kubectl describe svc kbvalues-deployment-dev-frontend
Name:              kbvalues-deployment-dev-frontend
Namespace:         default
Labels:            chart=tomcat-sidecar-war-1.0.4
                   environment=dev
                   name=kbvalues-frontend-dev
                   release=kbvalues-test
                   tier=frontend
Annotations:       <none>
Selector:          app=kbvalues-dev
Type:              ClusterIP
IP:                10.98.89.94
Port:              <unset>  28000/TCP
TargetPort:        8080/TCP
Endpoints:         10.1.0.174:8080
Session Affinity:  None
Events:            <none>

我正在尝试访问应用程序:http://localhost:28000/health。我确认本地web服务器容器内可以访问/health的URL。

感谢您提供的任何帮助。

编辑:

我尝试更改ingress-nginx服务以删除HTTPS,如此处所建议:https://dev59.com/_bTma4cB1Zd3GeqP0xju#56303330

这消除了日志中的443错误,但没有修复我的设置(仍然遇到连接被拒绝的问题)。

编辑2:这是Ingress YAML定义(kubectl get -o yaml):

$ kubectl get ing -o yaml
apiVersion: v1
items:
- apiVersion: extensions/v1beta1
  kind: Ingress
  metadata:
    annotations:
      kubernetes.io/ingress.class: nginx
    creationTimestamp: "2019-12-09T18:47:33Z"
    generation: 5
    name: kbvalues-deployment-dev-ingress
    namespace: default
    resourceVersion: "20414"
    selfLink: /apis/extensions/v1beta1/namespaces/default/ingresses/kbvalues-deployment-dev-ingress
    uid: 5c34bf7f-1ab4-11ea-80e4-00155d169409
  spec:
    rules:
    - host: localhost
      http:
        paths:
        - backend:
            serviceName: kbvalues-deployment-dev-frontend
            servicePort: 28000
          path: /
  status:
    loadBalancer:
      ingress:
      - hostname: localhost
kind: List
metadata:
  resourceVersion: ""
  selfLink: ""

编辑3:kubectl get svc -A命令的输出(只包括Ingress行):

ingress-nginx   ingress-nginx                      LoadBalancer   10.96.47.183     localhost     80:30470/TCP             21h

编辑4:我尝试从Windows HyperV获取虚拟机的IP地址,但似乎该虚拟机没有IP地址?

PS C:\> (Get-VMNetworkAdapter -VMName DockerDesktopVM)

Name            IsManagementOs VMName          SwitchName MacAddress   Status IPAddresses
----            -------------- ------          ---------- ----------   ------ -----------
Network Adapter False          DockerDesktopVM DockerNAT  00155D169409 {Ok}   {}

编辑5:

端口80的netstat -a -n -o -b输出:

  TCP    0.0.0.0:80             0.0.0.0:0              LISTENING       4
 Can not obtain ownership information

1
你能否在没有Ingress的情况下访问该服务?比如直接使用服务IP和端口进行访问是否可行? - Shubham
1
你应该尝试执行 kubectl exec -it <your nginx pod> /bin/bash 命令,运行 Shubham 建议的 curl 命令并检查输出结果。 - randominstanceOfLivingThing
1
kubectl get svc -A 的输出是什么(只粘贴 ingress 行)?我怀疑您的 ingress 服务配置不正确。对于云环境,我期望类型为 LoadBalancer,但对于您的情况,我认为您可能需要将其配置为使用 NodePort,在该端口上访问您的 ingress(例如,https://localhost:30252/myapp)。 - leeman24
1
@Shubham @randominstanceOfLivingThing 我成功地访问了服务,使用以下命令:kubectl port-forward svc/kbvalues-deployment-dev-frontend 28000 并访问:http://localhost:28000/health - RMorrisey
@DawidKruk 对于混淆感到抱歉 - 我的问题仍未解决。上述命令只是一种解决方法;它并没有像 OP 中描述的那样修复入口功能。 - RMorrisey
显示剩余2条评论
5个回答

30

我已经成功在Windows上的Kubernetes上创建了Ingress资源。

重现步骤

  • 启用Hyper-V
  • 安装Docker for Windows并启用Kubernetes
  • 连接kubectl
  • 启用Ingress
  • 创建部署
  • 创建服务
  • 创建Ingress资源
  • 将主机添加到本地hosts文件中
  • 测试

启用Hyper-V

以管理员身份运行PowerShell,运行以下命令:

Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All

系统可能会要求您重新启动计算机。

安装Docker for Windows并启用Kubernetes

使用所有默认选项安装Docker应用并启用Kubernetes

连接kubectl

安装kubectl

启用Ingress

运行以下命令:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/cloud-generic.yaml

编辑:确保没有其他服务正在使用端口80

重新启动您的计算机。从以管理员身份运行的cmd提示符中执行以下操作: net stop http 使用services.msc停止列出的服务。

使用netstat -a -n -o -b检查是否有其他进程在侦听端口80。

创建部署

下面是一个简单的部署,其中包含会响应请求的Pod:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello
spec:
  selector:
    matchLabels:
      app: hello
      version: 2.0.0
  replicas: 3
  template:
    metadata:
      labels:
        app: hello
        version: 2.0.0
    spec:
      containers:
      - name: hello
        image: "gcr.io/google-samples/hello-app:2.0"
        env:
        - name: "PORT"
          value: "50001"

通过运行以下命令来应用它:

$ kubectl apply -f file_name.yaml

创建服务

为了能够与 Pod 进行通信,您需要创建一个服务。

下面是一个示例:

apiVersion: v1
kind: Service
metadata:
  name: hello-service
spec:
  type: NodePort
  selector:
    app: hello
    version: 2.0.0
  ports:
  - name: http
    protocol: TCP
    port: 80
    targetPort: 50001

运行以下命令来应用此服务定义:

$ kubectl apply -f file_name.yaml

创建 Ingress 资源

下面是使用上述创建的服务的简单 Ingress 资源:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: hello-ingress 
spec:
  rules:
  - host: hello-test.internal
    http:
      paths:
      - path: /
        backend:
          serviceName: hello-service 
          servicePort: http

看一下:

spec:
  rules:
  - host: hello-test.internal 

hello-test.internal将用作连接到您的Pod的hostname

通过调用命令应用您的Ingress资源:

$ kubectl apply -f file_name.yaml

将主机添加到本地hosts文件中

我发现这个Github链接将允许您通过hostname连接到您的Ingress资源。

为了实现这一点,将一行127.0.0.1 hello-test.internal添加到您的C:\Windows\System32\drivers\etc\hosts文件中并保存。 您需要管理员权限才能这样做。

编辑:最新版的Docker Desktop for Windows已经添加了一个主机文件条目:127.0.0.1 kubernetes.docker.internal

测试

通过调用命令显示有关Ingress资源的信息: kubectl get ingress

它应该显示:

NAME            HOSTS                 ADDRESS     PORTS   AGE
hello-ingress   hello-test.internal   localhost   80      6m2s

现在您可以通过打开Web浏览器并输入

http://kubernetes.docker.internal/

来访问您的Ingress资源。

浏览器应输出:

Hello, world!
Version: 2.0.0
Hostname: hello-84d554cbdf-2lr76

主机名: hello-84d554cbdf-2lr76 是回复的Pod的名称。

如果该解决方案无法运行,请使用命令检查连接: netstat -a -n -o以管理员权限运行),以查看是否有进程正在使用端口80。


1
感谢您提供详细的说明!我明天早上会尝试按照这些步骤操作,并回报结果。 - RMorrisey
让我找一下 kubernetes.docker.internal 的设置在哪里。 - RMorrisey
我在我的.kube配置文件中更改了集群设置,但现在出现以下错误:无法连接到服务器:x509:证书仅适用于docker-for-desktop、kubernetes、kubernetes.default、kubernetes.default.svc、kubernetes.default.svc.cluster.local、kubernetes.docker.internal、vm.docker.internal、localhost,而不是hello-test.internal - RMorrisey
要明确的是,上面所有的步骤都有效,直到hosts文件步骤-这就是导致我的kubectl出现问题的原因。 - RMorrisey
我尝试了几种不同的变化(包括两个条目: 127.0.0.1 kubernetes.docker.internal 127.0.0.1 hello-test.internal) (将这两个项目放在同一行上:127.0.0.1 kubernetes.docker.internal hello-test.internal)。在这两种配置中,kubectl都可以工作,但我仍然得到了404错误。 - RMorrisey
显示剩余22条评论

2

在Windows上,Kubernetes集群是在虚拟机中运行的。请尝试访问该虚拟机的IP地址而不是localhost上的入口。


谢谢回复。我该如何找出虚拟机的IP? - RMorrisey
1
通过使用minikube,我可以使用 minikube ip,但是Docker桌面似乎工作方式不同...不确定如何获取它。 - RMorrisey
我无法弄清如何从HyperV获取IP。看起来虚拟机没有分配IP? - RMorrisey
1
稍等一下。我正在尝试在Windows 10上使用Docker设置Kubernetes,然后我会更深入地挖掘。 - Dávid Molnár
很遗憾,我无法设置它。在两台机器上尝试过了。相同的错误。你能否尝试列出 kubectl get nodeskubectl describe node 并发布输出? - Dávid Molnár
显示剩余2条评论

1

0
问题在于您的服务类型为ClusterIP,无法从外部访问。您需要将其更改为NodePort类型,这是Dawid Kruk指令中所做的操作。

0

我在使用手动步骤在裸机节点上部署ingress-nginx控制器ingress-nginx-deploy时遇到了类似的问题,但是遇到了问题。后来参考@RMorrisey提供的Github链接,转到其他线程,在那里他们提到安装ingress-nginx使用在mac上提到的步骤,并且没有对主机文件进行任何更改等操作,就可以解决问题了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接