摘要:看看一般網絡問題都怎麼定位的。
本文分享自華為雲社群《《跟唐老師學習雲網絡》 - 問題定位 - 主機通但容器不通》,作者: tsjsdbd。
本次網絡故障:主機可以通路目的網址,但是容器裡卻不行。問題有點奇怪,讓我們跟着唐老師分析的腳步,看看一般網絡問題都怎麼定位的吧。
問題現象
首先,這個節點上面的Docker是全新安裝的,系統Centos也是剛裝的。部門小夥伴報障說,啟動Docker後,容器裡面無法通路網絡;但是Host主機上通路則明明是好的。
報錯:
第一條紅線是容器裡面,第2條紅線是主機上。
圖示如下:
具體使用場景為,容器中用apt-get連華為雲的鏡像源(http://mirrors.tools.huawei.com)來安裝軟體包。但是容器中報錯:Temporary failure resolving 'mirrors.tools.huawei.com'。
但是主機連這個源站卻是OK的。
大家想一下,可能什麼原因?
IP Forward轉發
上手開始定位,是以我登入環境,準備啟動一個空白容器先試下。
可是一啟動容器,馬上看到這麼一條告警:
docker run -it ubuntu:18.04 /bin/bash
WARNING: IPv4 forwarding is disabled. Networking will not work
可以看到,這個告警資訊,正常的容器以前是沒有的。是以很明顯,這個問題必須先搞定。
檢視:
cat /proc/sys/net/ipv4/ip_forward
0
事實也是這樣,從主機看待容器,它(容器)就是另一台“電腦”。封包經過主機給到容器,相當于主機幫忙“轉發”給容器。是以主機必須要有“封包轉發能力”。 ps,不好了解的話,可以回看一下唐老師前面的課程《跟唐老師學習雲網絡 - 網絡命名空間》篇。
是以,我們在主機上面開啟 ip_forward 開關:
修改/etc/sysctl.conf ,在檔案裡增加一條net.ipv4.ip_forward = 1
然後sysctl -p /etc/sysctl.conf 生效。
改完後,再啟動容器,該Warning就消失了。可是發現DNS還是無法解析,錯誤Temporary failure resolving 'mirrors.tools.huawei.com'仍然存在。
DNS中search字段
容器中不通,那咱們就抓包看看。于是我在如下位置(所有容器封包出去都要經過的地方),即docker0上面抓包:
tcpdump -nn -i docker0 port 53
然後容納中
ping mirrors.tools.huawei.com
發現發出去的查詢DNS的封包中,為什麼要在我詢問的域名後面加個尾巴?(下圖紅線)
還記得《跟唐老師學習雲網絡 - DNS電話簿》章節的知識不,/etc/resolv.conf配置檔案中,有個進階參數search字段。它可以用來幫你查詢域名的時候,往目标域名尾巴上添東西的(即補上字尾)的。這個在Kubernetes的Service微服務裡面,有用到。
So,我們将 /etc/resolv.conf 檔案中的 search 字段給注釋掉,這個參數暫時沒用。
# Generated by NetworkManager
#search novalocal
nameserver 100.79.1.250
nameserver 100.79.1.46
ps,最終驗證發現,這個search參數,并不是目前容器網絡不通的原因。 不過注釋掉這個參數,也是合理的,因為我們并不需要novalocal字尾。
DNS不通
繼續分析,容器裡面無法解析“mirrors.tools.huawei.com”這個域名。那先看容器裡面的/etc/resolv.conf檔案,其内容:
# Generated by NetworkManager
#search novalocal
nameserver 100.79.1.250
nameserver 100.79.1.46
可以看到是copy了主機Host裡的/etc/resolv.conf檔案。既然跟主機的DNS配置一樣,那先看看主機怎麼解這個域名。
在Host中使用:
nslookup mirrors.tools.huawei.com
** server can't find mirrors.tools.huawei.com: NXDOMAIN
發現,域名也是解不開的。。。囧,那主機上apt-get怎麼擷取到包的?咱們回顧一下《跟唐老師學習雲網絡 - DNS電話簿》章節的知識,解開一個域名,是單純依靠DNS伺服器的麼?
So,趕緊看下 /etc/hosts 檔案,發現一條寫死的 IP記錄。難怪。。。原來同僚之前域名解不開就直接加了“偷懶”路徑。(ps,容器也想加這種寫死的域名-IP解析路徑,可以使用docker run --add-host 參數。但是我不想隻是規避,而是真的搞定網絡問題)
于是找一台能解該域名的機器,把DNS伺服器位址抄過來,放入 /etc/resolv.conf 配置檔案見如下第一個DNS伺服器記錄。
# cat /etc/resolv.conf
# Generated by NetworkManager
#search novalocal
nameserver 10.129.2.34
nameserver 100.79.1.250
nameserver 100.79.1.46
然後把 /etc/hosts裡面的記錄删除,再試了下,主機可以解開域名了。
然後重新建立容器,并确認容器中的 /etc/resolv.conf 檔案内容也對。
但是發現域名還是不通。。。
混雜模式
既然還是不通,那祭出大殺器Tcpdump呗(可以回看《跟唐老師學習雲網絡 - tcpdump》章節),是以繼續在主機的docker0上開始抓包分析:
tcpdump -nn -i docker0 port 53
然後容器裡面仍然執行:
ping mirrors.tools.huawei.com
但是好奇怪,這次又通了。(于是停掉tcpdump,跟同僚說好了,結果他說還不行呀。我試下,确實又還不行)
試了幾次發現,隻要我tcpdump抓包,網絡就通。一旦tcpdump停掉,網絡就不通。大家想到了什麼?
看過唐老師之前tcpdump章節的同學應該有印象,tcpdump指令,會使得網卡進入混雜模式,使它會接受不是屬于自己的封包。
沒錯,通過
cat /sys/class/net/docker0/flags
查詢狀态(右數第3位,0和1表示是否為混雜模式)。
結果為0x1003
而當開啟tcpdump時為0x1103
那麼說明問題就是docker0在預設情況下,并沒有進入混雜模式導緻的。
是以,修複方案就是把這個docker0的網卡,直接設定為混雜模式:
ifconfig docker0 promisc
或
ip link set docker0 promisc on
然後驗證,一切OK。
ip link set docker0 promisc off
再2次确認一下,将混雜模式關閉後,容器裡面繼續不通。
到此,整個網絡問題搞定。
可能的根因
猜測可能這台機器是新安裝的,一開始沒有打開IP Forward轉發開關。然後又是手動安裝的Docker離線包,導緻docker0為非混雜模式。
在打開IP Forward轉發開關後,如果執行如下操作:
ip link delete docker0
systemctl restart docker.service
按理,應該也可以修複問題。
問題總結
本次容器網絡不通問題,總結一下,大概:
- 主機IP Forward轉發沒打開。 ==》原因1
- conf中有search字段。 ==》幹擾項
- 主機DNS伺服器位址設定不對。 ==》原因2
- Docker0網橋的混雜模式未打開。 ==》原因3
本次網絡故障,未涉及iptables相關問題,是以還算簡單。感謝閱讀。
點選關注,第一時間了解華為雲新鮮技術~