之前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);

Https配置方式

但其实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);

Isito Gateway Https配置

由于目前环境已从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版本

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