【问题标题】:Istio mTLS working just between some services even though tls-check prints STATUS OK for everyoneIstio mTLS 仅在某些服务之间工作,即使 tls-check 为所有人打印 STATUS OK
【发布时间】:2020-01-03 01:54:17
【问题描述】:

我正在尝试在我已经使用 istio 的 sidecar 的网格中启用 mTLS。 我遇到的问题是我只能获得一个工作连接,然后连接失败。

这就是在我失败的 mTLS 实现(简化)的情况下现在设置服务的方式:

Istio IngressGateway -> NGINX pod -> API 网关 -> 服务 A -> [ 数据库 ] -> 服务 B

首先要注意的是,我使用 NGINX pod 作为负载均衡器来代理_将我的请求传递到我的 API 网关或我的前端页面。我尝试在没有 istio IngressGateway 的情况下保持它,但我无法让它工作。然后我尝试使用 Istio IngressGateway 并使用 VirtualService 直接连接到 API 网关,但对我来说也失败了。所以我暂时就这样离开了,因为这是我的请求成功到达 API 网关的唯一方式。

另外需要注意的是,服务 A 首先连接到网格外的数据库,然后向网格内并启用 mTLS 的服务 B 发出请求。

NGINX、API Gateway、Service A 和 Service B 在启用 mTLS 的网格内,"istioctl authn tls-check" 显示状态正常。

NGINX 和 API Gateway 位于名为 "gateway" 的命名空间中,数据库位于 "auth" 中,服务 A 和服务 B 位于另一个名为 的命名空间中“API”

Istio IngressGateway 目前位于命名空间 "istio-system" 中。

所以问题是,如果我将 STRICT 模式设置为网关命名空间并将 PERMISSIVE 模式设置为 api,那么一切正常,但是一旦我设置了 STRICT到 api,我看到请求进入服务 A,但是它无法将请求发送到服务 B,并返回 500。

这是失败时的输出,我可以在 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

最后,我的 VirtualServices:

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 以及为什么我必须在网关块中使用“网格”。如果我删除此块,我不会在 API Gateway 中收到我的请求,但如果我这样做了,它会工作,我的请求甚至会到达下一个服务(服务 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

【问题讨论】:

    标签: kubernetes istio mtls


    【解决方案1】:

    调试 Istio 服务网格的一般提示:

    1. 检查the requirements for services and pods
    2. 尝试从Istio tasks 列表中执行与您尝试执行的任务类似的任务。查看该任务是否有效,并找出与您的任务的不同之处。
    3. 按照Istio common problems page 上的说明进行操作。

    【讨论】:

    • 它不应该调用自己,ServiceA应该向ServiceB发出请求。顺便说一下是一个Springboot项目
    • 我已经用 ServiceA 的监听器转储更新了我的问题
    • 对不起,您能否也添加集群转储,并为集群和侦听器使用 -o json。
    • 我用 json 格式的集群和监听器更新了我的问题。抱歉,由于达到了限制,我不得不使用外部链接。我可以稍后使用文件的正确部分来修复它,以将其包含在帖子中,而不是作为外部链接。另外,我已尽力更改此问题的服务名称,如果我犯了任何错误,请见谅
    • 好的,我明白了。它与 serviceA 调用 serviceA 有关。也许这是 Springboot 执行的一些调用。让我看看 Istio 如何处理这些调用。从 serviceA 到 serviceB 的调用应该可以工作。能不能在serviceA的容器中运行curl,查看是否调用serviceB成功,调用serviceA失败?
    猜你喜欢
    • 1970-01-01
    • 2019-06-06
    • 2023-03-12
    • 2019-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-21
    • 1970-01-01
    相关资源
    最近更新 更多