之前Istio在测试环境、云环境(华为云、阿里云)上,都是用的Nginx挂载的Https证书;
测试环境:
(1)外网域名(含有固定前缀,例如:*-fat.xxx.com)通过dnsPod直接指到Nginx地址;
(2)在Nginx 443端口上挂载Https ssl配置(证书、私钥);
(3)Nginx 443端口监听外网域名并转发请求到Istio Ingress网关IP+http端口(31380);
云环境:
(1)外网域名(含有固定前缀,例如:*-uat.xxx.com)通过dnsPod直接指到云环境SLB外网IP;
(2)SLB监听443端口,并转发到Master节点上的Nginx监听的端口443(可以443,亦可以其他不冲突端口,如80等均可);
注:Nginx目前启动在Master中的某节点,启动在其他Node节点会导致80和443端口冲突,Nginx无法启动;
(3)在Nginx 443端口上挂载Https ssl配置(证书、私钥);
(4)Nginx 443端口监听外网域名并转发请求到Istio Ingress网关IP+http端口(31380);
但其实K8s Ingress、云环境SLB、Istio Gateway均支持挂载Https证书,
K8s Ingress:通过在Ingress上挂载secretName(对应secret tls --cert --key配置);
云环境SLB:可定义证书,并支持在监听器上关联证书(未实际测试,需结合具体云环境使用说明);
Istio Gateway:通过在Gateway上挂载证书路径(对应secret tls --cert --key配置)OR 挂载证书credentialName(对应secret tls --cert --key的secretName);
由于目前环境已从K8s全面切换到Istio(使用Isito Gateway代替K8s Ingress),且测试环境不部署在云上(不依赖SLB),所以最终决定将Https设置放到Isito Gateway上;
参照官网说明(1.1版本),Istio Gateway支持2中Https设置方式:
(1)文件挂载(File mount);
(2)SDS(Secret Discovery Service );
目前采用方式(1)文件挂载 - 较为基础的方式,基本步骤如下:
Isito官方参考链接:https://archive.istio.io/v1.1/docs/tasks/traffic-management/secure-ingress/mount/
1.创建K8s secret tls -> istio-ingressgateway-certs(证书、私钥)
kubectl create -n istio-system secret tls istio-ingressgateway-certs --key httpbin.example.com/3_application/private/httpbin.example.com.key.pem --cert httpbin.example.com/3_application/certs/httpbin.example.com.cert.pem
注:官方示例中使用的是.pem格式,而实际测试过程中使用的是*.cer和*.key格式,并且secret tls的名字必须为istio-ingressgateway-certs才能保证Ingress gateway自动加载该证书配置;
2.验证证书tls.crt和私钥tls.key是否成功挂载到ingress gateway pod中/etc/istio/ingressgateway-certs路径下
kubectl exec -it -n istio-system $(kubectl -n istio-system get pods -l istio=ingressgateway -o jsonpath='{.items[0].metadata.name}') -- ls -al /etc/istio/ingressgateway-certs
注:若ingress没有成功挂载tls证书,可通过重启Ingressgateway来使其重新加载tls证书和私钥;
3.定义Gateway监听指定域名的443端口并挂载tls配置(步骤2中的tls配置)
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: httpbin-gateway
spec:
selector:
istio: ingressgateway # use istio default ingress gateway
servers:
- port:
#监听Https协议端口443
#该端口与istio-system.service.istio-ingressgateway中ports.name=https的port对应,对外端口为31390
number: 443
name: https
protocol: HTTPS
#tls证书配置
tls:
#简单模式(仅需客户端验证服务端Https证书,不是双向验证(MUTUAL))
mode: SIMPLE
#挂载服务端证书(与之前定义的secret tls istio-ingressgateway-certs --cert对应)
serverCertificate: /etc/istio/ingressgateway-certs/tls.crt
#挂载服务端私钥(与之前定义的secret tls istio-ingressgateway-certs --key对应)
privateKey: /etc/istio/ingressgateway-certs/tls.key
hosts:
#需要监听的https域名
- "httpbin.example.com"
4.路由器监听443端口,并将443端口的请求转发到Istio Ingress网关IP+https端口(31390)
注:关于Istio 网关IP+Port的设置,可参考Isito官网:determining-the-ingress-ip-and-ports
5.多个Https配置需要多定义多个secret,然后由多个Gateway各自绑定对应的证书路径(绑定到istio-ingressgateway deployment上),多等一会,否则报404
官网参考:configure-a-tls-ingress-gateway-for-multiple-hosts
由于之前每个需要外网域名(满足*.xxx.com格式均可)的服务均各自对应一个gateway定义(即多个服务对应多个Gateway),故在绑定tls配置(证书支持*.xxx.com形式,可支持绑定多个域名)时,多个gateway对同一tls证书绑定了多次,如此设置后,会发现不同gateway绑定同一证书配置的https域名会出现只有一个域名(多个gateway中的一个gateway中的域名)的https协议生效,其他的不生效,即无法满足所有绑定该tls配置的域名同时https协议生效;
解决方法
若无法定义多个gateway同时绑定同一个tls配置,那么就把支持同一个tls配置(证书、私钥)的所有域名统一放到一个Gateway中进行定义,然后相关的VirtualService均绑定到该统一的Gateway上(实测好用);
即把同一个Https证书的支持的域名都放在同一个Gateway中进行定义;
kind: Gateway
apiVersion: networking.istio.io/v1alpha3
metadata:
name: xxx-https-gateway
namespace: tsp
spec:
servers:
#http 80端口设置(绑定多个域名)
- hosts:
- aaa.xxx.com
- bbb.xxx.com
- ccc.xxx.com
port:
name: http
number: 80
protocol: HTTP
#https 443端口设置(绑定多个支持同一个https证书的域名)
- hosts:
- aaa.xxx.com
- bbb.xxx.com
- ccc.xxx.com
port:
name: https
number: 443
protocol: HTTPS
tls:
mode: SIMPLE
privateKey: /etc/istio/ingressgateway-certs/tls.key
serverCertificate: /etc/istio/ingressgateway-certs/tls.crt
selector:
istio: ingressgateway
若VirtualService和Gateway定义在不同namespace,即不同namespace的VirtualService均绑定到同一个Gateway,可在VirtualService中gateways中通过your-namespace/gateway-name来跨namespace绑定Gateway,例如支持Https的Gateway定义如下:name=https-gateway, namespace=tsp,而具体服务的VirtualService定义在tsp2命名空间下,则可以在该tsp2命名空间下的VirtualService通过tsp/https-gateway进行跨namespace的Gateway绑定,官网示例如下:
VirtualService gateway说明:
参考链接:
gateway官方API - 1.1版本
VirtualService官方API - 1.1版本