因語雀與csdn markdown 格式有區別,請查看原文:
https://www.yuque.com/dycloud/pss8ys
一、Egress Listener 流量策略
前面學習了 sidecar 自動注入原理、inbound Listener、outbound Listener 等概念,也知道了 EgressListener 的流量策略是有兩個:<font style="color:#DF2A3F;">ALLOW_ANY</font>
和 <font style="color:#DF2A3F;">REGISTRY_ONLY</font>
,這里來詳細的學習一下 這兩種策略的區別
1.1 ALLOW_ANY 和 REGISTRY_ONLY 定義
<font style="color:#DF2A3F;">ALLOW_ANY</font>
(默認模式):允許 Pod 訪問任何外部服務(不管是否在服務注冊表中),對于未注冊的目標,Sidecar 執行透傳(<font style="color:#DF2A3F;">Passthrough</font>
),但這些外部目標流量無法納入到治理體系中,實施如<font style="color:#DF2A3F;">retry</font>
、<font style="color:#DF2A3F;">timeout</font>
和<font style="color:#DF2A3F;">fault injection</font>
一類的功能。<font style="color:#DF2A3F;">REGISTRY_ONLY</font>
(限制模式):只允許訪問明確注冊的服務(Kubernetes Service 或 ServiceEntry),拒絕所有未注冊的外部服務(返回 HTTP 502 或者 TCP 連接錯誤)。
1.2 查看當前策略
<font style="color:#DF2A3F;">Egress Listener </font>
流量的策略配置由 Istio 的全局配置 MeshConfig 控制,配置在 <font style="color:#DF2A3F;">istio-system</font>
命名空間的 <font style="color:#DF2A3F;">istio ConfigMap</font>
中
查看當前全局策略:
[root@k8s-master01 ~]# kubectl get configmap istio -n istio-system -o yaml
...
outboundTrafficPolicy:mode: ALLOW_ANYegressProxy: # 可選出口代理配置
...
查看 Sidecar 級別的策略:
[root@k8s-master01 ~]# kubectl get sidecar -n app client -o yaml | grep outboundTrafficPolicy{"apiVersion":"networking.istio.io/v1beta1","kind":"Sidecar","metadata":{"annotations":{},"name":"client","namespace":"app"},"spec":{"egress":[{"hosts":["./*"],"port":{"name":"frontend","number":80,"protocol":"HTTP"}}],"outboundTrafficPolicy":{"mode":"REGISTRY_ONLY"},"workloadSelector":{"labels":{"app":"client"}}}}outboundTrafficPolicy:
1.3 修改策略配置
全局策略修改:
[root@k8s-master01 ~]# kubectl edit configmap istio -n istio-system
data:mesh: |-outboundTrafficPolicy:mode: REGISTRY_ONLY # 修改此處
[root@k8s-master01 ~]# kubectl get configmap istio -n istio-system -o jsonpath='{.data.mesh}' | grep -A 2 outboundTrafficPolicy
outboundTrafficPolicy:mode: REGISTRY_ONLY
accessLogFile: /dev/stdout
命名空間級覆蓋
apiVersion: networking.istio.io/v1
kind: Sidecar
metadata:annotations:kubectl.kubernetes.io/last-applied-configuration: |{"apiVersion":"networking.istio.io/v1beta1","kind":"Sidecar","metadata":{"annotations":{},"name":"client","namespace":"app"},"spec":{"egress":[{"hosts":["./*"],"port":{"name":"frontend","number":80,"protocol":"HTTP"}}],"outboundTrafficPolicy":{"mode":"REGISTRY_ONLY"},"workloadSelector":{"labels":{"app":"client"}}}}creationTimestamp: "2025-08-05T07:41:14Z"generation: 2name: clientnamespace: appresourceVersion: "7432144"uid: 05872ea2-2a25-432a-b2d4-1402e555bf3c
spec:egress:- hosts:- ./*port:name: frontendnumber: 80protocol: HTTPoutboundTrafficPolicy:mode: REGISTRY_ONLYworkloadSelector:labels:app: client
1.4 ALLOW_ANY 模式詳解
1.4.1 處理流程
- 業務容器 發起請求 external.com:80。
- iptables 把流量重定向到本地 Envoy 代理(15001端口)。
- Envoy 檢查注冊表(即 Istio 下發的集群、服務路由規則)。
- 如果目標已在注冊表中(如有 ServiceEntry 或 K8s Service),走“智能路由”(可做流控、灰度、限流等)。
- 如果目標未注冊,則創建 ORIGINAL_DST 集群,即透明代理:Envoy 將請求直接轉發到原IP:Port(sidecar不干預,全部經過 passthrough)。
- 響應路徑反向返回給業務容器。
這里設計到幾個概念,ORIGINAL_DST 集群、TCP 協議透傳,下面來學習下
1.4.2 透傳(Passthrough)
當 Sidecar 代理到未注冊的外部目標時,直接使用原始請求轉發而不進行任何處理。
特點:
- 不修改請求內容(TCP 轉發)
- 不應用任何流量策略(如重試、超時、負載均衡等)
- 不收集應用層指標(僅基礎 TCP 指標)
- 類似于網絡中的透明代理,只負責轉發,不干預內容。
- 在
<font style="color:#DF2A3F;">ORIGINAL_DST</font>
模式下,原始報文中的 IP 和端口信息會被完整保留。
信息元素 | 是否保留 | 說明 |
---|---|---|
源 IP 地址 | ? 完全保留 | Pod 的實際 IP 地址 |
源端口 | ? 完全保留 | 應用程序分配的原始端口 |
目標 IP 地址 | ? 完全保留 | 應用程序指定的目標 IP |
目標端口 | ? 完全保留 | 應用程序指定的目標端口 |
協議類型 | ? 完全保留 | TCP/UDP 等傳輸層協議 |
透傳的觸發條件:
- 僅在
**<font style="color:#DF2A3F;">ALLOW_ANY</font>**
模式下生效 - 目標服務**未**在Istio服務注冊表中注冊(即不是Kubernetes Service或ServiceEntry)
1.4.3 ORIGINAL_DST 集群
**<font style="color:#DF2A3F;">ORIGINAL_DST</font>**
是Envoy支持的一種特殊集群類型。- 當使用這種集群時,Envoy會將流量轉發到**原始目標地址**(即未被iptables重定向前的目標地址)。
- 在Istio中,它用于處理未注冊外部流量的透傳。
特性 | 說明 |
---|---|
目標獲取 | 通過Linux內核的 <font style="color:#DF2A3F;">SO_ORIGINAL_DST</font> 選項獲取原始目標 |
負載均衡 | 無負載均衡,每個請求直連原始目標 |
協議處理 | 僅TCP層轉發,不解析應用層協議 |
連接管理 | 不應用連接池、健康檢查等高級功能 |
[root@k8s-master01 ~]# istioctl proxy-config route frontend-7c55c868cf-6mpj7 -n app --name 8080 -o yaml
...- '*'includeRequestAttemptCount: truename: allow_anyroutes:- match:prefix: /name: allow_anyroute:cluster: PassthroughClustermaxGrpcTimeout: 0stimeout: 0s
1.5 REGISTRY_ONLY 模式詳解
1.5.1 處理流程
1. **App 發起出站請求 **unregistered.com
- 流量被 iptables 劫持到本地 Envoy(sidecar)。
2. Envoy 檢查本地服務注冊表緩存
- Envoy 在內存中緩存了 Istiod 下發的服務注冊數據(如集群、目標域名/IP)。
- 分兩種情況:
- 已緩存且目標注冊:直接正常路由出站
- 已緩存但目標未注冊:立刻返回 502 錯誤,不再向 Istiod 查詢
3. 緩存未命中——Envoy 請求 Istiod 服務發現(xDS接口)
- Envoy 沒見過這個目標,向 Istiod 發起 xDS 查詢,請求目標主機的配置
4. Istiod 檢查 **<font style="color:#DF2A3F;">ServiceEntry</font>**
/K8s Service
- 如果注冊表中有目標(unregistered.com已登記):
- 返回目標的集群信息,Envoy補全本地緩存,進入正常路由流程
- 如目標未注冊:
- Istiod 返回“空配置”(無可達目標),Envoy 依照標準處理
5. Envoy 依實際配置處理請求
- 目標未注冊:Envoy 返回 502(Bad Gateway)給應用層
- 目標已注冊:Envoy 按配置發送請求,響應正常
1.5.2 BlackHoleCluster 集群
BlackHoleCluster 是 Envoy 代理中的一種特殊集群類型,在 Istio REGISTRY_ONLY 模式下有以下功能:
- 丟棄所有發送到該集群的流量
- 實現嚴格的出口流量控制
- 當目標未在 Istio 注冊表中注冊時才會觸發。
特性 | BlackHoleCluster | 標準集群 |
---|---|---|
端點數量 | 0 (空列表) | ≥1 |
流量處理 | 立即丟棄 | 正常路由 |
響應類型 | 協議感知拒絕 | 成功響應 |
配置方式 | 動態生成 | 靜態/動態 |
監控指標 | 明確拒絕計數 | 成功/失敗統計 |
1.5.3 協議特定的拒絕行為
協議類型 | 拒絕信號 | 客戶端表現 | Wireshark 特征 |
---|---|---|---|
HTTP/1.x | 502 Bad Gateway | <font style="color:rgb(251, 71, 135);">curl: (52) Empty reply</font> | [RST] 包 |
HTTP/2 | GOAWAY 幀 | <font style="color:rgb(251, 71, 135);">curl: (92) HTTP/2 stream 0 was not closed</font> | HTTP/2 GOAWAY |
HTTPS | TLS Alert | <font style="color:rgb(251, 71, 135);">curl: (35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL</font> | TLS Alert 21 |
gRPC | UNAVAILABLE | <font style="color:rgb(251, 71, 135);">status=14 UNAVAILABLE</font> | gRPC 狀態碼 |
Raw TCP | Connection reset | <font style="color:rgb(251, 71, 135);">connect: connection reset by peer</font> | [RST, ACK] 包 |
二、ServiceEntry
2.1 ServiceEntry 定義
ServiceEntry 是將外部服務注冊到 Istio 服務網格中的 CRD 資源,他可以擴展服務網格的發現范圍、定義外部服務的協議和端口特性、控制網格對外部服務的訪問策略等等。
<font style="color:#DF2A3F;">ServiceEntry CR</font>
就用于向Istio內部維護的服務注冊表(Registry)上手動添加注冊項(即Entry)從而將那些未能自動添加至網格中的服務,以手動形式添加至網格中- 向Istio的服務注冊表添加一個
<font style="color:#DF2A3F;">ServiceEntry</font>
后,網格中的Envoy可以流量發送給該Service,其行為與訪問網格中原有的服務并無本質上的不同; - 有了ServiceEntry,用戶也就能像治理網格內部流量一樣來治理那些訪問到網格外部的服務的流量。
2.2 ServiceEntry 功能介紹
- 重定向和轉發訪問外部目標的流量,例如哪些訪問網格外部的傳統服務的流量
- 可以為外部目標添加高級流量治理功能,如
<font style="color:#DF2A3F;">retry</font>
(重試)、<font style="color:#DF2A3F;">timeout</font>
(超時)、<font style="color:#DF2A3F;">fault injection</font>
(故障注入)和<font style="color:#DF2A3F;"> circuit breaker</font>
(熔斷)等一類功能。 - 可以將 VM 添加到網格中,從而能夠在 VM 上運行網格的服務。
- 可以將不同集群中的服務添加到網格中,讓 k8s 配置多集群的 istio 網格。
這里需要注意點是,訪問外部服務時,之前學習的 Sidecar Envoy 本身就可以支持將這些外部的流量直接通過 <font style="color:#DF2A3F;">Passthrough</font>
到外部的端點上,所以 <font style="color:#DF2A3F;">ServiceEntry</font>
并不是一個必須添加的資源。
使用 ServiceEntry 是為了能夠更好的對外部流量進行 Istio 自帶的高級流量治理功能,具體的治理機制還是要靠之前學習的 <font style="color:#DF2A3F;">VirtualService</font>
和 <font style="color:#DF2A3F;">DestinationRule</font>
來實現。
2.3 ServiceEntry 處理的服務類型
ServiceEntry 主要解決兩類服務的集成問題:
<font style="color:#DF2A3F;">MESH_EXTERNAL</font>
:網格外部的服務- Kubernetes 集群外部的服務(虛擬機、物理機)
- 非 Istio 管理的 Kubernetes 命名空間中的服務
<font style="color:#DF2A3F;">MESH_INTERNAL</font>
:網格內部但沒有自動注冊的服務- 網格內運行但未注冊到 istio 服務注冊表的服務
- 需要特殊處理的服務端點
2.4 ServiceEntry CR 資源定義
ServiceEntry本身用于描述要引入的外部服務的屬性,主要包括服務的DNS名稱、IP地址、端口、協議和相關的端點等;
- 端點的獲取方式有三種:
- DNS名稱解析
- 靜態指定:直接指定要使用端點
- 使用
**<font style="color:#DF2A3F;">workloadSelector</font>**
:基于標簽選擇器匹配Kubernetes Pod,或者由**<font style="color:#DF2A3F;">WorkloadEntry</font>**
CR引入到網格中的外部端點
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:name: external-service
spec:hosts:- api.external.com # 關鍵標識符location: MESH_EXTERNAL # 或 MESH_INTERNALports:- number: 443name: httpsprotocol: HTTPSresolution: DNS # 端點解析方式endpoints: # 靜態端點列表- address: 192.168.1.10ports:https: 8443workloadSelector: # 動態端點選擇器labels:app: legacy-backend
2.4.1 <font style="color:rgb(251, 71, 135);">hosts</font>
字段
- 作用:服務標識符,用于
<font style="color:#DF2A3F;">VirtualService</font>
和<font style="color:#DF2A3F;">DestinationRule</font>
匹配 - 協議特定行為:
- HTTP 流量:匹配
<font style="color:rgb(251, 71, 135);">Host</font>
/<font style="color:rgb(251, 71, 135);">Authority</font>
頭 - TLS 流量:匹配 SNI(Server Name Indication)
- TCP 流量:僅通過端口匹配
- HTTP 流量:匹配
示例:
hosts:
- "*.example.com" # 通配符支持
- "api.external.com"
2.4.2 <font style="color:#DF2A3F;">location</font>
類型
類型 | 場景 | 流量特征 |
---|---|---|
<font style="color:rgb(251, 71, 135);">MESH_EXTERNAL</font> | 外部API、云服務 | 出口流量,通常需要加密 |
<font style="color:rgb(251, 71, 135);">MESH_INTERNAL</font> | 網格內未注冊服務 | 內部流量,可應用完整網格策略 |
2.4.3 <font style="color:#DF2A3F;">resolution</font>
解析方式
模式 | 工作原理 | 適用場景 | Envoy 等效模式 |
---|---|---|---|
<font style="color:rgb(251, 71, 135);">NONE</font> | 假設地址已解析 | 已有負載均衡器 | ORIGINAL_DST |
<font style="color:rgb(251, 71, 135);">STATIC</font> | 使用endpoints字段中指定 的靜態IP地址作為與服務關系的實例 | 固定IP服務 | STATIC |
<font style="color:rgb(251, 71, 135);">DNS</font> | 通過異步查詢DNS來解析IP地址;類似于Envoy Cluster發現Endpoint的<font style="color:#DF2A3F;">STRICT_DNS</font> | 動態DNS服務 | STRICT_DNS |
<font style="color:rgb(251, 71, 135);">DNS_ROUND_ROBIN</font> | 通過異步查詢DNS來解析IP地址,但與前者不同的是,僅在需要啟動新連接時使用返回的第 一個IP地址,而不依賴于DNS解析的完整結果;類似于Envoy Cluster發現Endpoint的<font style="color:#DF2A3F;">LOGICAL_DNS</font> | 大型服務 | LOGICAL_DNS |
2.4.3 三種端點發現機制
靜態端點示例:
endpoints:
- address: 192.168.1.10ports:https: 8443 # 覆蓋服務級端口labels:env: prod
- address: 192.168.1.11ports:https: 8444
workloadSelector 示例
workloadSelector:labels:app: legacy-appenv: prod
2.5 ServiceEntry 的集成機制
2.5.1 配置生成流程
ServiceEntry之于Istio來說,其功能類似于自動發現并注冊的Service對象,主要負責于網格中完成如下功能:
- 基于指定的端口創建Listener,若已存在相應的偵聽器,則于偵聽器上基于hosts的定義,生成
<font style="color:#DF2A3F;">VirtualHost</font>
- 基于解析(resolution)得到的端點創建Cluster
- 生成Route Rule,設定偵聽器將接收到的發往相應VirtualHost的流量,路由至生成的Cluster
2.5.1.1 Listener 生成
- 基于
<font style="color:rgb(251, 71, 135);">ports</font>
創建新監聽器 - 或擴展現有監聽器的 VirtualHost
- 示例配置:
{"name": "0.0.0.0_443","filter_chains": [{"filters": [{"name": "envoy.filters.network.http_connection_manager","typed_config": {"route_config": {"virtual_hosts": [{"name": "api.external.com:443","domains": ["api.external.com"]}]}}}]}]
}
2.5.1.2 Cluster 生成
- 基于
<font style="color:rgb(251, 71, 135);">resolution</font>
和端點信息創建
{"name": "outbound|443||api.external.com","type": "STRICT_DNS","load_assignment": {"cluster_name": "api.external.com","endpoints": [{"lb_endpoints": [{"endpoint": {"address": {"socket_address": {"address": "api.external.com","port_value": 443}}}}]}]}
}
2.5.1.3 Route 生成
將流量路由到生成的 Cluster
{"name": "api.external.com","domains": ["api.external.com"],"routes": [{"match": {"prefix": "/"},"route": {"cluster": "outbound|443||api.external.com"}}]
}
2.5.2 自定義流量管理
- 可自定義VirtualService修改
<font style="color:#DF2A3F;">ServiceEntry</font>
默認生成的<font style="color:#DF2A3F;">Routes</font>
- 通過指定的
<font style="color:#DF2A3F;">hosts</font>
(主機名)適配到要修改的Route的位置 - 路由目標配置等可按需進行定義,包括將流量路由至其它目標
- 通過指定的
- 可自定義
<font style="color:#DF2A3F;">DestinationRule</font>
修改ServiceEntry默認生成的<font style="color:#DF2A3F;">Cluster</font>
- 通過指定的hosts(主機名)適配到要修改的Cluster
- 常用于集群添加各種高級設定,例如
<font style="color:#DF2A3F;">subset</font>
、<font style="color:#DF2A3F;">circuit breaker</font>
、<font style="color:#DF2A3F;"> traffic policy</font>
等;
2.5.2.1 VirtualService 定制管理示例
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:name: custom-api-routing
spec:hosts:- api.external.com # 匹配ServiceEntry的hostshttp:- match:- headers:x-env: exact: canaryroute:- destination:host: api.external.comsubset: canary- route:- destination:host: api.external.comsubset: stable
2.5.2.2 DestinationRule 增強示例
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:name: api-policy
spec:host: api.external.comtrafficPolicy:loadBalancer:simple: ROUND_ROBINconnectionPool:tcp:maxConnections: 100subsets:- name: canarylabels:version: v2trafficPolicy:loadBalancer:simple: LEAST_CONN- name: stablelabels:version: v1
2.6 ServiceEntry 配置案例
這里有一個詳細的案例,包括多個Nginx服務部署在Docker Compose中)和一個Kubernetes集群中的客戶端。客戶端通過Istio的<font style="color:#DF2A3F;">ServiceEntry</font>
訪問外部<font style="color:#DF2A3F;">Nginx</font>
服務
2.6.1 案例環境準備
1. Docker Compose 配置
運行三個Nginx服務,每個服務:
- 使用特定版本的Nginx鏡像(1.25-alpine或1.26-alpine)
- 掛載自定義HTML目錄(顯示不同內容)
- 在Docker網絡
<font style="color:#DF2A3F;">nginx_net</font>
(172.31.201.0/24)中有固定IP - 關鍵:將容器80端口映射到宿主機的特定IP和端口(如 10.122.24.139:8091)
注意:宿主機的IP(10.122.24.x)是Kubernetes節點能訪問的IP。
2. Kubernetes 客戶端配置
- Deployment:創建一個Pod,添加hostAliases將
nginx.dujie.com
和nginx
解析到172.29.1.201(注意:這里只寫了一個IP,但ServiceEntry會覆蓋這個解析) - Service:為客戶端Pod創建ClusterIP服務(非必須,本案例中客戶端不需要被訪問)
2.6.2 創建命名空間并添加自動注入
kubectl create ns entry
kubectl label namespace entry istio-injection=enabled
2.6.3 創建 Client 資源
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: clientname: clientnamespace: entry
spec:replicas: 1selector:matchLabels:app: clientversion: v1.2template:metadata:labels:app: clientversion: v1.2spec:hostAliases:- hostnames: ["nginx.dujie.com", "nginx"]ip: '172.29.1.201'containers:- image: ikubernetes/admin-box:v1.2name: admin-boxcommand: ['/bin/sh', '-c', 'sleep INFINITE']
---
apiVersion: v1
kind: Service
metadata:labels:app: clientname: clientnamespace: entry
spec:ports:- name: http-80appProtocol: httpport: 80protocol: TCPtargetPort: 80selector:app: clientversion: v1.2type: ClusterIP
2.6.4 ServiceEntry 資源配置
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:name: nginx-externalnamespace: entry
spec:hosts:- nginx.dujie.com- nginxaddresses: # 定義服務的虛擬IP列表- "10.122.24.139"# Service Portports:- number: 80name: httpprotocol: HTTPlocation: MESH_EXTERNALresolution: STATICendpoints:- address: "10.122.24.139"ports:http: 8091- address: "10.122.24.139"ports:http: 8092- address: "10.122.24.139"ports:http: 8093
**<font style="color:rgb(251, 71, 135);">addresses</font>**
字段
- ****定義該服務的虛擬IP地址(VIP)列表
- 覆蓋DNS解析:當應用訪問
<font style="color:#DF2A3F;">nginx.dujie.com</font>
時,Istio 會強制解析為這些IP(而不是真實DNS記錄) - 流量劫持:Envoy Sidecar 會攔截目標為這些IP的流量
為什么需要:
- 如果外部服務有多個IP,但DNS只返回一個(如輪詢解析),用此字段確保所有IP都被識別
- 避免DNS污染:即使客戶端緩存了舊IP,流量也會被正確劫持
**<font style="color:#DF2A3F;">endpoints</font>**
字段
- 作用:定義服務的實際后端實例(Endpoint)列表
- 關鍵屬性:
<font style="color:#DF2A3F;">address</font>
:后端實例的真實IP<font style="color:#DF2A3F;">ports</font>
:實例暴露的實際端口(可不同于服務的虛擬端口)
2.6.5 DestinationRule 配置
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:name: nginx-externalnamespace: entry
spec:host: nginx.dujie.comtrafficPolicy:loadBalancer:consistentHash:httpHeaderName: x-userconnectionPool:tcp:maxConnections: 10000connectTimeout: 10mstcpKeepalive:time: 7200sinterval: 75shttp:http2MaxRequests: 1000maxRequestsPerConnection: 10outlierDetection:maxEjectionPercent: 50consecutive5xxErrors: 5interval: 2mbaseEjectionTime: 1mminHealthPercent: 40
2.6.6 VirtualService 配置準備
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:name: nginx-externalnamespace: entry
spec:hosts:- nginx.dujie.comhttp:- name: falut-injectionmatch:- headers:X-Testing:exact: "true"route:- destination:host: nginx.dujie.comfault:delay:percentage:value: 5fixedDelay: 2sabort:percentage:value: 5httpStatus: 555- name: nginx-externalroute:- destination:host: nginx.dujie.com
2.6.6 Docker-compose 配置
version: '3.3'services:nginx2501:image: nginx:1.25-alpinevolumes:- ./html/nginx2501:/usr/share/nginx/html/networks:nginx_net:ipv4_address: 172.31.201.11aliases:- nginxexpose:- "80"ports:- "10.122.24.139:8091:80"nginx2502:image: nginx:1.25-alpinevolumes:- ./html/nginx2502:/usr/share/nginx/html/networks:nginx_net:ipv4_address: 172.31.201.12aliases:- nginxexpose:- "80"ports:- "10.122.24.139:8092:80"nginx2601:image: nginx:1.26-alpinevolumes:- ./html/nginx2601:/usr/share/nginx/html/networks:nginx_net:ipv4_address: 172.31.201.13aliases:- nginx- canaryexpose:- "80"ports:- "10.122.24.139:8093:80"networks:nginx_net:driver: bridgeipam:config:- subnet: 172.31.201.0/24
docker-compose 中每個容器都會掛在不同的 index 目錄
[root@k8s-master01 /usr/local/src]# cat nginx2501/index.html
<title>nginx.dujie.com</title>
Nginx 2501 ~~
[root@k8s-master01 /usr/local/src]# cat nginx2502/index.html
<title>nginx.dujie.com</title>
Nginx 2502 ~~
[root@k8s-master01 /usr/local/src]# cat nginx2601/index.html
<title>nginx.dujie.com</title>
Nginx 2601 ~~
2.6.7 測試
2.6.7.1 測試基本訪問
會輪流返回
[root@k8s-master01 /usr/local/src]# kubectl get pods -n entry
NAME READY STATUS RESTARTS AGE
client-78c98df4f6-2x6lk 2/2 Running 0 86m
[root@k8s-master01 /usr/local/src]# kubectl exec -it -n entry client-78c98df4f6-2x6lk -- bash
root@client-78c98df4f6-2x6lk /# while true; do CONTENT=$(curl -s -H "x-canary: true" nginx.dujie.com); echo $CONTENT; sleep 0.$RANDOM; done
<title>nginx.dujie.com</title> Nginx 2501 ~~
<title>nginx.dujie.com</title> Nginx 2601 ~~
<title>nginx.dujie.com</title> Nginx 2501 ~~
<title>nginx.dujie.com</title> Nginx 2502 ~~
<title>nginx.dujie.com</title> Nginx 2601 ~~
<title>nginx.dujie.com</title> Nginx 2501 ~~
<title>nginx.dujie.com</title> Nginx 2601 ~~
<title>nginx.dujie.com</title> Nginx 2501 ~~
<title>nginx.dujie.com</title> Nginx 2502 ~~
<title>nginx.dujie.com</title> Nginx 2501 ~~
<title>nginx.dujie.com</title> Nginx 2502 ~~
2.6.7.2 測試會話保持
可以看到請求頭中攜帶 x-user 字段的請求都會被轉發到同一臺后端節點
root@client-78c98df4f6-2x6lk /# while true; do CONTENT=$(curl -s -H "x-user: dujie" nginx.dujie.com); echo $CONTENT; sleep 0.$RANDOM; done
<title>nginx.dujie.com</title> Nginx 2601 ~~
<title>nginx.dujie.com</title> Nginx 2601 ~~
<title>nginx.dujie.com</title> Nginx 2601 ~~
<title>nginx.dujie.com</title> Nginx 2601 ~~
<title>nginx.dujie.com</title> Nginx 2601 ~~
<title>nginx.dujie.com</title> Nginx 2601 ~~
<title>nginx.dujie.com</title> Nginx 2601 ~~
<title>nginx.dujie.com</title> Nginx 2601 ~~
<title>nginx.dujie.com</title> Nginx 2601 ~~
<title>nginx.dujie.com</title> Nginx 2601 ~~
2.6.7.3 測試故障注入
可以看到下面的會有 5%的請求被返回 555,5%的請求會延遲 2 秒
root@client-78c98df4f6-2x6lk /# while true; do CONTENT=$(curl -s -H "X-Testing: true" nginx.dujie.com); echo $CONTENT; sleep 0.$RANDOM; done
<title>nginx.dujie.com</title> Nginx 2501 ~~<title>nginx.dujie.com</title> Nginx 2502 ~~
<title>nginx.dujie.com</title> Nginx 2502 ~~
<title>nginx.dujie.com</title> Nginx 2601 ~~
<title>nginx.dujie.com</title> Nginx 2501 ~~
<title>nginx.dujie.com</title> Nginx 2502 ~~
<title>nginx.dujie.com</title> Nginx 2501 ~~
<title>nginx.dujie.com</title> Nginx 2502 ~~
<title>nginx.dujie.com</title> Nginx 2501 ~~
<title>nginx.dujie.com</title> Nginx 2501 ~~
<title>nginx.dujie.com</title> Nginx 2501 ~~
<title>nginx.dujie.com</title> Nginx 2502 ~~
<title>nginx.dujie.com</title> Nginx 2501 ~~
<title>nginx.dujie.com</title> Nginx 2601 ~~
<title>nginx.dujie.com</title> Nginx 2601 ~~
<title>nginx.dujie.com</title> Nginx 2601 ~~
<title>nginx.dujie.com</title> Nginx 2501 ~~
<title>nginx.dujie.com</title> Nginx 2501 ~~
<title>nginx.dujie.com</title> Nginx 2502 ~~
fault filter abort
<title>nginx.dujie.com</title> Nginx 2501 ~~
<title>nginx.dujie.com</title> Nginx 2502 ~~
<title>nginx.dujie.com</title> Nginx 2501 ~~
<title>nginx.dujie.com</title> Nginx 2501 ~~
<title>nginx.dujie.com</title> Nginx 2501 ~~
<title>nginx.dujie.com</title> Nginx 2501 ~~
2.6.7.4 查看端點信息
這里也可以看到三個節點已經被 istio 的 endpoint 管理了
[root@k8s-master01 ~]# istioctl proxy-config endpoint client-78c98df4f6-2x6lk --cluster "outbound|80||nginx.dujie.com" -n entry
ENDPOINT STATUS OUTLIER CHECK CLUSTER
10.122.24.139:8091 HEALTHY OK outbound|80||nginx.dujie.com
10.122.24.139:8092 HEALTHY OK outbound|80||nginx.dujie.com
10.122.24.139:8093 HEALTHY OK outbound|80||nginx.dujie.com
三、WorkloadEntry 和 WorkloadGroup
上面已經通過 ServiceEntry 可以實現將服務網格外的應用通過 Istio 服務網格來管理了,而 ServiceEntry 他有一些局限性:
- 靜態配置:端點(IP)變更需要手動更新
- 無實例管理:無法感知端點健康狀態
- 無身份:難以對端點實施mTLS
- 不適合VM接入:無法將VM作為網格內服務提供者
痛點總結:ServiceEntry 適合訪問外部服務,但不適合將外部工作負載(如VM)作為網格內服務提供者。
所以 Istio 提供了 WorkloadEntry 來解決以上 ServiceEntry 無法處理的痛點。
特性 | ServiceEntry | WorkloadEntry |
---|---|---|
目標 | 定義外部服務 | 注冊工作負載實例 |
層級 | 服務級別 | 端點級別 |
使用場景 | 訪問外部API/DB | 將VM納入網格 |
關聯關系 | 獨立存在 | 需關聯Service |
動態性 | 靜態配置 | 支持動態注冊 |
3.1 WorkloadEntry 定義及資源規范
<font style="color:#DF2A3F;">workloadEntry</font>
是用于標識非 Kubernetes 工作負載的 Istio 資源對象。他可以將虛擬機、物理機或者外部服務等**非容器化工作負載**注冊到 Istio 服務網格中的端點上。
- 將 VM/物理機作為服務端點集成到服務網格
- 使非容器工作負載能參與服務發現
- 應用相同的流量管理策略(路由、負載均衡、熔斷)
- 實施一致的安全策略(mTLS、RBAC)
- 實現統一監控(指標、日志、追蹤)
資源規范:
apiVersion: networking.istio.io/v1beta1
kind: WorkloadEntry
metadata:name: vm-nginx # 資源名稱namespace: prod # 必須與關聯Service相同
spec:# --- 核心配置 ---address: 192.168.1.100 # 工作負載IP(必需)labels: # 標簽用于服務選擇(必需)app: nginxenv: prodversion: v1# --- 高級配置 ---serviceAccount: nginx-sa # 服務賬戶(用于mTLS)network: "cloud-vpc" # 網絡標識(多網絡場景)ports: # 端口別名映射http: 8080https: 8443locality: us-west1/zone1 # 地理位置(地域感知)weight: 1 # 流量權重(默認1)
字段 | 必填 | 說明 |
---|---|---|
<font style="color:rgb(251, 71, 135);">address</font> | 是 | 工作負載的 IP 地址 |
<font style="color:rgb(251, 71, 135);">labels</font> | 是 | 用于服務選擇的標簽 |
<font style="color:rgb(251, 71, 135);">serviceAccount</font> | 推薦 | 身份標識(用于 mTLS) |
<font style="color:rgb(251, 71, 135);">ports</font> | 可選 | 端口別名映射(如 http:8080) |
<font style="color:rgb(251, 71, 135);">network</font> | 多網絡必需 | 網絡標識(需與網格配置匹配) |
<font style="color:rgb(251, 71, 135);">locality</font> | 推薦 | 地域信息(格式:region/zone) |
<font style="color:rgb(251, 71, 135);">weight</font> | 可選 | 流量權重(默認1) |
3.2 WorkloadGroup 定義及資源規范
WorkloadGroup 是 <font style="color:#DF2A3F;">WorkloadEntry</font>
的模板和分組機制,用于自動化管理一組相似的非容器工作負載。它定義了工作負載的公共配置,并支持通過 <font style="color:rgb(251, 71, 135);">istioctl</font>
自動配置工作負載。
- 批量管理:統一配置一組相似工作負載
- 自動注冊:通過
<font style="color:rgb(251, 71, 135);">istioctl</font>
自動生成配置文件 - 配置標準化:確保工作負載配置一致性
- 健康檢查:定義統一健康檢查標準
- 簡化運維:減少手動配置錯誤
資源規范:
apiVersion: networking.istio.io/v1alpha3
kind: WorkloadGroup
metadata:name: nginx-vms # 工作組名稱namespace: prod # 命名空間
spec:# --- 公共元數據 ---metadata:labels: # 應用到所有工作負載的標簽app: nginxenv: prodannotations: # 應用到所有工作負載的注解backup: "daily"# --- WorkloadEntry 模板 ---template:serviceAccount: nginx-sanetwork: "cloud-vpc"ports:http: 8080locality: us-west1/zone1# --- 健康檢查配置 ---probe:periodSeconds: 10 # 檢查間隔initialDelaySeconds: 5 # 初始延遲httpGet: # HTTP檢查port: 8080path: /healthz# tcpSocket: # TCP檢查(替代方案)# port: 3306
字段 | 必填 | 說明 |
---|---|---|
<font style="color:rgb(251, 71, 135);">metadata.labels</font> | 是 | 工作負載公共標簽 |
<font style="color:rgb(251, 71, 135);">metadata.annotations</font> | 可選 | 工作負載注解 |
<font style="color:rgb(251, 71, 135);">template</font> | 是 | WorkloadEntry 模板配置 |
<font style="color:rgb(251, 71, 135);">probe</font> | 推薦 | 健康檢查配置 |
3.3 WorkloadEntry 案例
基于上面 ServiceEntry 的 docker-compose 案例,現在創建兩個 <font style="color:#DF2A3F;">workloadEntry</font>
,客戶端請求時首先通過 <font style="color:#DF2A3F;">vituralService</font>
路由到 <font style="color:#DF2A3F;">ServiceEntry</font>
,再由 <font style="color:#DF2A3F;">ServiceEntry</font>
通過標簽選擇器選擇 <font style="color:#DF2A3F;">WorkloadEntry</font>
,將請求指向 10.122.24.139:8091、8092、8093 端口,最終到達容器內部,架構圖如下:
3.3.1 WorkloadEntry 準備
將 Docker 服務注冊為 Istio 的端點
apiVersion: networking.istio.io/v1beta1
kind: WorkloadEntry
metadata:name: workload-nginx2501namespace: entrylabels:version: v1.25
spec:address: "10.122.24.139"ports:http: 8091labels:app: nginxversion: v1.25instance-id: Nginx2501
---
apiVersion: networking.istio.io/v1beta1
kind: WorkloadEntry
metadata:name: workload-nginx2502namespace: entrylabels:version: v1.25
spec:address: "10.122.24.139"ports:http: 8092labels:app: nginxversion: v1.25instance-id: Nginx2502
3.3.2 創建 ServiceEntry
定義邏輯服務<font style="color:rgb(251, 71, 135);">nginx.dujie.com</font>
,通過<font style="color:rgb(251, 71, 135);">workloadSelector</font>
關聯WorkloadEntry:
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:name: nginx-externalnamespace: entry
spec:hosts:- nginx.dujie.comports:- number: 80name: httpprotocol: HTTPtargetPort: 8091location: MESH_EXTERNAL# NONE, STATIC, DNS, DNS_ROUND_ROBINresolution: STATICworkloadSelector: # 這里通過標簽選擇workloadEntrylabels:app: nginx
3.3.3 創建 DestinationRule
配置服務級別的流量策略
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:name: nginx-externalnamespace: entry
spec:host: nginx.dujie.comtrafficPolicy:loadBalancer:simple: RANDOM # 隨機負載均衡connectionPool: # 連接池設置tcp:maxConnections: 10000connectTimeout: 10mstcpKeepalive:time: 7200sinterval: 75shttp:http2MaxRequests: 1000maxRequestsPerConnection: 10outlierDetection: # 熔斷設置 maxEjectionPercent: 50consecutive5xxErrors: 5 # 5次5xx錯誤觸發熔斷interval: 2mbaseEjectionTime: 1mminHealthPercent: 40
3.3.4 創建 VirtualService
定義路由規則和故障注入:
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:name: nginx-externalnamespace: entry
spec:hosts:- nginx.dujie.comhttp:- name: falut-injectionroute:- destination:host: nginx.dujie.comfault:delay:percentage:value: 20fixedDelay: 2sabort:percentage:value: 20httpStatus: 555
3.3.5 測試驗證
查看服務部署情況
[root@k8s-master01 ~]# kubectl -n entry get serviceentry,workloadentry,destinationrule,virtualservice
NAME HOSTS LOCATION RESOLUTION AGE
serviceentry.networking.istio.io/nginx-external ["nginx.dujie.com"] MESH_EXTERNAL STATIC 165mNAME AGE ADDRESS
workloadentry.networking.istio.io/workload-nginx2501 2m58s 10.122.24.139
workloadentry.networking.istio.io/workload-nginx2502 2m58s 10.122.24.139NAME HOST AGE
destinationrule.networking.istio.io/nginx-external nginx.dujie.com 165mNAME GATEWAYS HOSTS AGE
virtualservice.networking.istio.io/nginx-external ["nginx.dujie.com"] 165m
3.3.5.1 測試基礎連通性
root@client-78c98df4f6-2x6lk /# while true; do CONTENT=$(curl -s nginx.dujie.com); echo $CONTENT; sleep 0.$RANDOM; done
<title>nginx.dujie.com</title> Nginx 2501 ~~
<title>nginx.dujie.com</title> Nginx 2502 ~~
<title>nginx.dujie.com</title> Nginx 2502 ~~
<title>nginx.dujie.com</title> Nginx 2501 ~~
<title>nginx.dujie.com</title> Nginx 2502 ~~
<title>nginx.dujie.com</title> Nginx 2501 ~~
<title>nginx.dujie.com</title> Nginx 2501 ~~
<title>nginx.dujie.com</title> Nginx 2502 ~~
<title>nginx.dujie.com</title> Nginx 2501 ~~
<title>nginx.dujie.com</title> Nginx 2501 ~~
<title>nginx.dujie.com</title> Nginx 2502 ~~
<title>nginx.dujie.com</title> Nginx 2501 ~~
- 請求成功返回 200 OK
- 響應內容包含正確的 Nginx 版本信息
- 流量在 8091 和 8092 之間輪詢
3.3.5.2 故障注入測試
[root@k8s-master01 ~]# kubectl exec -it -n entry client-78c98df4f6-2x6lk bash
root@client-78c98df4f6-2x6lk /# for i in {1..20}; do echo -n "Request $i: "; curl -s -o /dev/null -w "%{http_code} %{time_total}s\n" -H "Host: nginx.dujie.com" http://nginx.dujie.com; sleep 0.5; done
Request 1: 555 0.000795s
Request 2: 200 0.001916s
Request 3: 200 2.002204s
Request 4: 200 0.001498s
Request 5: 200 0.001286s
Request 6: 200 0.001315s
Request 7: 200 0.001337s
Request 8: 200 0.001338s
Request 9: 200 2.001179s
Request 10: 555 0.000843s
Request 11: 200 0.001459s
Request 12: 200 0.001397s
Request 13: 200 0.001349s
Request 14: 200 0.001397s
Request 15: 555 0.000790s
Request 16: 200 0.001291s
Request 17: 200 2.001349s
Request 18: 200 0.001508s
Request 19: 200 0.001303s
Request 20: 200 0.001340s
- 約 20% 請求響應時間 >2 秒
- 約 20% 請求返回 555 狀態碼
- 60% 請求正常響應
3.4 WorkloadEntry 案例 2
基于上面的案例,可以增加一個 WorkloadEntry 作為金絲雀版本
3.4.1 配置 WorloadEntry
apiVersion: networking.istio.io/v1beta1
kind: WorkloadEntry
metadata:name: workload-nginx2501namespace: entry
spec:address: "10.122.24.139"ports:http: 8091labels:app: nginxversion: "v1.25"instance-id: Nginx2501
---
apiVersion: networking.istio.io/v1beta1
kind: WorkloadEntry
metadata:name: workload-nginx2502namespace: entry
spec:address: "10.122.24.139"ports:http: 8092labels:app: nginxversion: "v1.25"instance-id: Nginx2502
---
apiVersion: networking.istio.io/v1beta1
kind: WorkloadEntry
metadata:name: workload-nginx2601namespace: entry
spec:address: "10.122.24.139"ports:http: 8093labels:app: nginxversion: "v1.26"instance-id: Nginx2601
3.4.2 配置 serviceEntry
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:name: nginxnamespace: entry
spec:hosts:- nginx.dujie.comports:- number: 80name: httpprotocol: HTTPlocation: MESH_EXTERNALresolution: STATICworkloadSelector:labels:app: nginx
3.4.3 配置 destinationRule
這里配置了兩個子集,一個是版本 v1.25 另一個是 v1.26
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:name: nginx-externalnamespace: entry
spec:host: nginx.dujie.comtrafficPolicy:loadBalancer:simple: RANDOMconnectionPool:tcp:maxConnections: 10000connectTimeout: 10mstcpKeepalive:time: 7200sinterval: 75shttp:http2MaxRequests: 1000maxRequestsPerConnection: 10outlierDetection:maxEjectionPercent: 50consecutive5xxErrors: 5interval: 2mbaseEjectionTime: 1mminHealthPercent: 40subsets:- name: v25labels:version: "v1.25"- name: v26labels:version: "v1.26"
3.4.4 修改 VirtualService
這里可以基于權重或標頭值進行路由分配,可自行選擇
基于權重:
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:name: nginx-externalnamespace: entry
spec:hosts:- nginx.dujie.comhttp:- name: defaultroute:- destination:host: nginx.dujie.comsubset: v26weight: 5- destination:host: nginx.dujie.comsubset: v25weight: 95
基于標頭
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:name: nginx-externalnamespace: entry
spec:hosts:- nginx.dujie.comhttp:- name: falut-injectionmatch:- headers:x-canary:exact: "true"route:- destination:host: nginx.dujie.comsubset: v26fault:delay:percentage:value: 5fixedDelay: 2s- name: defaultroute:- destination:host: nginx.dujie.comsubset: v25fault:abort:percentage:value: 5httpStatus: 555
3.4.5 測試
3.4.5.1 測試基礎連通性
可以看到流量會在 v1.25 版本進行負載均衡
root@client-78c98df4f6-2x6lk /# while true; do CONTENT=$(curl -s nginx.dujie.com); echo $CONTENT; sleep 0.$RANDOM; done
<title>nginx.dujie.com</title> Nginx 2501 ~~
<title>nginx.dujie.com</title> Nginx 2501 ~~
<title>nginx.dujie.com</title> Nginx 2502 ~~
<title>nginx.dujie.com</title> Nginx 2502 ~~
<title>nginx.dujie.com</title> Nginx 2501 ~~
<title>nginx.dujie.com</title> Nginx 2501 ~~
<title>nginx.dujie.com</title> Nginx 2501 ~~
<title>nginx.dujie.com</title> Nginx 2501 ~~
<title>nginx.dujie.com</title> Nginx 2501 ~~
<title>nginx.dujie.com</title> Nginx 2502 ~~
<title>nginx.dujie.com</title> Nginx 2501 ~~
<title>nginx.dujie.com</title> Nginx 2502 ~~
<title>nginx.dujie.com</title> Nginx 2502 ~~
<title>nginx.dujie.com</title> Nginx 2502 ~~
<title>nginx.dujie.com</title> Nginx 2501 ~~
<title>nginx.dujie.com</title> Nginx 2501 ~~
3.4.5.2 驗證金絲雀發布
可以看到在請求頭中添加 x-canary: true 之后流量就會全部走向 v1.26 版本了
root@client-78c98df4f6-2x6lk /# while true; do CONTENT=$(curl -s -H "x-canary: true" nginx.dujie.com); echo $CONTENT; sleep 0.$RANDOM; done
<title>nginx.dujie.com</title> Nginx 2601 ~~
<title>nginx.dujie.com</title> Nginx 2601 ~~
<title>nginx.dujie.com</title> Nginx 2601 ~~
<title>nginx.dujie.com</title> Nginx 2601 ~~
<title>nginx.dujie.com</title> Nginx 2601 ~~
<title>nginx.dujie.com</title> Nginx 2601 ~~
<title>nginx.dujie.com</title> Nginx 2601 ~~
<title>nginx.dujie.com</title> Nginx 2601 ~~
<title>nginx.dujie.com</title> Nginx 2601 ~~
<title>nginx.dujie.com</title> Nginx 2601 ~~
<title>nginx.dujie.com</title> Nginx 2601 ~~
四、Egress Gateway
4.1 EgressGateway 介紹
Egress Gateway 是 Istio 中專門管理出站流量的網關組件,作為集群內服務訪問外部服務的統一出口。其核心作用類似于企業網絡的防火墻出口,所有內部服務訪問互聯網必須經過此節點。他并不是必須的配置,因為 Istio 內部每個業務 Pod 流量本身就可以直接出去,但有些中大型公司對出口網關有著非常強的合規要求,比如"業務 Pod 不能隨便訪問互聯網",風險不可控等等,這個時候就可以使用<font style="color:#DF2A3F;"> egress gateway</font>
來強制要求所有流量都必須經過它才能出去。
4.2 EgressGateway 使用場景
4.2.1 合規與安全隔離
很多大中型企業(金融/政企/跨云)出網有非常強的合規要求。“業務 pod 隨便訪問互聯網” :風險不可控
強制所有對外訪問都經由 egress gateway,可實現:
- 統一加密協議(如全鏈路 mTLS/TLS)
- 配合防火墻/nat/dlp做敏感數據防泄漏、外聯控制
- 精確控制哪些pod、哪些服務可以訪問哪些外部目標
4.2.2 審計與觀測
出口監控與日志,可獲得:
- 誰在訪問外部什么
- 訪問頻率、性能、異常流量實時分析
- 留痕追責、自動告警、流量快照
4.2.3 細粒度流量治理
通過 <font style="color:#DF2A3F;">egress gateway </font>
可以對所有出口流量實施灰度、熔斷、速率限制、出口流量轉發、with/without proxy、異常檢測等治理措施。
- 地理路由
- 協議轉換
- select 出國出口等
4.2.4 池化出口IP,對VPC/防火墻策略友好
讓流量統一出幾個出口IP,外部方只要信任少數網關IP就行,減少維護量和受信任面。
4.2.5 支持數據脫敏、協議安全轉換
出口網關可以完成加解密、協議規范化處理,把敏感內網數據做脫敏出網等“最后一道關”。
4.3 EgressGateway 安裝
因為我這里 istio 是基于 demo 配置安裝的,默認會自動安裝 egressGateway,而如果使用其他配置安裝則需要手動安裝
手動安裝操作可以查看官網https://istio.io/latest/zh/docs/setup/additional-setup/customize-installation/
需要再 IstioOperator 資源的 components 中指定 egressGateways
,將他的 <font style="color:#DF2A3F;">enabled</font>
設置為 true 即可
4.4 EgressGateway 案例
通過WorkloadEntry將非Kubernetes管理的Nginx實例接入Istio網格,并通過Egress Gateway控制出口流量。
4.4.1 workloadEntry 準備
apiVersion: networking.istio.io/v1beta1
kind: WorkloadEntry
metadata:name: workload-nginx2501namespace: entry
spec:address: "10.122.24.139"ports:http: 8091labels:app: nginxversion: "v1.25"instance-id: Nginx2501
---
apiVersion: networking.istio.io/v1beta1
kind: WorkloadEntry
metadata:name: workload-nginx2502namespace: entry
spec:address: "10.122.24.139"ports:http: 8092labels:app: nginxversion: "v1.25"instance-id: Nginx2502
---
apiVersion: networking.istio.io/v1beta1
kind: WorkloadEntry
metadata:name: workload-nginx2601namespace: entry
spec:address: "10.122.24.139"ports:http: 8093labels:app: nginxversion: "v1.26"instance-id: Nginx2601
4.4.2 serviceEntry 準備
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:name: nginxnamespace: entry
spec:hosts:- nginx.dujie.comports:- number: 80name: httpprotocol: HTTPlocation: MESH_EXTERNALresolution: STATICworkloadSelector:labels:app: nginx
4.4.3 destinationRule 準備
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:name: nginx-externalnamespace: entry
spec:host: nginx.dujie.comtrafficPolicy:loadBalancer:simple: RANDOMconnectionPool:tcp:maxConnections: 10000connectTimeout: 10mstcpKeepalive:time: 7200sinterval: 75shttp:http2MaxRequests: 1000maxRequestsPerConnection: 10outlierDetection:maxEjectionPercent: 50consecutive5xxErrors: 5interval: 2mbaseEjectionTime: 1mminHealthPercent: 40subsets:- name: v25labels:version: "v1.25"- name: v26labels:version: "v1.26"
4.4.4 egressGateway 準備
- 在80端口監聽HTTP流量
- 匹配所有主機(
<font style="color:rgb(251, 71, 135);">"*"</font>
)
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:name: egress-gatewaynamespace: entry
spec:selector:app: istio-egressgatewayservers:- port:number: 80name: httpprotocol: HTTPhosts:- "*"
4.4.5 VirtualService 準備
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:name: nginx-externalnamespace: entry
spec:hosts:- nginx.dujie.comgateways:- egress-gateway- meshhttp:- match:- gateways:- meshroute:- destination:host: istio-egressgateway.istio-system.svc.cluster.local- match:- gateways:- egress-gatewayroute:- destination:host: nginx.dujie.comsubset: v26weight: 5- destination:host: nginx.dujie.comsubset: v25weight: 95
4.4.6 測試驗證
[root@k8s-master01 ~]# istioctl proxy-config endpoints -n entry client-78c98df4f6-2x6lk --cluster 'outbound|80||nginx.dujie.com'
ENDPOINT STATUS OUTLIER CHECK CLUSTER
10.122.24.139:8091 HEALTHY OK outbound|80||nginx.dujie.com
10.122.24.139:8092 HEALTHY OK outbound|80||nginx.dujie.com
10.122.24.139:8093 HEALTHY OK outbound|80||nginx.dujie.com
測試流量分配,v1.26 版本出現的概率在 5%
root@client-78c98df4f6-2x6lk /# while true; do CONTENT=$(curl -s nginx.dujie.com); echo $CONTENT; sleep 0.$RANDOM; done
<title>nginx.dujie.com</title> Nginx 2501 ~~
<title>nginx.dujie.com</title> Nginx 2502 ~~
<title>nginx.dujie.com</title> Nginx 2502 ~~
<title>nginx.dujie.com</title> Nginx 2502 ~~
<title>nginx.dujie.com</title> Nginx 2501 ~~
<title>nginx.dujie.com</title> Nginx 2502 ~~
<title>nginx.dujie.com</title> Nginx 2501 ~~
<title>nginx.dujie.com</title> Nginx 2501 ~~
<title>nginx.dujie.com</title> Nginx 2501 ~~
<title>nginx.dujie.com</title> Nginx 2502 ~~
<title>nginx.dujie.com</title> Nginx 2502 ~~
<title>nginx.dujie.com</title> Nginx 2501 ~~
<title>nginx.dujie.com</title> Nginx 2502 ~~
<title>nginx.dujie.com</title> Nginx 2502 ~~
查看 egressGateway 日志,可以發現 istio 中所有的出口流量都先經過了 egressGateway 了
查看 kiali