天天看點

有點奇怪!通路目的網址,主機能容器卻不行

摘要:看看一般網絡問題都怎麼定位的。

本文分享自華為雲社群《《跟唐老師學習雲網絡》 - 問題定位 - 主機通但容器不通》,作者: 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      

按理,應該也可以修複問題。

問題總結

本次容器網絡不通問題,總結一下,大概:

  1. 主機IP Forward轉發沒打開。 ==》原因1
  2. conf中有search字段。 ==》幹擾項
  3. 主機DNS伺服器位址設定不對。 ==》原因2
  4. Docker0網橋的混雜模式未打開。 ==》原因3

本次網絡故障,未涉及iptables相關問題,是以還算簡單。感謝閱讀。

點選關注,第一時間了解華為雲新鮮技術~