之前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定義,故在綁定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