Kubernetes NGINX 入口控制器未获取 TLS 证书

Posted

技术标签:

【中文标题】Kubernetes NGINX 入口控制器未获取 TLS 证书【英文标题】:Kubernetes NGINX Ingress Controller not picking up TLS Certificates 【发布时间】:2018-03-25 21:03:26 【问题描述】:

我使用 nginx-ingress 控制器在 GKE 上设置了一个新的 kubernetes 集群。 TLS 不工作,它使用的是假证书。

有很多配置细节,所以我做了一个回购 - https://github.com/jobevers/test_ssl_ingress

简而言之,步骤是

创建一个没有 GKE 负载平衡器的新集群 使用我的密钥和证书创建一个 tls 机密 创建一个 nginx-ingress 部署/pod 创建入口控制器

nginx-ingress 配置来自https://zihao.me/post/cheap-out-google-container-engine-load-balancer/(看起来与 ingress-nginx 存储库中的许多示例非常相似)。

我的 ingress.yaml 与 the example one 几乎相同

当我运行 curl 时,我得到了

$ curl -kv https://35.196.134.52
[...]
*    common name: Kubernetes Ingress Controller Fake Certificate (does not match '35.196.134.52')
[...]
*    issuer: O=Acme Co,CN=Kubernetes Ingress Controller Fake Certificate
[...]

这表明我仍在使用默认证书。

我应该如何使用我的?


Ingress definition

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test-ssl-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  tls:
    - secretName: tls-secret
  rules:
  - http:
      paths:
      - path: /
        backend:
          serviceName: demo-echo-service
          servicePort: 80

Creating the secret:

kubectl create secret tls tls-secret --key tls/privkey.pem --cert tls/fullchain.pem

进一步调试,发现证书并存在于服务器上:

$ kubectl -n kube-system exec -it $(kubectl -n kube-system get pods | grep ingress | head -1 | cut -f 1 -d " ") -- ls -1 /ingress-controller/ssl/
default-fake-certificate-full-chain.pem
default-fake-certificate.pem
default-tls-secret-full-chain.pem
default-tls-secret.pem

而且,从日志中,我看到了

kubectl -n kube-system log -f $(kubectl -n kube-system get pods | grep ingress | head -1 | cut -f 1 -d " ")
[...]
I1013 17:21:45.423998       6 queue.go:111] syncing default/test-ssl-ingress
I1013 17:21:45.424009       6 backend_ssl.go:40] starting syncing of secret default/tls-secret
I1013 17:21:45.424135       6 ssl.go:60] Creating temp file /ingress-controller/ssl/default-tls-secret.pem236555242 for Keypair: default-tls-secret.pem
I1013 17:21:45.424946       6 ssl.go:118] parsing ssl certificate extensions
I1013 17:21:45.743635       6 backend_ssl.go:102] found 'tls.crt' and 'tls.key', configuring default/tls-secret as a TLS Secret (CN: [...])
[...]

但是,查看 nginx.conf,它仍在使用假证书:

$ kubectl -n kube-system exec -it $(kubectl -n kube-system get pods | grep ingress | head -1 | cut -f 1 -d " ") -- cat /etc/nginx/nginx.conf | grep ssl_cert
        ssl_certificate                         /ingress-controller/ssl/default-fake-certificate.pem;
        ssl_certificate_key                     /ingress-controller/ssl/default-fake-certificate.pem;

【问题讨论】:

【参考方案1】:

事实证明,入口定义需要如下所示:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test-ssl-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  tls:
    - hosts:
      - app.example.com
      secretName: tls-secret
  rules:
    - host: app.example.com
      http:
        paths:
        - path: /
          backend:
            serviceName: demo-echo-service
            servicePort: 80

rules下的host条目需要匹配tls下的hosts条目之一。

【讨论】:

感谢您直言不讳。我的集群一直存在问题,因为它需要通过 HTTPS 为通配符域提供服务,并且任何通过 HTTP 指向它的任意域。只需复制其中一个规则并显式添加通配符域就可以完全为我排序。 对我来说,入口类不正确。 这个配置应该如何查找通配符证书和域? 感谢您明确提供此配置。至于我,我为tls 部分添加了hosts,但为rules 部分跳过了它(出于某种原因)。在rules 中复制主机名后,它开始正常工作 这对我不起作用。如何准确调试系统正在执行的操作,以便找出为什么它是无礼的垃圾?【参考方案2】:

v0.30.0 也遇到了这个问题,事实证明,在没有明确主机名的情况下拥有这样的入口配置是可以的:

spec:
  tls:
    - secretName: ssl-certificate

在我这边,问题是我在入口上有一个注释,带有一个未正确解析的 int64 值,低于该值是定义 kubernetes.io/ingress.class 所以基本上 nginx 没有找到入口控制器,该控制器在正确的日志:

ignoring add for ingress <ingressname> based on annotation kubernetes.io/ingress.class with value

所以在注释中使用字符串解决了这个问题。

【讨论】:

【参考方案3】:

您需要在chrome、firefox、服务器证书池等地方添加ROOT CA Certificate to authority部分。

    创建一个名为 /usr/share/ca-certificates/extras 的目录 将 .pem 文件的扩展名更改为 .crt 并将此文件复制到 您创建的目录 运行 sudo dpkg-reconfigure ca-certificates 在打开的窗口中,先按回车键,然后选择你想要的文件 添加到使用空格键显示的列表中,然后再次按 Enter

您的计算机现在将自动识别您使用此证书生成的其他证书。

【讨论】:

以上是关于Kubernetes NGINX 入口控制器未获取 TLS 证书的主要内容,如果未能解决你的问题,请参考以下文章

Nginx 入口控制器返回 404 Kubernetes

具有多个入口资源对象的 Kubernetes nginx 入口控制器

使用 nginx 入口控制器的 minikube Kubernetes 集群上没有入口地址

Kubernetes nginx入口控制器不转发带有下划线的标头

k8s nginx 入口重写目标注释未按预期工作

自定义界面上自托管 Kubernetes 的入口