Kubernetes中的Pod無法訪問外網-Ubuntu16.04 LTS
安裝完Kubernetes後,在Pod中使用wget無法訪問外網URL地址,但是使用IP地址是可以訪問,應該是
Pod內無法解析DNS導致的。
1、解決方法
嘗試了將DNS換爲CoreDNS,問題仍然存在。經過多次測試,發現下面的方法是可行的:
編輯主機的/etc/resolv.conf文件:
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
# DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN #nameserver 127.0.1.1 nameserver 192.168.199.1 nameserver 8.8.8.8 nameserver 9.9.9.9 search lan
如果/etc/resolv.conf爲鏈接,則需要修改/etc/resolvconf/resolv.conf.d/base或head文件,然後運行resolvconf -u進行更新/etc/resolv.conf裏的內容。
2、原因分析
Ubuntu16.04 LTS安裝的resolvconf有一些問題,/etc/resolv.conf並非鏈接(有的安裝同一個版本是鏈接,很奇怪的),resolvconf -u等方法都會執行失敗。原則上,是鏈接的到/etc/resolvconf/resolv.conf.d裏面去改,不是鏈接的,直接修改/etc/resolv.conf文件。
可能Kubernetes啓動Pod時,要把/etc/resolv.conf裏的dns信息帶到pod中,而resolv.conf解析不到外面的地址。聯想到之前kube-dns經常出錯,估計也是這個原因。配置完後,kube-dns就很少出錯了。
3、其它
下面是從網上看到的方法,做過嘗試的一些方法。
經過測試,加入外部DNS後可以訪問外部網址,/etc/resolv.conf裏的nameserver的IP地址無法ping通,肯定也無法做域名解析了。因此,主要原因在於service的clusterip可以傳遞外部請求到pod,但是pod卻無法訪問service的ip,在多個技術網站搜索,基本上都出現此問題。
解決方法包括:
- 修改iptables的配置,在sysctl.conf。查看iptable配置,iptable -L -v。
- 使用Service Mesh,不知道是否有助於該問題。
- 使用weavenet的網絡驅動,有人說可以。有人說flannel可以,calico不行,但我用的flannel也是不行,可能跟操作系統也有關係,我的是ubuntu 16.04。
- sudo gedit sysctl.conf,插入:
###################################### # For K8s pod access service # by openthings,2018.06.30. #======================================
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-arptables = 1 #######################################
按照這些方法搞過,還是不行。 ping 10.96.0.10不通。
變通的方法:
- 設一個代理,使用IP地址去訪問。如https_proxy=192.168.199.99:9999 wget example.org,經測試,可行。也證明了網絡是通的,主要是DNS服務地址訪問不到。
- 嘗試通過修改/etc/resolvconf/resolv.conf.d/base,然後運行resolvconf不成功。
- 在POD裏添加新的DNS服務器,如在/etc/resolv.conf加上 nameserver=8.8.8.8,沒效果。進到pod裏,檢查/etc/resolv.conf,並沒有將主機的nameserver配置參數帶進來。
但是,這兩個方法雖然可以訪問外部地址了,但仍然不能訪問Kubernetes的Service產生的ClusterIP。不過,集羣內部訪問其它服務(包括POD自己的服務),可以通過服務名進行。
嘗試設置Kubernetes的Kube-dns的外部dns,將下面內容保存爲extdns.yaml。
apiVersion: v1 kind: ConfigMap metadata:
name: kube-dns
namespace: kube-system
labels:
addonmanager.kubernetes.io/mode: EnsureExists
data:
upstreamNameservers: /
["8.8.8.8", "9.9.9.9"]
- 然後運行kubectl create -f extdns.yaml,部署該設置到kubernetes集羣。不過,該方法貌似沒啥用。
- 更多參考:https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/
其它:
- docker inspect查看DNS設置。
- 以下內容來自於:https://juejin.im/entry/5aa9cc1af265da2384404c06
如果 Node 上安裝的 Docker 版本大於 1.12,那麼 Docker 會把默認的 iptables FORWARD 策略改爲 DROP。這會引發 Pod 網絡訪問的問題。解決方法則在每個 Node 上面運行 iptables -P FORWARD ACCEPT,比如
如果使用了 flannel/weave 網絡插件,更新爲最新版本也可以解決這個問題。
DNS 無法解析也有可能是 kube-dns 服務異常導致的,可以通過下面的命令來檢查 kube-dns 是否處於正常運行狀態
如果 kube-dns 處於 CrashLoopBackOff 狀態,那麼需要查看 kube-dns Pod 的日誌,根據日誌來修復 DNS 服務。
如果 kube-dns Pod 處於正常 Running 狀態,則需要進一步檢查是否正確配置了 kube-dns 服務:
如果 kube-dns service 不存在,或者 endpoints 列表爲空,則說明 kube-dns service 配置錯誤,可以重新部署 kube-dns service。