nginx ingress server alias 多域名多证书问题

2021-07-20 14:34:30 浏览数 (1)

背景

有时候需要多域名指向同一个 ingress 路由规则,比如 a.com a.cn 指向同一个 server

问题

通过查阅nginx-ingress的官方文档,可以知道有一个annotations 叫 server alias

https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#server-alias 可以帮助我们完成上述需求,

eg如下:

代码语言:javascript复制
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: aaa-ingress
  annotations:
    nginx.ingress.kubernetes.io/server-alias: "a.cn"
  labels:
    name: aaa
spec:
  rules:
    - host: a.com
      http:
        paths:
          - path: /
            backend:
              serviceName: aaa
              servicePort: 80

这里有个问题,我们知道 在一个域名时,我们配证书一般是这样配置的

根据密钥生成证书secret

代码语言:javascript复制
kubectl create secret tls a-com-https --key a-com.key --cert a-com.crt
代码语言:javascript复制
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: aaa-ingress
	annotations:
    nginx.ingress.kubernetes.io/server-alias: "a.cn"
  labels:
    name: aaa
spec:
  rules:
    - host: a.com
      http:
        paths:
          - path: /
            backend:
              serviceName: aaa
              servicePort: 80
	tls:
    - hosts:
        - a.com
      secretName: a-com-https

很简单的就配置好了

自然而然,在多域名时候仿照上述配置就有了如下配置

代码语言:javascript复制
kubectl create secret tls a-cn-https --key a-cn.key --cert a-cn.crt
代码语言:javascript复制
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: aaa-ingress
	annotations:
    nginx.ingress.kubernetes.io/server-alias: "a.cn"
  labels:
    name: aaa
spec:
  rules:
    - host: a.com
      http:
        paths:
          - path: /
            backend:
              serviceName: aaa
              servicePort: 80
	tls:
    - hosts:
        - a.com
      secretName: a-com-https
		- hosts:
        - a.cn
      secretName: a-cn-https

然后我们分别访问一下 a.coma.cn

此时 a.com 可以正常访问,但是 a.cn 会提示证书错误

这是为什么呢?

我们可以进入到 nginx-ingress-controller 的容器内看下生成的 nginx.conf,看看他到底帮我们做了些什么?

这是生成后的nginx.conf

我们可以看到,实际上,nginx-ingress-controller 把设置的 alias 全部配置到了 server_name 中,此时证书加载的其实是 a.com (tls 下的第一个证书),自然而且第二个域名访问时出现证书错误也是合理的。

解决

知道了问题所在,那可以怎么解决一下呢?

不用 server alias 就好了,每一个域名转发规则单独配置

代码语言:javascript复制
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: aaa-ingress
  labels:
    name: aaa
spec:
  rules:
		- host: a.cn
      http:
        paths:
          - path: /
            backend:
              serviceName: aaa
              servicePort: 80
    - host: a.com
      http:
        paths:
          - path: /
            backend:
              serviceName: aaa
              servicePort: 80
	tls:
    - hosts:
        - a.com
      secretName: a-com-https
		- hosts:
        - a.cn
      secretName: a-cn-https

上述配置就可以完成,但是同样也带来了一个问题

就是每个规则都需要配置多遍,但如果后期改动没有同时修改,就会导致出错。但目前没有找到合适的解决方案

结论

上述的解决方案还是有问题的,同时在生产环境上,一般也不是 ingress 的 lb 直接提供服务,一般外层还会有一层 cdn,我觉得将 tls 证书绑定在云厂商的 cdn 上比较合适,cdn 到 lb 直接使用 http 进行转发,同时还可以享受云厂商提供的证书的动态更新功能,自己在 ingress 管理证书在每年换证书时还需要手动更新一次。

0 人点赞