这里涉及两个知识点。第一个是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 就可以成功请求了。