Nginx Ingress 仅在将 nodeport 添加到主机名时才起作用。如何在没有节点端口的情况下使其工作?

Nginx Ingress works only if nodeport is added to the host name. How to make it work without nodeport?

我正在云 Kubernetes 集群上尝试一个简单的微服务应用程序。这是入口 yaml:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-nginx-nginx-ingress
  namespace: default
  annotations:
    kubernetes.io/ingress.class: nginx  
spec:
  defaultBackend:
    service:
      name: auth-svc
      port:
        number: 5000
  rules:
  - host: "somehostname.xyz"
    http:
      paths:
      - path: "/"
        pathType: Prefix
        backend:
          service:
            name: auth-svc
            port:
              number: 5000

问题:
当我使用此 URL 时,我能够访问身份验证服务:http://somehostname.xyz:31840。但是,如果我使用 http://somehostname.xyz,我会收到 “无法访问此站点 somehostname.xyz 拒绝连接。” 错误。
auth 服务也向其他服务发送 GET 请求,如果我使用:
,我可以看到这些服务的响应 http://somehostname.xyz:31840/gohttp://somehostname.xyz:31840/express。但同样,这些仅在使用节点端口 31840 时有效。

我的问题:

这些是 kubectl get all 和其他命令的结果。

NAME                                               READY   STATUS     RESTARTS
pod/auth-flask-58ccd5c94c-g257t                    1/1     Running    0          
pod/ingress-nginx-nginx-ingress-6677d54459-gtr42   1/1     Running    0  




NAME                                  TYPE           EXTERNAL-IP      PORT(S)             
service/auth-svc                      ClusterIP      <none>           5000/TCP            
service/ingress-nginx-nginx-ingress   LoadBalancer   172.xxx.xx.130   80:31840/TCP,443:30550/TCP 



NAME                                          READY   UP-TO-DATE   AVAILABLE 
deployment.apps/auth-flask                    1/1     1            1          
deployment.apps/ingress-nginx-nginx-ingress   1/1     1            1  

    


NAME                                                     DESIRED   CURRENT   READY 
replicaset.apps/auth-flask-58ccd5c94c                    1         1         1    
replicaset.apps/ingress-nginx-nginx-ingress-6677d54459   1         1         1 




NAME                          CLASS    HOSTS                   ADDRESS          PORTS   
ingress-nginx-nginx-ingress   <none>   somehostname.xyz   172.xxx.xx.130   80 

描述入口也很正常。

kubectl describe ingress ingress-nginx-nginx-ingress
Name:             ingress-nginx-nginx-ingress
Namespace:        default
Address:          172.xxx.xx.130
Default backend:  auth-svc:5000 (10.x.xx.xxx:5000)
Rules:
  Host                   Path  Backends
  ----                   ----  --------
  somehostname.xyz  
                         /   auth-svc:5000 (10.x.xx.xxx:5000)
Annotations:             kubernetes.io/ingress.class: nginx

这是授权码

import requests
from flask import Flask

app = Flask(__name__)

@app.route('/')
def indexPage():
    return '  <!DOCTYPE html><html><head><meta charset="UTF-8" />\
    <title>Microservice</title></head> \
    <body><div style="text-align: center;">Welcome to the Auth page</div></body></html>'
       
@app.route('/go')
def getGoJson():
    return requests.get('http://analytics-svc:8082/info').content
    
@app.route('/express')
def getNodeResponse():
    return requests.get('http://node-svc:8085/express').content

if __name__ == '__main__':
    app.run(debug=True, host="0.0.0.0")

和 Auth 的 Dockerfile:

FROM python:3.8-slim-buster
WORKDIR /usr/src/app
ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0
ENV FLASK_ENV=development 
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
COPY . .
CMD ["flask", "run"] 

docker部分-compose yaml for auth:

version: "3.3"
services:
  auth:
    build: ./auth/
    image: nav9/auth-flask:v1 
    ports:
    - "5000:5000"

Auth 的 Kubernetes 清单:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: auth-flask
spec:
  selector:
    matchLabels:
      any-name: auth-flask
  template:
    metadata:
      labels:
        any-name: auth-flask
    spec:
      containers:
        - name: auth-name
          image: nav9/auth-flask:v1
          imagePullPolicy: Always
          ports:
            - containerPort: 5000
---
apiVersion: v1
kind: Service
metadata:
  name: auth-svc
spec:
#  type: ClusterIP
  ports:
    - targetPort: 5000
      port: 5000
  selector:
    any-name: auth-flask

What typically causes such a problem, where I can access the service using the hostname and nodeport, but it won't work without supplying the nodeport?

如果 URL 在使用 nodeport 时有效,而不是在没有 nodeport 的情况下有效,那么这意味着入口未针对您想要执行的操作进行正确配置。

Is there a method to test this in a different way to figure out where the problem is?

故障排除步骤是:

  1. 第一步是确定错误是来自入口还是来自您的后端服务。

在你的情况下,错误 This site can’t be reached somehostname.xyz refused to connect,听起来像是 Ingress 找到了要映射到的服务并使用端口 5000 连接到它,但连接被拒绝或没有任何东西在端口 5000 上监听服务。

  1. 接下来我会查看 auth-svc 日志以查看该请求是否进入了系统以及它被拒绝的原因。

我的猜测是身份验证服务正在侦听端口 31840,但您的入口表示根据配置连接到端口 5000

您可以尝试添加一个从 80 到 31840 的端口映射作为 hack/test 以查看是否会出现不同的错误。

类似于:

spec:
  rules:
  - host: "somehostname.xyz"
    http:
      paths:
      - path: "/"
        backend:
          service:
            port:
              number: 31840

我只包含了正确显示缩进所需的部分。 所以另一种测试方法是创建额外的 URLs 映射到不同的端口,例如:

/try1 => auth-svc:5000
/try2 => auth-svc:31840
/try3 => auth-svc:443

我没有玩过的另一部分可能是个问题,因为您正在使用 http,而我不知道有任何使用 http 的身份验证服务,因此只需尝试使用 http 连接到需要 https 的应用程序将获得拒绝连接或出现奇怪错误的连接,因此这可能与您看到的 problem/error 有关。

希望这能给您一些尝试的想法。

解决方案分为三个部分:

  1. 使用kubectl get all找出运行入口服务:

    NAME                                 TYPE           EXTERNAL-IP     PORT(S)
    service/ingress-nginx-nginx-ingress  LoadBalancer   172.xxx.xx.130  80:31840/TCP,443:30550/TCP
    

复制服务的 EXTERNAL-IP(在本例中为 172.xxx.xx.130)。

  1. 为云集群添加名为*.somehostname.xyz的DNS A记录,并使用IP地址172.xxx.xx.130.

  2. 通过浏览器访问主机名时,请确保使用 http 而不是 https