【问题标题】:nginx-ingress: Too many redirects when force-ssl is enablednginx-ingress:启用 force-ssl 时重定向过多
【发布时间】:2018-09-26 03:50:53
【问题描述】:

我正在使用 nginx-ingress 在 kubernetes 中设置我的第一个入口。我像这样设置ingress-nginx 负载均衡器服务:

{
  "kind": "Service",
  "apiVersion": "v1",
  "metadata": {
    "name": "ingress-nginx",
    "namespace": "...",
    "labels": {
      "k8s-addon": "ingress-nginx.addons.k8s.io"
    },
    "annotations": {     
      "service.beta.kubernetes.io/aws-load-balancer-backend-protocol": "tcp",
      "service.beta.kubernetes.io/aws-load-balancer-proxy-protocol": "*",
      "service.beta.kubernetes.io/aws-load-balancer-ssl-cert": "arn....",
      "service.beta.kubernetes.io/aws-load-balancer-ssl-ports": "443"
    }
  },
  "spec": {
    "ports": [
      {
        "name": "http",
        "protocol": "TCP",
        "port": 80,
        "targetPort": "http",
        "nodePort": 30591
      },
      {
        "name": "https",
        "protocol": "TCP",
        "port": 443,
        "targetPort": "http",
        "nodePort": 32564
      }
    ],
    "selector": {
      "app": "ingress-nginx"
    },
    "clusterIP": "...",
    "type": "LoadBalancer",
    "sessionAffinity": "None",
    "externalTrafficPolicy": "Cluster"
  },
  "status": {
    "loadBalancer": {
      "ingress": [
        {
          "hostname": "blablala.elb.amazonaws.com"
        }
      ]
    }
  }
}

注意https 端口的targetPort 属性如何指向端口80 (http),以便在负载平衡器处终止ssl。

我的入口看起来像这样:

apiVersion: extensions/v1beta1
kind: Ingress
metadata: 
  name: something
  namespace: ...
  annotations:
    ingress.kubernetes.io/ingress.class: "nginx"
    ingress.kubernetes.io/force-ssl-redirect: "true"
spec:
  rules:
    - host: www.exapmle.com
      http:
        paths:
         - path: /
           backend:
            serviceName: some-service
            servicePort: 2100

现在,当我导航到该 url 时,我得到一个 Too many redirects error。令我困惑的是,当我添加以下标题“X-Forwarded-Proto: https”时,我得到了预期的响应 (curl https://www.example.com -v -H "X-Forwarded-Proto: https")。

有什么办法可以解决这个问题吗?

附:这与ingress.kubernetes.io/force-ssl-redirect: "false" 配合得很好,而且似乎没有任何无关的重定向。

【问题讨论】:

    标签: nginx kubernetes kops kubernetes-ingress


    【解决方案1】:

    这是annotation 的已知问题,用于 SSL 重定向结合代理协议和终止 ELB 上的 SSL 连接。

    关于它的问题已在GitHub 上发布,这是来自该线程的fix

    1. 您应该为 Nginx-Ingress 创建一个自定义的 ConfigMap,而不是使用 force-ssl-redirect 注释,如下所示:

      apiVersion: v1
      kind: ConfigMap
      metadata:
        labels:
          app: ingress-nginx
        name: nginx-ingress-configuration
        namespace: <ingress-namespace>
      data:
        ssl-redirect: "false"
        hsts: "true"
        server-tokens: "false"
        http-snippet: |
          server {
            listen 8080 proxy_protocol;
            server_tokens off;
            return 301 https://$host$request_uri;
          }
      

      该配置将创建一个额外的侦听器,并通过简单的重定向到 https。

    2. 然后,将该 ConfigMap 应用到您的入口控制器,将 NodePort 8080 添加到其容器定义和服务中。
    3. 现在,您可以将 ELB 的 80 端口指向服务的 8080 端口。

    有了这个额外的监听器,它就可以工作了。

    【讨论】:

    • 为什么要监听 8000 和 NodePort 8080?
    • 输入错误。谢谢,我在配置中设置了8080。
    • 关于第 2 步:是否必须是 NodePort?我可以改用ClusterIP 吗?
    • 实际上取决于您的配置。关键是让它将来自客户端的请求从http 端口转发到该端口。那只是一个小型重定向服务器,它将客户端从http://_anything_ 转发到https://the_same_anything_。仅此而已。
    • 我们如何在入口级别执行此操作,仅针对特定的。而不是整个入口控制器的配置图???
    【解决方案2】:

    我必须添加这些注释以使其在不更改入口控制器的情况下工作:

        annotations:
          kubernetes.io/ingress.class: nginx-ingress-internal # <- AWS NLB
          nginx.ingress.kubernetes.io/ssl-redirect: "true"
          nginx.ingress.kubernetes.io/configuration-snippet: |
            if ($http_x_forwarded_proto = 'http') {
              return 301 https://$host$request_uri;
            }
    

    【讨论】:

    • 根据我的环境的最佳答案
    • 这很好用,最适合所有环境
    【解决方案3】:

    另一种适用于我的环境的方法(k8s v1.16.15,rancher/nginx-ingress-controller:nginx-0.32.0-rancher1):

    apiVersion: v1
    data:
      compute-full-forwarded-for: "true"
      use-forwarded-headers: "true"
    kind: ConfigMap
    metadata:
      labels:
        app: ingress-nginx
      name: nginx-configuration
      namespace: ingress-nginx
    

    这与应用程序入口的 force-ssl-redirect 一起工作。入口控制器似乎没有使用开箱即用的 ELB 中的 X-Forwarded-Proto 标头。

    【讨论】:

      【解决方案4】:

      Too many redirects error 添加另一个原因。

      在使用 ingress-nginx 作为一些 k8s 服务前面的入口控制器时。

      其中一项服务(在我的例子中是 ArgoCD)自行处理 TLS 终止并始终将 HTTP 请求重定向到 HTTPS

      问题是 nginx 入口控制器也处理了 TLS 终止并使用 HTTP 与后端服务通信,结果是 ArgoCD 的服务器总是响应重定向到 HTTPS,这是导致多个重定向。

      任何将相关值传递给入口的尝试下面的注释都无济于事

      annotations:
        nginx.ingress.kubernetes.io/ssl-redirect: false/true
        nginx.ingress.kubernetes.io/backend-protocol: "HTTP"/"HTTPS"
      

      解决方案是通过将--insecure 标志传递给 argocd-server 部署来确保服务不处理 TLS

      规格:

        template:
          spec:
            containers:
            - name: argocd-server
              command:
              - argocd-server
              - --repo-server
              - argocd-repo-server:8081
              - --insecure # <-- Here
      

      【讨论】:

      • 于 2021 年 12 月 23 日发表评论。除了你的,什么都没有。非常感谢你
      猜你喜欢
      • 2021-11-28
      • 2020-07-17
      • 1970-01-01
      • 2019-06-18
      • 2021-02-22
      • 1970-01-01
      • 1970-01-01
      • 2023-01-04
      • 1970-01-01
      相关资源
      最近更新 更多