Istio Destinationrule规则定义后不生效(跨命名空间)
Destinationrule规则定义后不生效(跨命名空间)
现象
- 配置
subset
后无法正常访问nginx资源(default命名空间) - 将vs/gw/dr配置到默认的default空间后可以正常访问
gw和vs配置如下
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:name: bookinfo-gatewaynamespace: istio
spec:selector:istio: ingressgatewayservers:- port:number: 80name: httpprotocol: HTTPhosts:- "*"
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:name: nginxnamespace: istio
spec:hosts:- "*"exportTo: # *,生成的规则让其他网格内访问时也生效- "*"gateways:- bookinfo-gatewayhttp:- match:route:- destination:host: nginx.default.svc.cluster.localport:number: 80
访问测试,可以发现是可以正常访问的
╰─ curl http://192.168.0.15 -I -H "Host:test.com"
HTTP/1.1 200 OK
server: istio-envoy
date: Sat, 08 Apr 2023 15:24:24 GMT
content-type: text/html
content-length: 615
last-modified: Tue, 28 Dec 2021 15:28:38 GMT
etag: "61cb2d26-267"
accept-ranges: bytes
x-envoy-upstream-service-time: 1
由于nginx这个应用有多个版本,需要配置subset,但是配置后,却无法访问,报503,ingress-gateway报: “HEAD / HTTP/1.1” 503 NC cluster_not_found
- “-” 0 0 0 - “172.16.0.1” “curl/7.87.0” “8e119892-3e5d-9edf-8856-265112809263” “192.168.0.15” “-” - - 172.16.0.15:8080 172.16.0.1:37165 - -
# vs&dr配置重,即使将exporTo暴露到所有命名空间,也无法正常访问
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:name: nginxnamespace: istio
spec:hosts:- "*"exportTo:- "*"gateways:- bookinfo-gatewayhttp:- match:route:- destination:host: nginx.default.svc.cluster.localport:number: 80subset: v1
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:name: nginxnamespace: istio
spec:host: nginx.default.svc.cluster.localexportTo:- "*"subsets:- name: v1labels:app: nginx# 访问,可见无法正常访问后面的nginx
╰─ curl http://192.168.0.15 -I
HTTP/1.1 503 Service Unavailable
date: Sat, 08 Apr 2023 15:51:49 GMT
server: istio-envoy
transfer-encoding: chunked# 查看cluster,cluster=outbound|80|v1|nginx.default.svc.cluster.local 在管理业务无法找到,这也就是为什么ingress-gateway报:`NC cluster_not_found` outbound|80|v1|nginx.default.svc.cluster.local
原因
在特定命名空间中设置 DestinationRule
的可见性并不能保证会使用该规则。将 DestinationRule
导出到其他命名空间可以使您在其它命名空间中使用它,但是要在请求时真正应用该 DestinationRule
,命名空间也必须位于 DestinationRule
查找路径上:
- 客户端命名空间
- 服务命名空间
- Istio 根配置命名空间(默认是
istio-system
)
例如,以下 YAML 文件用于为 ns1 命名空间中的 myservice 服务定义目标规则。该host
字段表示 myservice 服务是在 default 命名空间中定义的。
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:name: myservice
spec:host: myservice.default.svc.cluster.localtrafficPolicy:connectionPool:tcp:maxConnections: 100
- 如果使用驻留在 ns1 命名空间中的客户端调用 myservice 服务,则调用成功,因为
Istio 在 ns1 命名空间中找到 myservice 服务的目标规则
,并使用目标规则路由调用请求 - 如果使用驻留在 ns2 命名空间中的客户端调用 myservice 服务,调用将失败。Istio 根据以下过程搜索目标规则
- 用于调用 myservice 服务的客户端驻留在 ns2 名称空间中。Istio在 ns2 命名空间中搜索目标规则。但是,找不到目标规则,因为它不存在于 ns2 命名空间中
- 要调用的 myservice 服务驻留在 default 命名空间中。Istio在默认命名空间中搜索目标规则。但是,找不到目标规则,因为它不存在于默认命名空间中
- Istio的根命名空间固定为 istio-system。Istio 在 istio-system 命名空间中搜索目标规则。但是,找不到目标规则,因为它不存在于 istio-system 命名空间中。
- 即使将
myservice
服务导出到所有命名空间,并因此在ns2
中可见,并且DestinationRule
也导出到包括ns2
在内的所有命名空间。来自ns2
的请求依然不会应用该规则,因为它不在查找路径上的任何命名空间中
您可以通过在与相应服务相同的命名空间(在此示例中为 default
)中创建 DestinationRule
来避免此问题。然后,它将应用于任何命名空间中的客户端请求。您也可以将 DestinationRule
移至 istio-system
命名空间,即查找路径上的第三个命名空间,尽管不建议这样做,除非 DestinationRule
是适用于所有命名空间的全局配置,并且这需要管理员权限。
Istio 使用这种受限制的 DestinationRule
查找路径有两个原因:
- 防止定义覆盖完全不相关的命名空间中的服务行为的
DestinationRule
。 - 当同一host有多个
DestinationRule
时,可以有一个清晰的查找顺序。
解决方案
为服务定义目标规则时,请在以下命名空间之一中定义目标规则:
- Istio的根命名空间
- 服务所在的命名空间
- 调用服务的客户端所在的命名空间
Istio-system部署DR
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:name: nginxnamespace: istio
spec:hosts:- "*"exportTo:- "*"gateways:- bookinfo-gatewayhttp:- match:route:- destination:host: nginx.default.svc.cluster.localport:number: 80subset: v1
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:name: nginxnamespace: istio-system # 将命名空间修改为istio所在命名空间
spec:host: nginx.default.svc.cluster.localexportTo:- "*"subsets:- name: v1labels:app: nginx# 可以访问了
╰─ curl http://192.168.0.15 -I
HTTP/1.1 200 OK
server: istio-envoy
date: Sat, 08 Apr 2023 16:07:52 GMT
content-type: text/html
content-length: 615
last-modified: Tue, 28 Dec 2021 15:28:38 GMT
etag: "61cb2d26-267"
accept-ranges: bytes
x-envoy-upstream-service-time: 1
被调用方命名空间部署DR
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:name: nginxnamespace: istio
spec:hosts:- "*"exportTo:- "*"gateways:- bookinfo-gatewayhttp:- match:route:- destination:host: nginx.default.svc.cluster.localport:number: 80subset: v1
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:name: nginxnamespace: default # 将命名空间设置被调用方的命名空间
spec:host: nginx.default.svc.cluster.localexportTo:- "*"subsets:- name: v1labels:app: nginx# 访问测试,能正常访问
╰─ curl http://192.168.0.15 -I
HTTP/1.1 200 OK
server: istio-envoy
date: Sat, 08 Apr 2023 16:14:05 GMT
content-type: text/html
content-length: 615
last-modified: Tue, 28 Dec 2021 15:28:38 GMT
etag: "61cb2d26-267"
accept-ranges: bytes
x-envoy-upstream-service-time: 0
调用方命名空间
- 适用于东西流量,
下面monitor夸命名空间去访问nginx,还是访问到二个版本流量,default命名空间访问正常,原因未知
# 未将ds设置到monitor命名空间之前访问nginx,vs/dr如下(不配置gateway,将其设置mesh,仅在网格内部生效)
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:name: nginxnamespace: default
spec:exportTo:- "."hosts: # 由于跨了命名空间,所以fqdn- nginx-version-all.default.svc.cluster.localgateways:- meshhttp:- match:route:- destination:host: nginx-version-all.default.svc.cluster.localport:number: 80subset: v1weight: 100
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:name: nginxnamespace: default
spec:host: nginx-version-all.default.svc.cluster.localexportTo:- "*"subsets:- name: v1labels:app: nginxversion: v1