微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

AWS EKS 集群中的 TLS nginx 入口导致 404 Not Found

如何解决AWS EKS 集群中的 TLS nginx 入口导致 404 Not Found

我正在尝试使用 Kubernetes Ingress Nginx 控制器并在 AWS EKS 中运行一个简单的 Nginx 服务器。

浏览器(https) --> Route 53 (DNS) --> CLB --> Nginx Ingress (Terminate TLS) --> Service --> POD

但我在浏览器中收到 404 错误(使用的网址:https://example.com/my-nginx):

<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>Nginx/1.19.10</center>
</body>
</html>

在入口日志(kubectl logs -n nginx-ingress nginx-ingress-Nginx-controller-6db6f85bc4-mfpwx)中,我可以看到以下内容

192.168.134.181 - - [24/Apr/2021:19:02:01 +0000] "GET /my-Nginx HTTP/2.0" 404 154 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64 ; rv:88.0) Gecko/20100101 Firefox/88.0" 219 0.002 [eshop-dev-my-Nginx-9443] [] 192.168.168.105:80 154 0.000 404 42f3526392fbe26325cb5b63925cb5b693

这是我的部署 yaml:

apiVersion: apps/v1
kind: Deployment
Metadata:
  name: my-Nginx
  namespace: eshop-dev
spec:
  selector:
    matchLabels:
      run: my-Nginx
  replicas: 2
  template:
    Metadata:
      labels:
        run: my-Nginx
    spec:
      containers:
      - name: my-Nginx
        image: Nginx
        ports:
        - containerPort: 80

服务 yaml:

apiVersion: v1
kind: Service
Metadata:
  namespace: eshop-dev
  name: my-Nginx
spec:
  selector:
    run: my-Nginx
  ports:
    - name: server
      port: 9443
      targetPort: 80
      protocol: TCP

和入口 yaml:

apiVersion: networking.k8s.io/v1
kind: Ingress
Metadata:
  name: test-ingress
  namespace: eshop-dev
  annotations:
    kubernetes.io/ingress.class: "Nginx"
spec:
  rules:
  - host: example.com
    http:
      paths:
      - path: /my-Nginx
        pathType: ImplementationSpecific
        backend:
          service:
            name: my-Nginx
            port:
                number: 9443
  tls:
  - hosts:
    - example.com
    secretName: externaluicerts

我已验证服务在与端口转发一起使用时返回所需的输出

kubectl -n eshop-dev port-forward service/my-Nginx 9443:9443

我不确定入口是否配置不正确,还是其他问题。提前感谢您的帮助!

nginx-port-forward

这里是 kubectl get ingress -n eshop-dev test-ingress -o yaml 的输出

kubectl get ingress -n eshop-dev test-ingress -o yaml
Warning: extensions/v1beta1 Ingress is deprecated in v1.14+,unavailable in v1.22+; use networking.k8s.io/v1 Ingress
apiVersion: extensions/v1beta1
kind: Ingress
Metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"networking.k8s.io/v1","kind":"Ingress","Metadata":{"annotations":{"kubernetes.io/ingress.class":"Nginx"},"name":"test-ingress","namespace":"eshop-dev"},"spec":{"rules":[{"host":"example.com","http":{"paths":[{"backend":{"service":{"name":"my-Nginx","port":{"number":9443}}},"path":"/my-Nginx","pathType":"ImplementationSpecific"}]}}],"tls":[{"hosts":["example.com"],"secretName":"externaluicerts"}]}}
    kubernetes.io/ingress.class: Nginx
  creationTimestamp: "2021-04-24T13:16:21Z"
  generation: 13
  managedFields:
  - apiVersion: networking.k8s.io/v1beta1
    fieldsType: FieldsV1
    fieldsV1:
      f:status:
        f:loadBalancer:
          f:ingress: {}
    manager: nginx-ingress-controller
    operation: Update
    time: "2021-04-24T13:16:40Z"
  - apiVersion: extensions/v1beta1
    fieldsType: FieldsV1
    fieldsV1:
      f:Metadata:
        f:annotations: {}
    manager: kubectl-client-side-apply
    operation: Update
    time: "2021-04-24T13:18:36Z"
  - apiVersion: networking.k8s.io/v1
    fieldsType: FieldsV1
    fieldsV1:
      f:Metadata:
        f:annotations:
          f:kubectl.kubernetes.io/last-applied-configuration: {}
          f:kubernetes.io/ingress.class: {}
      f:spec:
        f:rules: {}
        f:tls: {}
    manager: kubectl-client-side-apply
    operation: Update
    time: "2021-04-24T16:33:47Z"
  name: test-ingress
  namespace: eshop-dev
  resourceVersion: "7555944"
  selfLink: /apis/extensions/v1beta1/namespaces/eshop-dev/ingresses/test-ingress
  uid: a7694655-20c6-48c7-8adc-cf3a53cf2ffe
