Istio mTLS 仅在某些服务之间工作,即使 tls-check 为每个人打印 STATUS OK
Istio mTLS working just between some services even though tls-check prints STATUS OK for everyone
我正在尝试在我已经使用 istio 的 sidecars 的网格中启用 mTLS。
我遇到的问题是我最多只能建立一个工作连接,然后连接失败。
这就是我的 mTLS(简化版)实施失败时的服务设置方式:
Istio IngressGateway -> NGINX pod -> API 网关 -> 服务 A -> [ 数据库] -> 服务 B
首先要注意的是,我使用 NGINX pod 作为负载均衡器 proxy_pass 我对 API 网关或前端页面的请求。我尝试在没有 istio IngressGateway 的情况下保留它,但我无法让它工作。然后我尝试使用 Istio IngressGateway 并使用 VirtualService 直接连接到 API 网关,但对我来说也失败了。所以我现在就这样离开,因为这是我的请求成功到达 API 网关的唯一途径。
另一件需要注意的事情是,服务 A 首先连接到网格外部的数据库,然后向网格内部启用了 mTLS 的服务 B 发出请求。
NGINX,API 网关、服务 A 和服务 B 在启用了 mTLS 的网格内,"istioctl authn tls-check" 显示状态正常。
NGINX 和 API 网关位于名为 "gateway" 的命名空间中,数据库位于 "auth" 并且服务 A 和服务 B 在另一个名为 "api".
中
Istio IngressGateway 现在位于命名空间 "istio-system" 中。
所以问题是,如果我将 STRICT 模式设置为网关名称空间并将 PERMISSIVE 设置为 api,一切正常但是一旦我将 STRICT 设置为 api,我看到请求进入服务 A,但随后它无法通过 500.[=20= 将请求发送到服务 B ]
这是失败时的输出,我可以在 Service A pod 的 istio-proxy 容器中看到:
api/serviceA[istio-proxy]: [2019-09-02T12:59:55.366Z] "- - -" 0 - "-" "-" 1939 0 2 - "-" "-" "-" "-" "10.20.208.248:4567" outbound|4567||database.auth.svc.cluster.local 10.20.128.44:35366 10.20.208.248:4567
10.20.128.44:35364 -
api/serviceA[istio-proxy]: [2019-09-02T12:59:55.326Z] "POST /api/my-call HTTP/1.1" 500 - "-" "-" 74 90 60 24 "10.90.0.22, 127.0.0.1, 127.0.0.1" "PostmanRuntime/7.15.0" "14d93a85-192d-4aa7-aa45-1501a71d4924" "serviceA.api.svc.cluster.local:9090" "127.0.0.1:9090" inbound|9090|http-serviceA|serviceA.api.svc.cluster.local - 10.20.128.44:9090 127.0.0.1:0 outbound_.9090_._.serviceA.api.svc.cluster.local
虽然 ServiceB 中没有消息。
目前,我没有全局 MeshPolicy,我正在为每个命名空间设置 Policy 和 DestinationRule
政策:
apiVersion: "authentication.istio.io/v1alpha1"
kind: "Policy"
metadata:
name: "default"
namespace: gateway
spec:
peers:
- mtls:
mode: STRICT
---
apiVersion: "authentication.istio.io/v1alpha1"
kind: "Policy"
metadata:
name: "default"
namespace: auth
spec:
peers:
- mtls:
mode: STRICT
---
apiVersion: "authentication.istio.io/v1alpha1"
kind: "Policy"
metadata:
name: "default"
namespace: api
spec:
peers:
- mtls:
mode: STRICT
目的地规则:
apiVersion: "networking.istio.io/v1alpha3"
kind: "DestinationRule"
metadata:
name: "mutual-gateway"
namespace: "gateway"
spec:
host: "*.gateway.svc.cluster.local"
trafficPolicy:
tls:
mode: ISTIO_MUTUAL
---
apiVersion: "networking.istio.io/v1alpha3"
kind: "DestinationRule"
metadata:
name: "mutual-api"
namespace: "api"
spec:
host: "*.api.svc.cluster.local"
trafficPolicy:
tls:
mode: ISTIO_MUTUAL
---
apiVersion: "networking.istio.io/v1alpha3"
kind: "DestinationRule"
metadata:
name: "mutual-auth"
namespace: "auth"
spec:
host: "*.auth.svc.cluster.local"
trafficPolicy:
tls:
mode: ISTIO_MUTUAL
然后我有一些 DestinationRule 来禁用数据库的 mTLS(我在同一个命名空间中有一些其他服务,我想使用 mTLS 启用)和 Kubernetes API
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: "myDatabase"
namespace: "auth"
spec:
host: "database.auth.svc.cluster.local"
trafficPolicy:
tls:
mode: DISABLE
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: "k8s-api-server"
namespace: default
spec:
host: "kubernetes.default.svc.cluster.local"
trafficPolicy:
tls:
mode: DISABLE
然后我的 IngressGateway 是这样的:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: ingress-gateway
namespace: istio-system
spec:
selector:
istio: ingressgateway # use istio default ingress gateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- my-api.example.com
tls:
httpsRedirect: true # sends 301 redirect for http requests
- port:
number: 443
name: https
protocol: HTTPS
tls:
mode: SIMPLE
serverCertificate: /etc/istio/ingressgateway-certs/tls.crt
privateKey: /etc/istio/ingressgateway-certs/tls.key
hosts:
- my-api.example.com
最后,我的虚拟服务:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ingress-nginx
namespace: gateway
spec:
hosts:
- my-api.example.com
gateways:
- ingress-gateway.istio-system
http:
- match:
- uri:
prefix: /
route:
- destination:
port:
number: 80
host: ingress.gateway.svc.cluster.local # this is NGINX pod
corsPolicy:
allowOrigin:
- my-api.example.com
allowMethods:
- POST
- GET
- DELETE
- PATCH
- OPTIONS
allowCredentials: true
allowHeaders:
- "*"
maxAge: "24h"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: api-gateway
namespace: gateway
spec:
hosts:
- my-api.example.com
- api-gateway.gateway.svc.cluster.local
gateways:
- mesh
http:
- match:
- uri:
prefix: /
route:
- destination:
port:
number: 80
host: api-gateway.gateway.svc.cluster.local
corsPolicy:
allowOrigin:
- my-api.example.com
allowMethods:
- POST
- GET
- DELETE
- PATCH
- OPTIONS
allowCredentials: true
allowHeaders:
- "*"
maxAge: "24h"
我不明白的一件事是为什么我必须为我的 API 网关创建一个 VirtualService 以及为什么我必须在网关块中使用 "mesh"。如果我删除此块,我不会在 API 网关中收到我的请求,但如果我这样做,它会工作并且我的请求甚至会到达下一个服务(服务 A),但不会到达下一个服务。
感谢您的帮助。我真的被这个困住了。
ServiceA 的侦听器转储:
ADDRESS PORT TYPE
10.20.128.44 9090 HTTP
10.20.253.21 443 TCP
10.20.255.77 80 TCP
10.20.240.26 443 TCP
0.0.0.0 7199 TCP
10.20.213.65 15011 TCP
0.0.0.0 7000 TCP
10.20.192.1 443 TCP
0.0.0.0 4568 TCP
0.0.0.0 4444 TCP
10.20.255.245 3306 TCP
0.0.0.0 7001 TCP
0.0.0.0 9160 TCP
10.20.218.226 443 TCP
10.20.239.14 42422 TCP
10.20.192.10 53 TCP
0.0.0.0 4567 TCP
10.20.225.206 443 TCP
10.20.225.166 443 TCP
10.20.207.244 5473 TCP
10.20.202.47 44134 TCP
10.20.227.251 3306 TCP
0.0.0.0 9042 TCP
10.20.207.141 3306 TCP
0.0.0.0 15014 TCP
0.0.0.0 9090 TCP
0.0.0.0 9091 TCP
0.0.0.0 9901 TCP
0.0.0.0 15010 TCP
0.0.0.0 15004 TCP
0.0.0.0 8060 TCP
0.0.0.0 8080 TCP
0.0.0.0 20001 TCP
0.0.0.0 80 TCP
0.0.0.0 10589 TCP
10.20.128.44 15020 TCP
0.0.0.0 15001 TCP
0.0.0.0 9000 TCP
10.20.219.237 9090 TCP
10.20.233.60 80 TCP
10.20.200.156 9100 TCP
10.20.204.239 9093 TCP
0.0.0.0 10055 TCP
0.0.0.0 10054 TCP
0.0.0.0 10251 TCP
0.0.0.0 10252 TCP
0.0.0.0 9093 TCP
0.0.0.0 6783 TCP
0.0.0.0 10250 TCP
10.20.217.136 443 TCP
0.0.0.0 15090 HTTP
以json格式转储簇: https://pastebin.com/73zmAPWg
以 json 格式转储监听器: https://pastebin.com/Pk7ddPJ2
从 serviceA 容器到 serviceB 的 curl 命令:
/opt/app # curl -X POST -v "http://serviceB.api.svc.cluster.local:4567/session/xxxxxxxx=?parameters=hi"
* Trying 10.20.228.217...
* TCP_NODELAY set
* Connected to serviceB.api.svc.cluster.local (10.20.228.217) port 4567 (#0)
> POST /session/xxxxxxxx=?parameters=hi HTTP/1.1
> Host: serviceB.api.svc.cluster.local:4567
> User-Agent: curl/7.61.1
> Accept: */*
>
* Empty reply from server
* Connection #0 to host serviceB.api.svc.cluster.local left intact
curl: (52) Empty reply from server
如果我禁用 mTLS,请求将通过 Curl 从 serviceA 发送到 serviceB
调试 Istio 服务网格的一般技巧:
- 检查the requirements for services and pods。
- 尝试执行与 Istio tasks 列表中您要执行的任务类似的任务。查看该任务是否有效并找出与您的任务的不同之处。
- 按照 Istio common problems page 上的说明进行操作。
我正在尝试在我已经使用 istio 的 sidecars 的网格中启用 mTLS。 我遇到的问题是我最多只能建立一个工作连接,然后连接失败。
这就是我的 mTLS(简化版)实施失败时的服务设置方式:
Istio IngressGateway -> NGINX pod -> API 网关 -> 服务 A -> [ 数据库] -> 服务 B
首先要注意的是,我使用 NGINX pod 作为负载均衡器 proxy_pass 我对 API 网关或前端页面的请求。我尝试在没有 istio IngressGateway 的情况下保留它,但我无法让它工作。然后我尝试使用 Istio IngressGateway 并使用 VirtualService 直接连接到 API 网关,但对我来说也失败了。所以我现在就这样离开,因为这是我的请求成功到达 API 网关的唯一途径。
另一件需要注意的事情是,服务 A 首先连接到网格外部的数据库,然后向网格内部启用了 mTLS 的服务 B 发出请求。
NGINX,API 网关、服务 A 和服务 B 在启用了 mTLS 的网格内,"istioctl authn tls-check" 显示状态正常。
NGINX 和 API 网关位于名为 "gateway" 的命名空间中,数据库位于 "auth" 并且服务 A 和服务 B 在另一个名为 "api".
中Istio IngressGateway 现在位于命名空间 "istio-system" 中。
所以问题是,如果我将 STRICT 模式设置为网关名称空间并将 PERMISSIVE 设置为 api,一切正常但是一旦我将 STRICT 设置为 api,我看到请求进入服务 A,但随后它无法通过 500.[=20= 将请求发送到服务 B ]
这是失败时的输出,我可以在 Service A pod 的 istio-proxy 容器中看到:
api/serviceA[istio-proxy]: [2019-09-02T12:59:55.366Z] "- - -" 0 - "-" "-" 1939 0 2 - "-" "-" "-" "-" "10.20.208.248:4567" outbound|4567||database.auth.svc.cluster.local 10.20.128.44:35366 10.20.208.248:4567
10.20.128.44:35364 -
api/serviceA[istio-proxy]: [2019-09-02T12:59:55.326Z] "POST /api/my-call HTTP/1.1" 500 - "-" "-" 74 90 60 24 "10.90.0.22, 127.0.0.1, 127.0.0.1" "PostmanRuntime/7.15.0" "14d93a85-192d-4aa7-aa45-1501a71d4924" "serviceA.api.svc.cluster.local:9090" "127.0.0.1:9090" inbound|9090|http-serviceA|serviceA.api.svc.cluster.local - 10.20.128.44:9090 127.0.0.1:0 outbound_.9090_._.serviceA.api.svc.cluster.local
虽然 ServiceB 中没有消息。
目前,我没有全局 MeshPolicy,我正在为每个命名空间设置 Policy 和 DestinationRule
政策:
apiVersion: "authentication.istio.io/v1alpha1"
kind: "Policy"
metadata:
name: "default"
namespace: gateway
spec:
peers:
- mtls:
mode: STRICT
---
apiVersion: "authentication.istio.io/v1alpha1"
kind: "Policy"
metadata:
name: "default"
namespace: auth
spec:
peers:
- mtls:
mode: STRICT
---
apiVersion: "authentication.istio.io/v1alpha1"
kind: "Policy"
metadata:
name: "default"
namespace: api
spec:
peers:
- mtls:
mode: STRICT
目的地规则:
apiVersion: "networking.istio.io/v1alpha3"
kind: "DestinationRule"
metadata:
name: "mutual-gateway"
namespace: "gateway"
spec:
host: "*.gateway.svc.cluster.local"
trafficPolicy:
tls:
mode: ISTIO_MUTUAL
---
apiVersion: "networking.istio.io/v1alpha3"
kind: "DestinationRule"
metadata:
name: "mutual-api"
namespace: "api"
spec:
host: "*.api.svc.cluster.local"
trafficPolicy:
tls:
mode: ISTIO_MUTUAL
---
apiVersion: "networking.istio.io/v1alpha3"
kind: "DestinationRule"
metadata:
name: "mutual-auth"
namespace: "auth"
spec:
host: "*.auth.svc.cluster.local"
trafficPolicy:
tls:
mode: ISTIO_MUTUAL
然后我有一些 DestinationRule 来禁用数据库的 mTLS(我在同一个命名空间中有一些其他服务,我想使用 mTLS 启用)和 Kubernetes API
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: "myDatabase"
namespace: "auth"
spec:
host: "database.auth.svc.cluster.local"
trafficPolicy:
tls:
mode: DISABLE
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: "k8s-api-server"
namespace: default
spec:
host: "kubernetes.default.svc.cluster.local"
trafficPolicy:
tls:
mode: DISABLE
然后我的 IngressGateway 是这样的:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: ingress-gateway
namespace: istio-system
spec:
selector:
istio: ingressgateway # use istio default ingress gateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- my-api.example.com
tls:
httpsRedirect: true # sends 301 redirect for http requests
- port:
number: 443
name: https
protocol: HTTPS
tls:
mode: SIMPLE
serverCertificate: /etc/istio/ingressgateway-certs/tls.crt
privateKey: /etc/istio/ingressgateway-certs/tls.key
hosts:
- my-api.example.com
最后,我的虚拟服务:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ingress-nginx
namespace: gateway
spec:
hosts:
- my-api.example.com
gateways:
- ingress-gateway.istio-system
http:
- match:
- uri:
prefix: /
route:
- destination:
port:
number: 80
host: ingress.gateway.svc.cluster.local # this is NGINX pod
corsPolicy:
allowOrigin:
- my-api.example.com
allowMethods:
- POST
- GET
- DELETE
- PATCH
- OPTIONS
allowCredentials: true
allowHeaders:
- "*"
maxAge: "24h"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: api-gateway
namespace: gateway
spec:
hosts:
- my-api.example.com
- api-gateway.gateway.svc.cluster.local
gateways:
- mesh
http:
- match:
- uri:
prefix: /
route:
- destination:
port:
number: 80
host: api-gateway.gateway.svc.cluster.local
corsPolicy:
allowOrigin:
- my-api.example.com
allowMethods:
- POST
- GET
- DELETE
- PATCH
- OPTIONS
allowCredentials: true
allowHeaders:
- "*"
maxAge: "24h"
我不明白的一件事是为什么我必须为我的 API 网关创建一个 VirtualService 以及为什么我必须在网关块中使用 "mesh"。如果我删除此块,我不会在 API 网关中收到我的请求,但如果我这样做,它会工作并且我的请求甚至会到达下一个服务(服务 A),但不会到达下一个服务。
感谢您的帮助。我真的被这个困住了。
ServiceA 的侦听器转储:
ADDRESS PORT TYPE
10.20.128.44 9090 HTTP
10.20.253.21 443 TCP
10.20.255.77 80 TCP
10.20.240.26 443 TCP
0.0.0.0 7199 TCP
10.20.213.65 15011 TCP
0.0.0.0 7000 TCP
10.20.192.1 443 TCP
0.0.0.0 4568 TCP
0.0.0.0 4444 TCP
10.20.255.245 3306 TCP
0.0.0.0 7001 TCP
0.0.0.0 9160 TCP
10.20.218.226 443 TCP
10.20.239.14 42422 TCP
10.20.192.10 53 TCP
0.0.0.0 4567 TCP
10.20.225.206 443 TCP
10.20.225.166 443 TCP
10.20.207.244 5473 TCP
10.20.202.47 44134 TCP
10.20.227.251 3306 TCP
0.0.0.0 9042 TCP
10.20.207.141 3306 TCP
0.0.0.0 15014 TCP
0.0.0.0 9090 TCP
0.0.0.0 9091 TCP
0.0.0.0 9901 TCP
0.0.0.0 15010 TCP
0.0.0.0 15004 TCP
0.0.0.0 8060 TCP
0.0.0.0 8080 TCP
0.0.0.0 20001 TCP
0.0.0.0 80 TCP
0.0.0.0 10589 TCP
10.20.128.44 15020 TCP
0.0.0.0 15001 TCP
0.0.0.0 9000 TCP
10.20.219.237 9090 TCP
10.20.233.60 80 TCP
10.20.200.156 9100 TCP
10.20.204.239 9093 TCP
0.0.0.0 10055 TCP
0.0.0.0 10054 TCP
0.0.0.0 10251 TCP
0.0.0.0 10252 TCP
0.0.0.0 9093 TCP
0.0.0.0 6783 TCP
0.0.0.0 10250 TCP
10.20.217.136 443 TCP
0.0.0.0 15090 HTTP
以json格式转储簇: https://pastebin.com/73zmAPWg
以 json 格式转储监听器: https://pastebin.com/Pk7ddPJ2
从 serviceA 容器到 serviceB 的 curl 命令:
/opt/app # curl -X POST -v "http://serviceB.api.svc.cluster.local:4567/session/xxxxxxxx=?parameters=hi"
* Trying 10.20.228.217...
* TCP_NODELAY set
* Connected to serviceB.api.svc.cluster.local (10.20.228.217) port 4567 (#0)
> POST /session/xxxxxxxx=?parameters=hi HTTP/1.1
> Host: serviceB.api.svc.cluster.local:4567
> User-Agent: curl/7.61.1
> Accept: */*
>
* Empty reply from server
* Connection #0 to host serviceB.api.svc.cluster.local left intact
curl: (52) Empty reply from server
如果我禁用 mTLS,请求将通过 Curl 从 serviceA 发送到 serviceB
调试 Istio 服务网格的一般技巧:
- 检查the requirements for services and pods。
- 尝试执行与 Istio tasks 列表中您要执行的任务类似的任务。查看该任务是否有效并找出与您的任务的不同之处。
- 按照 Istio common problems page 上的说明进行操作。