使用nginx代理跨机房的saltstack使用

问题背景

我们是游戏研发公司, 需要和不同的发行商合作运营
而且很多发行商要求使用自己的服务器(毕竟自己控制更可靠)
所以就出现了这么一种情况

业务不大, 但是不同云厂和区域的服务器不少.
并且我们使用 SaltStack 来管理主机的信息.
从主机的注册到作业的执行, 基本上是这样的

1
salt-master<----->nginx-stream<----->salt-minion

这里为啥使用 nginx-stream, 而不是 salt-syndic
主要是因为简单, 稳定, 而且 salt-syndic 无法针对单个 minion 下发 job

把 nginx 部署在docker swarm
有一个区域就添加一个docker worker, 然后自动的部署上去了

大概的思路是这样的, 然而在部署好了后使用salt 'h72g9g19vr391.qcloud.hk' test.ping
有时正常, 有时却返回超时

排查思路

saltstack 排查

先打开 salt-master 日志的 debug 模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2020-05-29 16:29:01,272 Sending event: tag = 20200529162901272112; data = {'minions': ['h72g9g19vr391.qcloud.hk'], '_stamp': '2020-05-29T08:29:01.272678'}
2020-05-29 16:29:01,273 Sending event: tag = salt/job/20200529162901272112/new; data = {'jid': '20200529162901272112', 'tgt_type': 'glob', 'tgt': 'h72g9g19vr391.qcloud.hk', 'us
2020-05-29 16:29:01,285 LazyLoaded config.option
2020-05-29 16:29:01,293 [salt.master :2346][INFO ][137] User root Published command test.ping with jid 20200529162901272112
2020-05-29 16:29:01,293 Published command details {'fun': 'test.ping', 'arg': [], 'tgt': 'h72g9g19vr391.qcloud.hk', 'jid': '20200529162901272112', 'ret': '', 'tgt_type': 'glob'
2020-05-29 16:29:01,294 Signing data packet
2020-05-29 16:29:01,294 salt.crypt.get_rsa_key: Loading private key
2020-05-29 16:29:01,294 salt.crypt.sign_message: Signing message.
2020-05-29 16:29:01,296 Sending payload to publish daemon. jid=20200529162901272112 size=452
2020-05-29 16:29:01,297 Connecting to pub server: ipc:///var/run/salt/master/publish_pull.ipc
2020-05-29 16:29:01,297 Sent payload to publish daemon.
2020-05-29 16:29:01,297 Publish daemon received payload. size=452
2020-05-29 16:29:01,298 Closing AsyncZeroMQReqChannel instance
2020-05-29 16:29:01,299 Publish daemon getting data from puller ipc:///var/run/salt/master/publish_pull.ipc
2020-05-29 16:29:01,332 LazyLoaded mongo.get_load
2020-05-29 16:29:01,336 LazyLoaded config.option
2020-05-29 16:29:01,567 get_iter_returns for jid 20200529162901272112 sent to {'h72g9g19vr391.qcloud.hk'} will timeout at 16:29:06.567535
2020-05-29 16:29:06,675 Checking whether jid 20200529162901272112 is still running

从上面 saltstack 的日志来看, master 已经将 job 信息 publish 到了 zeromq 里面了
然而, 在 salt-minion 上并没有看到相关的日志信息.

也就是说 salt-minion 完全没有收到 salt-master 的 publish 的信息.
salt-master 已经发了, 但是 salt-minion 没有收到
那就说明数据丢在了 nginx 的转发上面

nginx 排查

213f9a29b1b06f3565870b7711b86e40.png

从上面的抓包数据可以看到, 在第 8 秒时, “客户端”主动发起来断开的数据包(FIN)
到底是 salt-minion 发出的 FIN, 还是 nginx 发出的 FIN

猜测应该是 nginx 发出的 FIN, 理由如下

  1. 直连的 salt-minion 没有问题.
  2. salt-minion 的 debug 日志里没有任何信息
  3. 对比了正常请求的 salt-master 的 debug 日志, 没有任何关于客户端的错误

先看看 nginx 的配置

1
2
3
4
5
6
7
8
9
10
11
12
stream {
upstream salt-master {
hash $remote_addr consistent;
server 1.1.1.1:4505;
}
server {
listen 4505;
proxy_connect_timeout 5s;
proxy_timeout 5s;
proxy_pass salt-master;
}
}

从配置上来看, 问题出在了proxy_timeout 5s;, 查下文档.

1
2
3
4
5
6
Syntax:	proxy_timeout timeout;
Default:
proxy_timeout 10m;
Context: stream, server
Sets the timeout between two successive read or write operations on client or proxied server connections.
If no data is transmitted within this time, the connection is closed.

在客户端和代理服务器上设置读取或写入的超时时间, 如果没有数据传输, 则连接断开.
把这个配置文件去掉后, 就都正常了.

复盘总结

  1. 排查的思路很重要, 一直以为是 saltstack 出了问题, 不停的在查两边的日志.
  2. 配置文件是完全复制之前的, 所以出了问题才发现.