spec:
  rules:
  - host: example.com
    http:
      paths:
      - backend:
          serviceName: my-Nginx
          servicePort: 9443
        path: /my-Nginx
        pathType: ImplementationSpecific
  tls:
  - hosts:
    - example.com
    secretName: externaluicerts
status:
  loadBalancer:
    ingress:
    - hostname: xxxxxxxxxxxxxxxxdc75878b2-433872486.eu-west-1.elb.amazonaws.com

解决方法

从您发布的 nginx-port-forward 的图片中,我看到您直接访问了 localhost:9443,这意味着您尝试访问的 Nginx 服务器在 / 下提供其内容

但在入口定义中,您定义服务将由 path: /my-nginx 提供。这可能是问题所在,因为您请求的 https://example.com/my-nginx 基本上会转到 my-nginx:9443/my-nginx,并且根据此服务背后的 Pod,如果该路径上没有任何内容,它可能会返回 404。

要测试问题是否是我上面指定的问题,您有几个选择:

  • 最简单的方法是删除 path: /my-nginx 并改为使用 path: /。您还可以指定 pathType: Prefix,这意味着该服务将提供与指定子路径匹配的所有内容。
  • 添加重写目标,如果您想在不同于应用程序预期路径的路径上提供服务,这是必要的。

添加类似如下的注释:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: test-ingress
  namespace: eshop-dev
  annotations:
    kubernetes.io/ingress.class: "nginx"
    # this will rewrite request under / + second capture group
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  rules:
  - host: example.com
    http:
      paths:
        # this will serve all paths under /my-nginx and capture groups for regex annotations
      - path: /my-nginx(/|$)(.*)
        pathType: ImplementationSpecific
        backend:
          service:
            name: my-nginx
            port:
              number: 9443
  tls:
  - hosts:
    - example.com
    secretName: externaluicerts
  • 配置您的应用程序以了解它将在您想要的路径下提供服务。这通常是更好的方法,因为前端应用程序应该几乎总是在他们期望的路径下提供服务。

根据您发布的信息,我认为这是问题一旦解决,您的设置应该可以工作。


如果您对重写目标或路径在 Ingress 中的工作方式感到好奇,这里有一些文档:

重写(https://kubernetes.github.io/ingress-nginx/examples/rewrite/#rewrite

路径类型 ( https://kubernetes.io/docs/concepts/services-networking/ingress/#path-types )


更新

关于为什么将应用程序配置为直接在 Ingress 中指定的路径上提供其内容(基本上是知道它将在哪个路径上提供)是最佳解决方案:

假设您在 Pod 中提供一个复杂的应用程序,它将在 / 下提供其内容。主页将尝试从根目录加载一些其他资源,如 css、js 代码等。基本上,如果我打开 /,应用程序也会加载:

/example.js
/my-beautiful.css

现在,如果我在另一个路径的入口后面提供这个应用程序,假设在 /test/ 具有重写目标下,主页将工作,因为:

/test/ --> /  # this is my rewrite rule

但是,页面将请求 /example.js,并且重写仅在一个方向上工作,因此浏览器将请求将进入 404 的资源,因为请求应该是 /test/example.js (因为这会重写以删除路径的 /test 部分)

因此,对于前端应用程序,重写目标可能还不够,主要是在应用程序请求具有绝对路径的资源时。仅使用 REST API 或单个请求,重写通常效果很好。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。