Ingress 存取控制
此任務向您展示如何使用授權原則在 Istio ingress 閘道上強制執行基於 IP 的存取控制。
開始之前
在開始此任務之前,請執行以下操作
閱讀 Istio 授權概念。
使用 Istio 安裝指南 安裝 Istio。
在命名空間
foo
中部署工作負載httpbin
,並啟用 Sidecar 注入$ kubectl create ns foo $ kubectl label namespace foo istio-injection=enabled $ kubectl apply -f @samples/httpbin/httpbin.yaml@ -n foo
透過 Ingress 閘道公開
httpbin
使用以下命令驗證
httpbin
工作負載和入口閘道是否如預期般運作$ curl "$INGRESS_HOST:$INGRESS_PORT"/headers -s -o /dev/null -w "%{http_code}\n" 200
將流量導入 Kubernetes 和 Istio
所有將流量導入 Kubernetes 的方法都涉及到在所有工作節點上開啟一個端口。實現此目標的主要功能是 NodePort
服務和 LoadBalancer
服務。即使 Kubernetes 的 Ingress
資源也必須由一個 Ingress 控制器提供支援,該控制器將建立一個 NodePort
或 LoadBalancer
服務。
NodePort
只是在每個工作節點上開啟 30000-32767 範圍內的端口,並使用標籤選擇器來識別將流量發送到哪個 Pod。您必須手動在工作節點前面建立某種類型的負載平衡器,或使用循環 DNS。LoadBalancer
與NodePort
非常相似,但它還會建立一個特定於環境的外部負載平衡器來處理將流量分配到工作節點。例如,在 AWS EKS 中,LoadBalancer
服務會建立一個經典 ELB,並以您的工作節點作為目標。如果您的 Kubernetes 環境沒有LoadBalancer
實現,那麼它將只會像NodePort
一樣運作。Istio 入口閘道會建立一個LoadBalancer
服務。
如果處理來自 NodePort
或 LoadBalancer
的流量的 Pod 沒有在接收流量的工作節點上執行怎麼辦?Kubernetes 有自己的內部代理,稱為 kube-proxy,它接收封包並將它們轉發到正確的節點。
原始用戶端的來源 IP 位址
如果封包通過外部代理負載平衡器和/或 kube-proxy,則客戶端的原始來源 IP 位址會遺失。以下小節將描述一些策略,用於為不同類型的負載平衡器保留原始客戶端 IP 以進行記錄或安全目的
為了方便參考,以下是在常見的受管理 Kubernetes 環境中使用 LoadBalancer
服務由 Istio 建立的負載平衡器類型
雲端供應商 | 負載平衡器名稱 | 負載平衡器類型 |
---|---|---|
AWS EKS | 經典彈性負載平衡器 | TCP 代理 |
GCP GKE | TCP/UDP 網路負載平衡器 | 網路 |
Azure AKS | Azure 負載平衡器 | 網路 |
IBM IKS/ROKS | 網路負載平衡器 | 網路 |
DO DOKS | 負載平衡器 | 網路 |
TCP/UDP Proxy 負載平衡器
如果您使用的是 TCP/UDP 代理外部負載平衡器 (AWS 經典 ELB),它可以使用 PROXY 通訊協定 將原始客戶端 IP 位址嵌入到封包資料中。外部負載平衡器和 Istio 入口閘道都必須支援 PROXY 通訊協定才能使其運作。
以下是一個範例組態,顯示如何在 AWS EKS 上使入口閘道支援 PROXY 通訊協定
網路負載平衡器
如果您使用的是保留客戶端 IP 位址的 TCP/UDP 網路負載平衡器 (AWS 網路負載平衡器、GCP 外部網路負載平衡器、Azure 負載平衡器),或者您使用的是循環 DNS,那麼您可以使用 externalTrafficPolicy: Local
設定來同時保留 Kubernetes 內部的客戶端 IP,方法是繞過 kube-proxy 並防止它將流量傳送到其他節點。
更新入口閘道以設定 externalTrafficPolicy: Local
,使用以下命令保留入口閘道上的原始客戶端來源 IP
HTTP/HTTPS 負載平衡器
如果您使用的是 HTTP/HTTPS 外部負載平衡器 (AWS ALB、GCP),它可以將原始客戶端 IP 位址放入 X-Forwarded-For 標頭中。Istio 可以透過一些組態從此標頭中擷取客戶端 IP 位址。請參閱 設定閘道網路拓撲。如果您在 Kubernetes 前面使用單個負載平衡器,則快速範例
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
meshConfig:
accessLogEncoding: JSON
accessLogFile: /dev/stdout
defaultConfig:
gatewayTopology:
numTrustedProxies: 1
基於 IP 的允許清單和拒絕清單
何時使用 ipBlocks
與 remoteIpBlocks
: 如果您使用 X-Forwarded-For HTTP 標頭或 PROXY 通訊協定來判斷原始客戶端 IP 位址,那麼您應該在您的 AuthorizationPolicy
中使用 remoteIpBlocks
。如果您使用 externalTrafficPolicy: Local
,那麼您應該在您的 AuthorizationPolicy
中使用 ipBlocks
。
負載平衡器類型 | 客戶端 IP 來源 | ipBlocks 與 remoteIpBlocks |
---|---|---|
TCP 代理 | PROXY 通訊協定 | remoteIpBlocks |
網路 | 封包來源位址 | ipBlocks |
HTTP/HTTPS | X-Forwarded-For | remoteIpBlocks |
- 以下命令會為 Istio 入口閘道建立授權原則
ingress-policy
。以下原則會將action
欄位設定為ALLOW
,以允許ipBlocks
中指定的 IP 位址存取入口閘道。不在清單中的 IP 位址將被拒絕。ipBlocks
同時支援單個 IP 位址和 CIDR 標記法。
驗證對入口閘道的請求遭到拒絕
$ curl "$INGRESS_HOST:$INGRESS_PORT"/headers -s -o /dev/null -w "%{http_code}\n" 403
將您的原始客戶端 IP 位址指派給環境變數。如果您不知道它,您可以使用以下命令在 Envoy 日誌中找到它
- 更新
ingress-policy
以包含您的客戶端 IP 位址
驗證對入口閘道的請求被允許
$ curl "$INGRESS_HOST:$INGRESS_PORT"/headers -s -o /dev/null -w "%{http_code}\n" 200
更新
ingress-policy
授權原則以將action
鍵設定為DENY
,以便不允許ipBlocks
中指定的 IP 位址存取入口閘道
驗證對入口閘道的請求遭到拒絕
$ curl "$INGRESS_HOST:$INGRESS_PORT"/headers -s -o /dev/null -w "%{http_code}\n" 403
您可以使用線上代理服務,使用不同的客戶端 IP 來存取入口閘道,以驗證請求是否被允許。
如果您沒有收到預期的回應,請檢視入口閘道日誌,其中應該會顯示 RBAC 偵錯資訊
清除
- 移除授權原則
移除命名空間
foo
$ kubectl delete namespace foo