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

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

本文分享自華為雲社區《《跟唐老師學習雲網絡》 – 問題定位 – 主機通但容器不通》,作者: tsjsdbd。

本次網絡故障:主機可以訪問目的網址,但是容器里卻不行。問題有點奇怪,讓我們跟着唐老師分析的腳步,看看一般網絡問題都怎麼定位的吧。

問題現象

首先,這個節點上面的Docker是全新安裝的,系統Centos也是剛裝的。部門小夥伴報障說,啟動Docker後,容器裏面無法訪問網絡;但是Host主機上訪問則明明是好的。

報錯:

第一條紅線是容器裏面,第2條紅線是主機上。

圖示如下:

具體使用場景為,容器中用apt-get連華為雲的鏡像源()來安裝軟件包。但是容器中報錯: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相關問題,所以還算簡單。感謝閱讀。

 

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