热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

MySQL在KubernetesIPVS模式下引发的TCP超时问题

以下数据库上Kubernetes都是研发、测试环境,非生产环境我们研测测试环境的数据库如 Mysql ,redis ,rabbitmq都以容器的方式在我们自研的paas平台上创

以下数据库上Kubernetes都是研发、测试环境,非生产环境

我们研测测试环境的数据库如 Mysql ,redis ,rabbitmq都以容器的方式在我们自研的paas平台上创建;

但是当我们把mysql移到k8s上时, 我们经常发现MYSQL 的error日志爆出如下错误:

然后我们的客户端则会经常报 Lost Mysql Connection错误
, 重试后,连接恢复:

对于该问题,我们首先思路是排查我们代码上是否存在未正常关闭连接, 同时,我们也部署了另一套非容器的 mysql 环境,相同代码下,非容器mysql的表现的非常正常,没有一条Aborted记录,因此我们怀疑一定中间某个网络环节导致了该问题。

Percona
社区写了一篇比较好的文章,这篇文章有必要阅读下,因为这种错误原因是不确定的。

地址是 https://www.percona.com/blog/2016/05/16/mysql-got-an-error-reading-communication-packet-errors/

但是并没有给出这类问题的根本原因,或者说导致该错误的原因其实可能有多种。

由于是基本确立问题范围出现在 docker网络,所以我们必须要深入了解下 kubernetes 1.11上的 IPVS
模式原理。

Kubernetes ipvs 基于 LVS-NAT模型,基本流程如下图:

  • 当用户请求到达Director Server,此时请求的数据报文会先到达内核的PREROUTING链,此时报文的源IP是CIP,目标IP是VIP(K8S 每个node都会有该VIP子接口,名为kube-ipvs0,为虚拟接口)。

在Kubernetes里,这里的VIP
就是 ClusterIP
, 熟悉kubernetes的原理可知该VIP是kubernetes Service,本身就是个负载均衡地址,且各个节点都会监听 VIP的连接, 当用户请求到达DS
, 这一过程在k8s上体现为流量打到 Service
VIP
上, DS是谁呢?每一台K8S node
都是 DS
. 这要看我们是谁去访问SVC, 在我们的case中, Mysql SVC
vip为10.101.219.112
; 访问 Mysql SVC
的是我们的后端 Pod
, 我们的 Client Pod 的 PodIP 为 192.100.183.187
; 我的 RS
POD IP为 192.100.111.84

  • PREROUTING链检查发现数据包的目标IP是本机,将数据包送至INPUT链。

iptables命令是查不到的INPUT这个规则的,因为是ipvs的缘故, 使用 ipvsadm -ln
可以查看到如下规则:

  • POSTROUTING链通过选路,将数据包发送到Real Server(这个我们不好看到,因为内核态或者有没有好的办法可以告知我。)
  • Real Server比对发现目标IP是自己的IP,开始建立响应报文发回给Director Server,此时报文的源IP是RIP,目标IP是CIP. 我们这里CIP就是 192.100.183.187
  • Director Server在响应客户端之前,此时会将源IP地址修改为自己的IP地址,然后响应给客户端,做SNAT转换。此时报文的源IP是VIP (10.101.219.112
    )。目标IP是CIP。

至此 IPVS原理结束。

回到问题, 我们的问题其实遇到比较长时间了,大概一个背景就是,连续使用问题不大,不会报错,但是搁置一段时间后去访问, 就会出现一些异常(我们web上体现到一些查询查不到数据), 所以我们怀疑网络拓扑中存在着连接超时的问题,究竟哪一块有超时呢?我决定抓包。

在哪抓, 我们客户端是我们一个后端,当它启动时,如果有查询任务,肯定是向mysql 发起请求连接的, 所以我们查到该 Client所在 Node上,宿主机上执行tcpdump;

我们的是calico网络, 需要抓 tunl0
网卡流量;

