k8singress外部域名(ExternalDomains)
这里涉及两个知识点。第一个是ingress ,第二个是external domains。ingress 大家可能比较熟悉,比如下面的配置,访问hello-world.info的域名,请求"/"目录,将会把请求转发到web 这个服务。apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: example-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: /$1 spec: rules: - host: hello-world.info http: paths: - path: / pathType: Prefix backend: service: name: web port: number: 8080
external domains大家可能不经常使用,这个是k8s 提供的CNAME能力,比如下面通过外部域名的功能,为my-service 的域名增加一个 my.database.example.com的CNAME,这样当我们在容器里面访问 my-service域名的时候,域名解析到CNAME my.database.example.com,从而将请求转发到 my.database.example.com 。apiVersion: v1 kind: Service metadata: name: my-service namespace: prod spec: type: ExternalName externalName: my.database.example.com
但外部域名有个小问题,就是它只是重定向域名,并不会修改 HTTP header,这就导致一个问题:请求url 里面域名和header中的域名不一致。而ingress 大部分都是HTTP 请求。比如下面service 的定义。apiVersion: v1 kind: Service metadata: name: my-service namespace: my-namespace spec: type: ExternalName externalName: example.com
当通过 my-sample.com 请求ingress的时候,ingress转发请求的时候, HTTP HOST header 还是my-sample.com,但上面设置的外部域名是 example.com,这就导致不一致了,nginx无法转发流量。apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: external-ingress annotations: kubernetes.io/ingress.class: my-nginx nginx.ingress.kubernetes.io/backend-protocol: https nginx.ingress.kubernetes.io/upstream-vhost: example.com spec: rules: - host: my-sample.com http: paths: - backend: serviceName: my-service servicePort: 443 path: / pathType: ImplementationSpecific tls: - hosts: - my-sample.com secretName: my-tls
但我们还可以通过 nginx.ingress.kubernetes.io/upstream-vhost 这个annotation修改我们的请求header,如上面例子,我们将请求header的HOST 修改成 example.com 就可以成功请求了。