你使用的Go版本是什么( go version
)?
在以下三个版本上进行了测试:
$ go version
go version go1.11.13 linux/amd64
$ go version
go version go1.12.9 linux/amd64
$ go version
go version go1.13 linux/amd64
这个问题在最新版本的发布中是否重现?
尚未在1.13.1版本中进行测试。
你正在使用什么操作系统和处理器架构( go env
)?
go env
输出
$ go env
GOARCH="amd64"
GOBIN=""
GOCACHE="/root/.cache/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/root/go"
GOPROXY=""
GORACE=""
GOROOT="/root/golang/1.12.9"
GOTMPDIR=""
GOTOOLDIR="/root/golang/1.12.9/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/mnt/git/github/netns-go-proof/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build717114236=/tmp/go-build -gno-record-gcc-switches"
你做了什么?
当我在解决Docker容器内运行的进程的套接字ID时,我发现当与进程网络命名空间关联的锁定线程读取procfs数据时,结果是不确定的。有时它会读取正确的数据,但相当频繁的是它会从主机命名空间中读取数据。
通过以下代码,我在RHEL 7.2 - 7.6上成功复现了这个问题: https://github.com/difrost/netns-go-proof
使用证明代码重现问题的步骤:
- 找到一个打开大量网络连接的容器:
$ docker ps --format "{{.ID}} {{.Ports}} {{.Names}}"
96cc2a87e368 0.0.0.0:1358->1358/tcp cranky_sutherland
b78274b8892f 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp rancher
- 在b78274b8892f中获取正在运行的进程:
$ docker top b78274b8892f -o pid,cmd
PID CMD
29724 tini -- rancher --http-listen-port=80 --https-listen-port=443 --audit-log-path=/var/log/auditlog/rancher-api-audit.log --audit-level=0 --audit-log-maxage=10 --audit-log-maxbackup=10 --audit-log-maxsize=100
29763 rancher --http-listen-port=80 --https-listen-port=443 --audit-log-path=/var/log/auditlog/rancher-api-audit.log --audit-level=0 --audit-log-maxage=10 --audit-log-maxbackup=10 --audit-log-maxsize=100
- 使用来自util-linux包的nsenter 从/proc/net/tcp中计算行数:
$ sudo nsenter -n -t 29763 cat /proc/net/tcp |wc -l
797
- 在29763上运行证明代码:
$ sudo ./NetNSBug -pid 29763
INFO[0000] Analysing 29763 in TID: 28877 PID: 28877
INFO[0000] We are in TID: 28877
INFO[0000] Got data for 29763:
INFO[0000] Got 0 lines loaded for UDP6
INFO[0000] Got 796 lines loaded for TCP
INFO[0000] Got 0 lines loaded for UDP
INFO[0000] Got 30 lines loaded for TCP6
INFO[0000] Namespace for 29763: net:[4026532507]
INFO[0000] Namespace for tid 28877: net:[4026532507]
- 作为参考,主机命名空间中的TCP:
$ cat /proc/net/tcp | wc -l
5
- 再次运行证明代码,但这次强制在除主线程之外的其他线程上执行。这是通过调用虚拟goroutine并使用runtime.Gosched授予其一些资源来完成的。
$ sudo ./NetNSBug -pid 29763 -f
INFO[0000] Analysing 29763 in TID: 29224 PID: 29224
INFO[0000] Forcing schedule on a proper thread.
INFO[0000] We are in TID: 29226
INFO[0000] Got data for 29763:
INFO[0000] Got 6 lines loaded for UDP6
INFO[0000] Got 4 lines loaded for TCP
INFO[0000] Got 4 lines loaded for UDP
INFO[0000] Got 4 lines loaded for TCP6
INFO[0000] Namespace for 29763: net:[4026532507]
INFO[0000] Namespace for tid 29226: net:[4026532507]
你期望看到什么?
从与网络命名空间关联的procfs中正确读取数据。
你看到了什么?
从主机命名空间中读取的数据。
2条答案
按热度按时间nkhmeac61#
以下是好和坏的读取计划跟踪,我找不到任何有助于发现根本原因的东西:
好的
坏的
svujldwt2#
CC @aclements