命令如下(幸好第一份工作做网络的。。。。):

tcpdump -i tunl0 host 192.100.111.84 -s0 -w client-mysql.pcap

注意不用指定src dst,那样只能抓到单向报文。。

同时我们的 client发起一个mysql查询请求, 并另开一个shell 在该node执行 ipvsadm -lnc

结果如下:

这个图。。。。

第二列 ,很可疑。。。expired date。。。。。超时。。。,先不管,证明我们的猜想。。继续往下走,不断执行该命令, 第二列在减少,看起来默认是15min,那么这15min我client不再做任何查询,等等吧。。。。

waiting。。。

还有5分钟, 好紧张

我们想抓到到15min那时候, 会发生什么, 然后client再去查询,会不会触发 mysql的错误以及client的错误(文初的错误)

时间到:

我凑, 看起来该链接被清掉了,这时候我们去执行一条查询看看;

我们再看看抓包情况:(我是在POD所在节点宿主上抓的跟数据库交互的报文,然后没有抓到连接被RST的报文略疑惑,lvs清空连接对连接本身究竟做了什么操作仍需要关注。。)

在此之后,查询时候又会新键连接, 即没有任何征兆该链接就被断开了,按理说client使用 mysql connection pool 连接复用是不会轻易就更换连接的。

基本确定了问题, 看起来是 ipvs 维护 VIP的这条链接存在15min左右的超时阈值设定,这个值是否跟系统默认的tcp_keepalive_timeout
有协同影响?那么系统的默认tcp超时时间是多少呢?

确立这个思路,查阅资料(基于15min ipvs为关键词):

  • https://github.com/moby/moby/issues/31208
  • https://success.docker.com/article/ipvs-connection-timeout-issue
  • https://access.redhat.com/solutions/23874

基于上述资料,基本可以分析到, ipvs维护链接有个超时时间,默认为900s为15分钟;然后操作系统默认的tcp_keepalive_timeout 默认为7200s,当一个空闲 tcp连接达到900s时,首先他被ipvs断了,但是操作系统认为该链接还没有到保活超时,所以客户端还会使用之前的连接去发送查询请求,但是ipvs已经不维护该链接了,所以 Lost Connection。。所以只要减小系统的tcp_keepalive_timeout时间,比如到600,后发送一个心跳包,让tcp保活, 这样, ipvs的连接超时也会被重置计数为15min。

我紧急基于上述资料做了k8s node全量修改配置:

playbook如下:

k8s.conf
如下:

关于这三个参数解释下:

当启用与内核参数或守护程序端配置或客户端配置相关的选项时,它将根据这些选项终止tcp会话。例如,当您将以上述内核参数选项视为示例时,首先将在600秒后开始发送keepalive数据包,之后每隔30秒发送一次下一个数据包10次。当客户端或服务器在这段时间内根本没有应答时,tcp会话将被视为已损坏,并将终止。

  • 为什么我们要设置为600s呢, 其实只要比 ipvs的默认值900小即可!

经修复后, 断链问题基本解决, 数据库的 error communication packget
报文基本不再复现, 多么痛的领悟。。

抓到如下报文(修改后ip等数值与上文不一样,发生了变化):

  • (可以清楚看到13:33 到 13:43 期间连接无数据,但是10分钟到了,里面有一个KeepAlive报文,修改之前linux 这个值默认是7200s也就是2小时!)

我们可以在 https://access.redhat.com/solutions/23874
看到一些解释

  • 该client的数据库连接池的连接被保活而不是被ipvs clear掉。

原文链接:https://berlinsaint.github.io/blog/2018/11/01/Mysql_On_Kubernetes%E5%BC%95%E5%8F%91%E7%9A%84TCP%E8%B6%85%E6%97%B6%E9%97%AE%E9%A2%98%E5%AE%9A%E4%BD%8D/



