前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >记一次 Istio 云数据库连接失败的错误排查过程

记一次 Istio 云数据库连接失败的错误排查过程

原创
作者头像
谢正伟
修改2020-08-14 15:14:31
3.1K1
修改2020-08-14 15:14:31
举报
文章被收录于专栏:云原生研究

写这篇文章的目的主要是记录 在 容器/istio 下如何使用一些手段和工具来排查错误。

0 错误显现

首先先看下错误描述:

代码语言:txt
复制
2020-08-14 10:37:20.774  ERROR 1 --- [Create-24097622] com.alibaba.druid.pool.DruidDataSource   : create connection SQLException, url: jdbc:postgresql://......, errorCode 0, state 08001

org.postgresql.util.PSQLException: The connection attempt failed.
	at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:292)
	at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:49)
	at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:195)
	at org.postgresql.Driver.makeConnection(Driver.java:458)
	at org.postgresql.Driver.connect(Driver.java:260)
	at com.alibaba.druid.pool.DruidAbstractDataSource.createPhysicalConnection(DruidAbstractDataSource.java:1596)
	at com.alibaba.druid.pool.DruidAbstractDataSource.createPhysicalConnection(DruidAbstractDataSource.java:1662)
	at com.alibaba.druid.pool.DruidDataSource$CreateConnectionThread.run(DruidDataSource.java:2697)
Caused by: java.net.SocketTimeoutException: connect timed out
	at java.net.PlainSocketImpl.socketConnect(Native Method)
	at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
	at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
	at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
	at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
	at java.net.Socket.connect(Socket.java:589)
	at org.postgresql.core.PGStream.<init>(PGStream.java:75)
	at org.postgresql.core.v3.ConnectionFactoryImpl.tryConnect(ConnectionFactoryImpl.java:91)
	at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:192)
	... 7 common frames omitted

从错误中看到,是 postgres 连不上, 08001 表示 “SQLCLIENT UNABLE TO ESTABLISH SQLCONNECTION”,下面亦显示连接超时。但这个错误并不是每次都出现,有时候会正常工作,但绝大多数会出错。而且应用在虚拟机里运行正常,在 Istio 中会出错。

postgres 使用的是同 VPC 下的云数据库,在 TKE 环境下,网络默认是通的。

什么原因?Sidecar 有问题?Java 程序有问题?网络问题?

1、将 postgres 流量绕开 Sidecar

首先想到,如果是 envoy 阻止了外部的 postgres,可能会出现此情况。检查 egress 流量模式,已经是“Allow Any”。

干脆将连接 postgres 的流量完全绕开 envoy 试试,只需要将端口 5432 排除:

代码语言:txt
复制
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-dubbo-consumer
  namespace: xyz
  labels:
    app: hello-dubbo-consumer
    version: v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: hello-dubbo-consumer
      version: v1
  template:
    metadata:
      annotations:
        traffic.sidecar.istio.io/excludeOutboundPorts: "5432"
      labels:
        app: hello-dubbo-consumer
        version: v1
    spec:
      containers:
        - name: hello-dubbo-consumer
          image: tencent-cloud-one-docker.pkg.coding.net/xyz-demo/images/hello-dubbo-consumer:1.0.0
          command: ["java","-jar","hello-dubbo-consumer-fat.jar"]

增加注解:traffic.sidecar.istio.io/excludeOutboundPorts: "5432",这个可以让 5432 端口的流量直接绕过 envoy 发送。

测试无果,问题依然存在,初步排除是 sidecar 的问题。

2、部署 psql 客户端参与测试

为了验证连接问题,需要在集群内增加一个 psql 的客户参与验证,这样可以快速连接数据库,看是否存在问题。

很自然的,直接拿一个官方 Docker 镜像即可,官方镜像里已经内置服务端和客户端,我们只要将这个镜像运行在集群内即可。

代码语言:txt
复制
apiVersion: apps/v1
kind: Deployment
metadata:
  name: psql-client
  namespace: xyz
spec:
  replicas: 1
  selector:
    matchLabels:
      app: psql-client
  template:
    metadata:
      labels:
        app: psql-client
    spec:
      containers:
      - image: postgres
        imagePullPolicy: IfNotPresent
        name: psql-client
        command: ["tail", "-f", "/dev/null"]

修改了 容器的启动参数为 “tail -f /dev/null” 避免直接退出,将这个容器置入了集群,现在可以进去执行psql命令了。

代码语言:txt
复制
# 进入 psql-client 容器
kubectl exec -it <containerid> -n xyz -c psql-client sh

# 进入之后使用 psql 连接远程数据库
psql -h <postgres-ip> -U username -d postgres

“很不幸”,使用 psql 成功联入了远程数据库。有点懵。

3、网络问题

为什么同一个集群,使用 psql 客户端可以连上,Java 应用却经常连不上。有没有可能有的 node 和 数据库的网络是通的,有的却不通呢。

随机选取了一个 和 psql-client 同机的 应用 pod 进入交互,直接探查远程 5432 端口。

代码语言:txt
复制
nc -zv <postgres-ip> 5432

结果,是 open 的。试验了这个 node 的其他pod。结果亦然。都是通的。

测试有问题的 Java 应用所在的 node 的其他 pod,发现真的是网络不通。

继续测试了集群的其他 node。结果只有 2 个 node 的上的 pod 和 远程数据库是联通的。

进一步排查,发现:集群内的主机是属于两个不同的安全组,安全组的设置是不一样的。

所以,在部署应用的时候,当应用恰好部署在正确安全组的主机上,应用就是正常。

终于真相大白。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 0 错误显现
  • 1、将 postgres 流量绕开 Sidecar
  • 2、部署 psql 客户端参与测试
  • 3、网络问题
相关产品与服务
私有网络
私有网络(Virtual Private Cloud,VPC)是基于腾讯云构建的专属云上网络空间,为您在腾讯云上的资源提供网络服务,不同私有网络间完全逻辑隔离。作为您在云上的专属网络空间,您可以通过软件定义网络的方式管理您的私有网络 VPC,实现 IP 地址、子网、路由表、网络 ACL 、流日志等功能的配置管理。私有网络还支持多种方式连接 Internet,如弹性 IP 、NAT 网关等。同时,您也可以通过 VPN 连接或专线接入连通腾讯云与您本地的数据中心,灵活构建混合云。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档