Istio的流量管理(實操三)
阿新 • • 發佈:2020-08-28
# Istio的流量管理(實操三)
涵蓋官方文件[Traffic Management](https://istio.io/docs/tasks/traffic-management/)章節中的egress部分。其中有一小部分問題(已在下文標註)待官方解決。
[TOC]
## 訪問外部服務
由於啟用了istio的pod的出站流量預設都會被重定向到代理上,因此對叢集外部URL的訪問取決於代理的配置。預設情況下,Envoy代理會透傳對未知服務的訪問,雖然這種方式為新手提供了便利,但最好配置更嚴格的訪問控制。
本節展示使用如下三種方式訪問外部服務:
1. 允許Envoy代理透傳到網格外部的服務
2. 配置[service entries](https://istio.io/docs/reference/config/networking/service-entry/)來訪問外部訪問
3. 透傳某一個IP端的請求
### 部署
- 部署sleep app,用於傳送請求。
```shell
$ kubectl apply -f samples/sleep/sleep.yaml
```
- 設定`SOURCE_POD`為請求源pod名
```shell
$ export SOURCE_POD=$(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name})
```
### Envoy透傳流量到外部服務
istio有一個[安裝選項](https://istio.io/docs/reference/config/istio.mesh.v1alpha1/#MeshConfig-OutboundTrafficPolicy-Mode),`meshConfig.outboundTrafficPolicy.mode`,用於配置sidecar處理外部服務(即沒有定義到istio內部服務註冊中心的服務)。如果該選項設定為`ALLOW_ANY`,則istio代理會放行到未知服務的請求;如果選項設定為`REGISTRY_ONLY`,則istio代理會阻塞沒有在網格中定義HTTP服務或服務表項的主機。預設值為`ALLOW_ANY`,允許快速對istio進行評估。
1. 首先將`meshConfig.outboundTrafficPolicy.mode`選項設定為`ALLOW_ANY`。預設應該就是`ALLOW_ANY`,使用如下方式獲取當前的模式:
```shell
$kubectl get configmap istio -n istio-system -o yaml |grep -o "mode: ALLOW_ANY" |uniq
mode: ALLOW_ANY
```
如果沒有配置模式,可以手動新增:
```
outboundTrafficPolicy:
mode: ALLOW_ANY
```
2. 從網格內向外部服務傳送兩個請求,可以看到請求成功,返回200
```shell
$ kubectl exec -it $SOURCE_POD -c sleep -- curl -I https://www.baidu.com | grep "HTTP/"; kubectl exec -it $SOURCE_POD -c sleep -- curl -I https://edition.cnn.com | grep "HTTP/"
HTTP/1.1 200 OK
HTTP/2 200
```
使用這種方式可以訪問外部服務,但無法對該流量進行監控和控制,下面介紹如何監控和控制網格到外部服務的流量。
### 控制訪問外部服務
使用ServiceEntry配置可以從istio叢集內部訪問公共服務。本節展示如何配置訪問外部HTTP服務,httpbin.org以及www.baidu.com,同時會監控和控制istio流量。
#### 修改預設的阻塞策略
為了展示如何控制訪問外部服務的方式,需要將`meshConfig.outboundTrafficPolicy.mode`設定為`REGISTRY_ONLY`
1. 執行如下命令將`meshConfig.outboundTrafficPolicy.mode`選項設定為`REGISTRY_ONLY`
```shell
$ kubectl get configmap istio -n istio-system -o yaml | sed 's/mode: ALLOW_ANY/mode: REGISTRY_ONLY/g' | kubectl replace -n istio-system -f -
```
2. 從SOURCE_POD訪問外部HTTPS服務,此時請求會被阻塞(可能需要等一段時間來使配置生效)
```shell
$ kubectl exec -it $SOURCE_POD -c sleep -- curl -I https://www.baidu.com | grep "HTTP/"; kubectl exec -it $SOURCE_POD -c sleep -- curl -I https://edition.cnn.com | grep "HTTP/"
command terminated with exit code 35
command terminated with exit code 35
```
#### 訪問外部HTTP服務
1. 建立一個`ServiceEntry`註冊外部服務,這樣就可以直接訪問外部HTTP服務,可以看到此處並沒有用到virtual service和destination rule
> 下面serviceEntry使用`DNS` 作為resolution是一種比較安全的方式,將resolution設定為`NONE`將可能導致攻擊。例如,惡意客戶可能會再HOST首部中設定`httpbin.org`,但實際上訪問的不同的IP地址。istio sidecar代理會信任HOST首部,並錯誤地允許此次訪問(即使會將流量傳遞到不同於主機的IP地址),該主機可能是一個惡意網站,或是一個被網格安全策略遮蔽的合法網站。
>
> 使用`DNS` resolution時,sidecar代理會忽略原始目的地址,並將流量傳遞給`hosts`欄位的主機。在轉發流量前會使用DNS請求`hosts`欄位的IP地址。
>
> serviceEntry包括如下三種[resolution](https://istio.io/latest/docs/reference/config/networking/service-entry/#ServiceEntry-Resolution):
>
> | Name | Description |
> | -------- | ------------------------------------------------------------ |
> | `NONE` | Assume that incoming connections have already been resolved (to a specific destination IP address). Such connections are typically routed via the proxy using mechanisms such as IP table REDIRECT/ eBPF. After performing any routing related transformations, the proxy will forward the connection to the IP address to which the connection was bound. |
> | `STATIC` | Use the static IP addresses specified in endpoints (see below) as the backing instances associated with the service. |
> | `DNS` | Attempt to resolve the IP address by querying the ambient DNS, during request processing. If no endpoints are specified, the proxy will resolve the DNS address specified in the hosts field, if wildcards are not used. If endpoints are specified, the DNS addresses specified in the endpoints will be resolved to determine the destination IP address. DNS resolution cannot be used with Unix domain socket endpoints. |
```shell
$ kubectl apply -