Https 在本地无法用于我的 kubernetes 集群上的入口

问题描述

我试图让我的入口通过 https 运行,但我收到了 HTTP ERROR 403,我不知道我在这里遗漏了什么。

我试图在 my-local-domain.com 上访问它们,并且我在我的 etc/hosts 文件添加了该条目作为 127.0.0.1 my-local-domain.com 这样我就可以通过这种方式访问​​它。

这是我的发行人

apiVersion: cert-manager.io/v1
kind: Issuer
Metadata:
  name: cert-issuer
  namespace: my-namespace
spec:
  selfSigned: {}

这是我的证书

apiVersion: cert-manager.io/v1
kind: Certificate
Metadata:
  name: self-signed-cert
  namespace: my-namespace
spec:
  secretName: my-secret-tls
  dnsNames:
    - my-local-domain.com
    - www.my-local-domain.com
  issuerRef:
    name: cert-issuer

虽然这是我的 Nginx 入口:

apiVersion: networking.k8s.io/v1
kind: Ingress
Metadata:
  name: ingress-service
  labels:
      name: ingress-service
  namespace: my-namespace
  annotations:
    Nginx.ingress.kubernetes.io/rewrite-target: /$1
    Nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
    Nginx.ingress.kubernetes.io/ssl-redirect: 'true'
    namespace: my-namespace
spec:
  tls:
    - hosts:
      - my-local-domain.com
      - www.my-local-domain.com
      secretName: my-secret-tls
  rules:
  - host: my-local-domain.com
    http:
      paths:
      - path: /api/(.*)
        pathType: Prefix
        backend:
          service:
            name: web-api
            port:
              number: 443
      - path: /(.*)
        pathType: Prefix
        backend:
          service:
            name: web-client
            port:
              number: 80

Nginx.conf 用于我的网络客户端服务

server {
        listen 80;

        location / {
            root /usr/share/Nginx/html;
            index index.html index.htm;
            try_files $uri $uri/ /index.html;
        }

        gzip  on; 
    }

当我尝试使用 https://my-local-domain.com

访问它时
Access to my-local-domain.com was denied
You don't have authorization to view this page.
HTTP ERROR 403

我也试过跑

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "//CN=my-local-domain.com\O=my-local-domain.com" -addext "subjectAltName = DNS:my-local-domain.com"

kubectl create secret tls tls-secret --key tls.key --cert tls.crt -n my-namespace

删除 CertificateCertificateIssuer 并在入口中添加 tls-secret 作为 secretName,并将这些 tls.keytls.crt 添加到我的网络-client Nginx 并将其更新为:

    server {
      listen 443 ssl default_server;

      ssl_protocols SSLv3 TLSv1;

      server_name www.my-local-domain.com my-local-domain.com;

      access_log /var/log/Nginx/access.log;
      error_log  /var/log/Nginx/error.log info;

      keepalive_timeout 75 75;

      ssl_certificate /etc/ssl/certs/self-signed.crt;
      ssl_certificate_key /etc/ssl/private/self-signed.key;
      ssl_session_timeout  5m;

      add_header Strict-Transport-Security "max-age=7200";
      
      location / {
          root /usr/share/Nginx/html;
          index index.html index.htm;
          try_files $uri $uri/ /index.html;
      }
    }

附言这样做时,我在端口 443 而不是 80 上运行 everyrhin。

当我从入口中删除 tls 部分时,它确实通过 HTTP 工作。而且我还尝试将我的 dns/host 从 my-local-domain.com 更改为仅 localhost 但仍然相同。即使我尝试访问 https://localhost,我也会得到 HTTP ERROR 403

解决方法

我不知道这是否会有所帮助,但这里有一些建议:

  1. 确定错误的来源
    您向我们提供了大量代码,但没有提供错误的详细信息。 403 是由您的网络服务、您的 api 还是您的入口控制器抛出的?您可以在错误页面中检查。来自 ingress-controller 的错误通常在页脚中包含一些类似“openresty”的想法。但这几乎不取决于您在 k8s 中使用的入口控制器。
    您还可以检查容器的日志(nginx 将日志写入 /var/log/nginx/error.log)。您可以在此处找到一些更详细的信息,说明您收到 403 的原因。

  2. 让集群处理 SSL 终止
    不要将 ssl 认证放入容器中。它几乎不会增加您的应用程序的复杂性。
    当集群处理它时,它会容易得多。因此,您的应用可以更快地部署在具有其他环境的其他集群上。

  3. 在使用自签名证书时避免使用证书管理器
    正如您已经测试过的,但我建议仅在需要来自 Let encrypt 的证书时才使用 cert-manager。否则会再次增加复杂性。

  4. 不要混淆 HTTP 和 HTTPS
    您的 webapi 使用 HTTPS 进行内部通信(内部表示:ingress-controller -> webapi-service,通常未加密)...但不适用于您的 web-server。
    保持简单 - 为所有人或任何人使用 HTTPS。

  5. 尽量避免 url 重写
    只要可能,尽量避免 url-rewrite。我经常看到它的问题,所以我建议避免它。
    我知道这并不总是可能的,但是当所有组件都由您开发时......您为什么需要它?这是您在“简单”中的入口:

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
       name: ingress-service
       labels:
          name: ingress-service
       namespace: my-namespace
       annotations:
          nginx.ingress.kubernetes.io/ssl-redirect: 'true'
    
    spec:
       tls:
          - hosts:
             - my-local-domain.com
             - www.my-local-domain.com
          secretName: my-secret-tls
       rules:
          - host: my-local-domain.com
            http:
               paths:
                  - path: /api/       
                    backend:
                       service:
                          name: web-api
                          port:
                             number: 80
                  - path: /
                    backend:
                       service:
                       name: web-client
                       port:
                          number: 80  
    
  6. 无根是最好的
    对于您的问题不是很重要,但不要使用标准的 nginx-image,而是使用无特权的 nginx-image。如果您的服务(在本例中为 nginx)被黑客入侵,则黑客拥有与 nginx 相同的权限。这意味着,他可以轻松地将工具安装到 nginx-container 中并做非常糟糕的事情。
    如果您使用的是非特权映像,那么黑客可以……几乎什么也做不了。他需要第二次利用来提升他的权利。

祝你好运找到你的错误。当您与我们分享您的后续步骤时,我们很高兴。