推荐阅读
  • 基于PgpoolII的PostgreSQL集群安装与配置教程
    本文介绍了基于PgpoolII的PostgreSQL集群的安装与配置教程。Pgpool-II是一个位于PostgreSQL服务器和PostgreSQL数据库客户端之间的中间件,提供了连接池、复制、负载均衡、缓存、看门狗、限制链接等功能,可以用于搭建高可用的PostgreSQL集群。文章详细介绍了通过yum安装Pgpool-II的步骤,并提供了相关的官方参考地址。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • ZSI.generate.Wsdl2PythonError: unsupported local simpleType restriction ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • Go Cobra命令行工具入门教程
    本文介绍了Go语言实现的命令行工具Cobra的基本概念、安装方法和入门实践。Cobra被广泛应用于各种项目中,如Kubernetes、Hugo和Github CLI等。通过使用Cobra,我们可以快速创建命令行工具,适用于写测试脚本和各种服务的Admin CLI。文章还通过一个简单的demo演示了Cobra的使用方法。 ... [详细]
  • mysql-cluster集群sql节点高可用keepalived的故障处理过程
    本文描述了mysql-cluster集群sql节点高可用keepalived的故障处理过程,包括故障发生时间、故障描述、故障分析等内容。根据keepalived的日志分析,发现bogus VRRP packet received on eth0 !!!等错误信息,进而导致vip地址失效,使得mysql-cluster的api无法访问。针对这个问题,本文提供了相应的解决方案。 ... [详细]
  • centos安装Mysql的方法及步骤详解
    本文介绍了centos安装Mysql的两种方式:rpm方式和绿色方式安装,详细介绍了安装所需的软件包以及安装过程中的注意事项,包括检查是否安装成功的方法。通过本文,读者可以了解到在centos系统上如何正确安装Mysql。 ... [详细]
  • 本文介绍了关系型数据库和NoSQL数据库的概念和特点,列举了主流的关系型数据库和NoSQL数据库,同时描述了它们在新闻、电商抢购信息和微博热点信息等场景中的应用。此外,还提供了MySQL配置文件的相关内容。 ... [详细]
  • 使用C++编写程序实现增加或删除桌面的右键列表项
    本文介绍了使用C++编写程序实现增加或删除桌面的右键列表项的方法。首先通过操作注册表来实现增加或删除右键列表项的目的,然后使用管理注册表的函数来编写程序。文章详细介绍了使用的五种函数:RegCreateKey、RegSetValueEx、RegOpenKeyEx、RegDeleteKey和RegCloseKey,并给出了增加一项的函数写法。通过本文的方法,可以方便地自定义桌面的右键列表项。 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • mac php错误日志配置方法及错误级别修改
    本文介绍了在mac环境下配置php错误日志的方法,包括修改php.ini文件和httpd.conf文件的操作步骤。同时还介绍了如何修改错误级别,以及相应的错误级别参考链接。 ... [详细]
  • 先看一段错误日志:###Errorqueryingdatabase.Cause:com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransie ... [详细]
  • 背景应用安全领域,各类攻击长久以来都危害着互联网上的应用,在web应用安全风险中,各类注入、跨站等攻击仍然占据着较前的位置。WAF(Web应用防火墙)正是为防御和阻断这类攻击而存在 ... [详细]
  • 一次上线事故,30岁+的程序员踩坑经验之谈
    本文主要介绍了一位30岁+的程序员在一次上线事故中踩坑的经验之谈。文章提到了在双十一活动期间,作为一个在线医疗项目,他们进行了优惠折扣活动的升级改造。然而,在上线前的最后一天,由于大量数据请求,导致部分接口出现问题。作者通过部署两台opentsdb来解决问题,但读数据的opentsdb仍然经常假死。作者只能查询最近24小时的数据。这次事故给他带来了很多教训和经验。 ... [详细]
author-avatar
撒大时代撒的照写真
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有