有點奇怪!訪問目的網址,主機能容器卻不行
摘要:看看一般網絡問題都怎麼定位的。
本文分享自華為雲社區《《跟唐老師學習雲網絡》 – 問題定位 – 主機通但容器不通》,作者: tsjsdbd。
本次網絡故障:主機可以訪問目的網址,但是容器里卻不行。問題有點奇怪,讓我們跟着唐老師分析的腳步,看看一般網絡問題都怎麼定位的吧。
問題現象
首先,這個節點上面的Docker是全新安裝的,系統Centos也是剛裝的。部門小夥伴報障說,啟動Docker後,容器裏面無法訪問網絡;但是Host主機上訪問則明明是好的。
報錯:
第一條紅線是容器裏面,第2條紅線是主機上。
圖示如下:
具體使用場景為,容器中用apt-get連華為雲的鏡像源(//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相關問題,所以還算簡單。感謝閱讀。