启用 Istio 的 GKE 集群无法与 Google 服务基础架构 API 进行可靠通信

Istio enabled GKE cluster not reliably communicating with Google Service Infrastructure APIs

我一直无法可靠地允许启用了 istio 的 Google Kubernetes Engine 集群通过 extensible service proxy 连接到 Google Cloud Endpoints(服务管理 API)。当我部署我的 Pods 时,代理总是无法启动导致 Pod 重新启动,并输出以下错误:

INFO:Fetching an access token from the metadata service
WARNING:Retrying (Retry(total=0, connect=None, read=None, redirect=0, status=None)) after connection broken by 'NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7fea4abece90>: Failed to establish a new connection: [Errno 111] Connection refused',)': /computeMetadata/v1/instance/service-accounts/default/token
ERROR:Failed fetching metadata attribute: http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token

但是在重新启动后,代理报告一切正常,它能够获取访问令牌并且我能够成功向 Pod 发出请求:

INFO:Fetching an access token from the metadata service
INFO:Fetching the service config ID from the rollouts service
INFO:Fetching the service configuration from the service management service
INFO:Attribute zone: europe-west2-a
INFO:Attribute project_id: my-project
INFO:Attribute kube_env: KUBE_ENV
nginx: [warn] Using trusted CA certificates file: /etc/nginx/trusted-ca-certificates.crt
10.154.0.5 - - [23/May/2020:21:19:36 +0000] "GET /domains HTTP/1.1" 200 221 "-" "curl/7.58.0"

大约一个小时后,大概是因为访问令牌已过期,代理日志表明它再次无法获取访问令牌,我无法再向我的 Pod 发出请求。

2020/05/23 22:14:04 [error] 9#9: upstream timed out (110: Connection timed out)
2020/05/23 22:14:04[error]9#9: Failed to fetch service account token
2020/05/23 22:14:04[error]9#9: Fetch access token unexpected status: INTERNAL: Failed to fetch service account token

我有一个 ServiceEntry 资源,它应该允许代理向 GKE 节点上的元数据服务器发出请求:

apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: google-metadata-server
spec:
  hosts:
  - metadata.google.internal # GCE metadata server
  addresses:
  - 169.254.169.254 # GCE metadata server
  location: MESH_EXTERNAL
  ports:
  - name: http
    number: 80
    protocol: HTTP
  - name: https
    number: 443
    protocol: HTTPS

我已通过 exec 进入其中一个容器并 运行:

确认这是有效的
curl -H "Metadata-Flavor: Google" http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token

如何防止这种行为并可靠地让代理与 Google 服务基础设施 API 通信?

虽然我不完全相信这是解决方案,但似乎使用专用服务帐户在可扩展服务代理容器内生成访问令牌可以防止上述行为发生,而且我能够可靠地向代理和上游服务,甚至在一个小时后。

我使用的服务帐户具有以下角色:

  • roles/cloudtrace.agent
  • roles/servicemanagement.serviceController

假设这是一个稳定的问题解决方案,我对此结果更满意,因为我不是 100% 满意地使用元数据服务器,因为它依赖于与 GKE 节点关联的服务帐户。此服务帐户通常比 ESP 完成其工作所需的功能更强大。

不过,我将继续监视此情况,以防上游代理再次无法访问。