1.1、背景
寫這篇文章的目的是為了說明以下問題:如何使用TCP協議相同的埠訪問網格外多個服務? 這是最近直播的時候有一個同學提出的,當時我沒有完全明白,“訪問多叢集” 的意思。後來仔細思考了一下,問題應該就是Istio服務網格內如何通過相同的協議,埠訪問不同的服務。
1.2、使用場景
肯定會有人回答,既然相同的埠不能使用,何不換一個埠呢,這樣做也是一種解決方法。我在想有一些場景一定沒法或者不方便繞過去。
1) 假如同一個網格內部署了生產,測試,開發三套環境,都需要通過3306埠訪問對應環境的mysql資料庫。
2) 假如同一個網格內部署了生產,測試,開發三套環境,都需要通過6379埠訪問對應環境的redis。
在微服務盛行的今天,往往需要團隊之間協作,沒辦法保證所有的微服務都執行在同一服務網格內。尤其是中介軟體服務,作為公司公共服務,一定是業務共享的。既然我們不可避免的需要使用相同的埠,訪問外部服務,接下來告訴大家兩種方案解決以上問題。
1.3、解決方案
通過相同的埠443訪問 https://github.com 和 https://www.huaweicloud.com,從網格內訪問外部服務,需要分別建立對應的ServiceEntentry:
1) www.huaweicloud.com
```
cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: hwcloud
spec:
hosts:
- www.huaweicloud.com
ports:
- number: 443
name: tcp
protocol: TCP
resolution: DNS
location: MESH_EXTERNAL
EOF
2) github.com
```
cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: github
spec:
hosts:
- github.com
ports:
- number: 443
name: tcp
protocol: TCP
resolution: DNS
location: MESH_EXTERNAL
EOF
```
兩條規則建好之後,等待pilot將新的配置下發到所有的proxy,我們通過sleep pod驗證連通性
```
$ kubectl exec sleep-754684654f-trpt2 -- curl -sL -o /dev/null https://www.huaweicloud.com –v
…
< HTTP/1.1 200 OK
< Server: NWSs
< Date: Fri, 21 Dec 2018 02:23:11 GMT
< Content-Type: text/html;charset=utf-8
< Content-Length: 703122
< Connection: keep-alive
< Cache-Control: public, max-age=600
< Expires: Fri, 21 Dec 2018 02:33:10 GMT
< Last-Modified: Thu, 20 Dec 2018 10:30:00 GMT
< X-NWS-LOG-UUID: 0d13017f-8767-4399-a509-6c11b2a9f3d0
< Access-Control-Allow-Origin: *
< dl-from: qcloud
< X-Cache-Lookup: Hit From Disktank3
< X-Via: LIANTONG-HENAN_171(200:hit)
<
{ [15930 bytes data]
* Connection #0 to host www.huaweicloud.com left intact
```
```
kubectl exec sleep-754684654f-trpt2 -- curl -sL -o /dev/null https://github.com –v -k
…
< HTTP/1.1 404 Not Found
< Server: NWSs
< Date: Fri, 21 Dec 2018 02:29:26 GMT
< Content-Type: text/html
< Content-Length: 52
< Connection: keep-alive
< X-NWS-LOG-UUID: b283fee3-89e0-48bc-8d6e-0c3a68ecc4bf
< X-Via: LIANTONG-HENAN_25(404:hit)
<
{ [52 bytes data]
* Connection #0 to host github.com left intact
```
由此可見可以在網格內部訪問https://www.huaweicloud.com,但是不可以訪問https://github.com. 這裡有一個原因是istio會將ServiceEntry規則按照建立時間排序,建立時間較早的優先順序高,所以先建立的 hwcloud ServiceEntry生效。
可以檢視sleep pod上的配置來確認:listener配置只有到華為雲的cluster "outbound|443||www.huaweicloud.com"
```
$ istioctl pc listener sleep-754684654f-trpt2 --address=0.0.0.0 --port=443 -ojson
[
{
"name": "0.0.0.0_443",
"address": {
"socketAddress": {
"address": "0.0.0.0",
"portValue": 443
}
},
"filterChains": [
{
"filters": [
{
"name": "mixer",
…
},
{
"name": "envoy.tcp_proxy",
"config": {
"access_log": [
{
…
}
],
"cluster": "outbound|443||www.huaweicloud.com",
"stat_prefix": "outbound|443||www.huaweicloud.com"
}
}
]
}
],
…
}
]
```
為了同時訪問兩者,這裡我提供兩種方法:
1.3.1建立ServiceEntry時指定Address
查詢www.huaweicloud.com域名繫結的ip地址,選擇一個或者多個更新hwcloud ServiceEntry
同樣的方法更新 github
驗證https://www.huaweicloud.com和https://github.com均可以從網格內訪問,因為指定了spec.addresses 後,pilot生成listener使就會使用指定的ip地址代替‘0.0.0.0’的全匹配方式。
雖然著這種方式一定程度上可以解決同一埠訪問外部服務的需求。但是由於需要提前設定ip地址,所以在ip經常變動的場景下缺少靈活性。下面提供一種更靈活的方法。
1.3.2 指定ServiceEntry的作用域
Istio社群最近實現了網路的配置作用域特性:https://github.com/istio/istio/pull/10287, 允許使用者設定相應規則的作用域範圍。
目前 ServiceEntry,VirtualService,Gateway, DestinationRule等都可以通過spec.configScope設定作用範圍。ConfigScope 可以設定為"PUBLIC","PRIVATE"型別。
"PUBLIC" 表示規則對網格內所有的工作負載可見,這也是預設值。
"PRIVATE" 表示規則僅對同一namespace下面的工作負載可見。
因此可以利用ConfigScope將github以及hwcloud都設定成PRIVATE,分別建立在兩個不同的namespace下面。這樣也可以做到ns1內的工作負載訪問https://github.com, ns2內的工作負載訪問https://www.huaweicloud.com .
```
cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: github
namespace: ns1
spec:
hosts:
- github.com
ports:
- number: 443
name: tcp
protocol: TCP
resolution: DNS
location: MESH_EXTERNAL
configScope: PRIVATE
EOF
cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: hwcloud
namespace: ns2
spec:
hosts:
- www.huaweicloud.com
ports:
- number: 443
name: tcp
protocol: TCP
resolution: DNS
location: MESH_EXTERNAL
configScope: PRIVATE
EOF
```
ConfigScope這種方式非常適合前面提到的場景:在同一個微服務網格內同時部署生產,測試環境, 並且生產,測試環境都需要呼叫對應環境的中介軟體服務(快取,資料庫,MQ等)。
1.4、小結
Istio服務網格內,埠衝突導致的服務連通性問題非常常見,但是千變萬化都逃不過Listener - Route – Cluster – Endpoint, Envoy的所有功能歸根到底都是通過這四種配置控制。社群提供的命令列工具:istioctl可以很方便的能夠解析出Envoy的配置,便於快速定位問題。Ref:https://istio.io/help/ops/traffic-management/proxy-cmd/