故障描述
起因是根据研发同学反应对话平台后台管理系统登陆不了,报错查询clickhouse数据库异常,因为clickhouse为自建数据库,也是建立在k8s集群里面的pod,所以去查看相关后端项目和clickhouse数据库状态,经排查确认为数据库select卡主,数据存储用的是AWS efs。首先排查是否挂载异常,在堡垒机上挂载这个efs能挂载上,而且数据也还在,此时pod状态还为running,似乎除了查询不了其他都正常,数据库也能正常连接,因为此环境还未正式对外,所以本着测试的精神直接删除了相关Pod,但过了一会儿再看状态的时候Pod一直处于ContainerCreating,此时describe pod出现如下状态
查看到Pod无法挂载configmap和secret token
排查过程
参与人:AWS EKS工程师、AWS EFS工程师
首先进入Pod分配所在节点,查看kubelet相关日志,日志如下图
kubelet显示无法attach or mount相关volumes,其中就包含configmap、default-token,报错超时。于是手动在节点上挂载efs试试,mount也一直处于卡主最后超时,于是怀疑是否是网络不通,之后使用nc探测了efs的2048端口,efs默认监听的是tcp 2048端口,发现端口是通的。于是又去看系统日志
系统日志里面显示挂载EFS超时,not responding,没有返回,但之前使用nc探测的时候网络是通的,此时比较纳闷儿
接下来又随机去另外两个节点尝试了一下,发现也出现一样的状况,无法挂载efs,比较巧的是这几个节点都位于同一个交换机,当时未注意。之后我又随机删除了几个有挂载pvc的其他namespace里面的pod,发现并未报错都能正常启动。于是乎又去这个正常pod所在节点尝试挂载efs,发现是OK的,尝试了。纳闷儿了,于是乎去剩下的所有节点(节点不多)都尝试了一遍,发现部分节点可用挂载,部分节点不行。总结了一下是位于某一个交换机下的node节点都挂载不了
锁定了是某一个交换机的问题之后,最开始都检查过安全组规则,都是没有问题的,出入都放行,于是去找了一下acl规则,找到不能挂载的交换机acl规则,规则如下:
发现除了1024一下的端口有限制其他都没有,此时又做了一次aws ReachabilityAnalyzer测试网络连通性,测试结果也为正常,但出于尝试防止其他干扰,手动把这个交换机的acl规则出入站所有端口对所有地址都放行
再去节点测试,发现如愿以偿,之前不能挂载的那个交换机下的所有节点都能正常挂载了,于是得出结论可能是和efs建立双向连接的时候使用到了1024以下的端口。为了验证结论是否成立,用tcpdump进行了相关到efs的抓包测试,经分析发现确实存在客户端会使用1024一下的端口和efs连接
因为之前的acl规则对出站小于1024的端口会deny,所以才会导致上面的一些列问题
最终结论(来自AWS)
在经过测试后,我确认当挂载 NFS 时,客户端会使用到所谓的 privilege port (一般来说会是小于 1024 的端口)。根据我查找的资料,是由于过去 NFS 对于安全检查而有这样的的设计[1][2]。您可以透过以下命令来查看您系统中的 privilege port (以 Amazon Linux 2 为例):
$ sysctl -a | grep resvport
sunrpc.max_resvport = 1023
sunrpc.min_resvport = 665
我可以确认到在挂载 EFS 时,皆使用到上述范围的 port:
$ sudo mount -t nfs4 -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport fs-0705b30dbe1741990.efs.us-east-1.amazonaws.com:/ /mnt
$ sudo netstat -tanpo | grep 2049
tcp 0 0 172.31.38.122:952 172.31.35.153:2049 ESTABLISHED - keepalive (7.62/0/0)
$ sudo umount /mnt
$ sudo mount -t nfs4 -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,resvport fs-0705b30dbe1741990.efs.us-east-1.amazonaws.com:/ /mnt
$ sudo netstat -tanpo | grep 2049
tcp 0 0 172.31.38.122:711 172.31.35.153:2049 ESTABLISHED - keepalive (27.52/0/0)
$ sudo umount /mnt
且会根据系统设定的 privilege port 而变更:
$ sudo sysctl -w sunrpc.max_resvport=2048
sunrpc.max_resvport = 2048
$ sudo sysctl -w sunrpc.min_resvport=1024
sunrpc.min_resvport = 1024
$ sysctl -a | grep resvport
sunrpc.max_resvport = 2048
sunrpc.min_resvport = 1024
$ sudo mount -t nfs4 -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,resvport fs-0705b30dbe1741990.efs.us-east-1.amazonaws.com:/ /mnt
$ sudo netstat -anotp | grep 2049
tcp 0 0 172.31.33.197:1306 172.31.35.153:2049 ESTABLISHED - keepalive (23.93/0/0)
$ sudo umount /mnt
然而,这个行为仍有赖于客户端的行为。因此,在 EFS 的文件中也说明,为了支持各种不同的 NFS 客户端,Amazon EFS 允许来自任何源端口的连接[3]。建议您如果希望限制对于 EFS 存取的客户端,且同时避免客户端来源端口的问题,您可以考虑使用安全组来限制连线而避免使用 NACL