當前位置:首頁 » 文件傳輸 » 宿主機訪問容器的ip
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

宿主機訪問容器的ip

發布時間: 2023-01-08 08:15:51

Ⅰ Docker:Docker實現同Ip網段聯通

最近解決docker與宿主機同網段通信的問題,寫此文章記錄一下整個過程。
例如

宿主機A 和宿主機B是網路聯通關系,在宿主機A上面創建了多個容器組成集群,但是我希望通過宿主機B也可以訪問到宿主機A的容器,當然,你也可能會說,埠映射非常方便,如果我需要的埠比較多,或者著如果我臨時需要增加某些埠,可能設置起來比較麻煩,那麼如果我們將宿主機A裡面的容器的IP與宿主機的IP在同一個網路,不就可以直接來進行互聯互通了么。

安裝 Docker

安裝 pipework 這個工具可以使用一條命令就可以實現更改容器的IP,更准確來說為容器IP添加一個新的網卡。

編輯默認ip配置文件,eth0或者ens33(不同操作系統,名稱不一致,例如我操作的這台機器的名稱為ifcfg-ens33)

輸入 i 進入到編輯模式,將下面的內容復制到文件中

並且將配置內容復制到配置文件中

重啟虛擬機網路服務

修改docker的配置文件 /etc/sysconfig/

修改內容如下

修改完之後:

--net=none 代表容器的網卡都是為空的,需要通過 pipework 進行自定義指定

修改主機ip,網段與宿主機A網橋IP段保持一致。設置後,宿主機A,B之間可以互相ping通

到這里,就完成了Docker網路之間的通信。

Ⅱ docker容器網路

利用Net Namespace可以為Docker容器創建隔離的網路環境,容器具有完全獨立的網路棧,與宿主機隔離。也可以使Docker容器共享主機或者其他容器的網路命名空間,基本可以滿足開發者在各種場景下的需要。

Docker支持 4種網路模式 :

1)host模式,--net=host指定,不支持多主機。

2)container模式,--net = container : name_or_id指定,不支持多主機。

3)none模式,--net=none指定,不支持多主機。

4)bridge模式,--net=bridge指定,默認設置,不支持多主機。

啟動容器的時候使用Host模式,那麼該容器與宿主機共用一個Network Namespace,因此容器將不會虛擬自己的網卡、配置自己的IP等,而是使用宿主機的IP和埠。

採用Host模式的容器,可以直接使用宿主機的IP地址與外界進行通信,無需額外進行NAT轉換。由於容器通信時,不再需要通過Linux Bridge等方式轉發或者數據包的拆封,性能上有很大優勢。當然, Host模式有利也有弊 ,主要包括以下缺點:

1)容器沒有隔離、獨立的網路棧。容器因與宿主機共用網路棧而爭搶網路資源,並且容器崩潰也可能導致宿主機崩潰,這在生產環境中是不允許發生的。

2)容器不再擁有所有的埠資源,因為一些埠已經被宿主機服務、Bridge模式的容器埠綁定等其他服務佔用了。

需要補充說明的是,Host模式下的容器僅僅是網路命名空間與主機相同,但容器的文件系統、進程列表等還是和與宿主機隔離的。

Container模式是一種特殊的網路模式。該模式下的容器使用其他容器的網路命名空間,網路隔離性會處於Bridge模式與Host模式之間。當容器與其他容器共享網路命名空間時,這兩個容器間不存在網路隔離,但它們與宿主機及其他容器又存在網路隔離。

在Kubernetes體系架構下引入Pod概念,Kubernetes為Pod創建一個基礎設施容器, 同一Pod下的其他容器都以Container模式 共享這個基礎設施容器的網路命名空間,相互之間以localhost訪問,構成一個統一的整體。

與前兩種不同,None模式的Docker容器擁有自己的Network Namespace,但並不為Docker容器進行網路配置。該Docker容器沒有網卡、IP、路由等信息。需要用戶為Docker容器添加網卡、配置IP等。

Bridge模式是Docker默認的網路模式,也是開發者最常使用的網路模式。在這種模式下,Docker為容器創建獨立的網路棧,保證容器內的進程使用獨立的網路環境,實現容器之間、容器與宿主機之間的網路棧隔離。同時,通過宿主機上的Docker0網橋,容器可以與宿主機乃至外界進行網路通信。

同一宿主機上,容器之間都是連接在Docker0這個網橋上,Docker0作為虛擬交換機使容器間相互通信 。但是, 由於宿主機的IP地址與容器veth pair的IP地址均不在同一個網段 ,故僅僅依靠 veth pair和NameSpace的技術 並不足以使宿主機以外的網路主動發現容器的存在。Docker採用了 埠綁定的方式(通過iptables的NAT) ,將宿主機上的埠流量轉發到容器內的埠上,這樣一來,外界就可以與容器中的進程進行通信。 iptables的介紹,請點我點我 。

創建容器,並將宿主機的3306埠綁定到容器的3306埠:docker run -tid --name db -p 3306:3306 mysql

在宿主機上,可以通過「iptables -t nat -L -n」,查到一條DNAT規則:DNAT tcp --0.0.0.0/0 0.0.0.0/0 tcp dpt:3306 to:172.17.0.5:3306

Bridge模式的容器與外界通信時,必定會佔用宿主機上的埠,從而與宿主機競爭埠資源,這會造成對宿主機埠管理很復雜。同時,由於容器與外界通信是基於三層上iptables NAT,性能和效率損耗是顯而易見的。

NAT將地址空間分段的做法引入了額外的復雜度。比如容器中應用所見的IP並不是對外暴露的IP, 因為網路隔離,容器中的應用實際上只能檢測到容器的IP,但是需要對外宣稱的則是宿主機的IP,這種信息的不對稱將帶來諸如破壞自注冊機制等問題 。

摘抄自陸平的《基於Kubernetes的容器雲平台實戰》一書的第10章Kubernetes網路

Ⅲ docker從容器中怎麼訪問宿主機

例如你的docker環境的虛擬IP是192.168.99.100,那麼宿主機同樣會託管一個和192.168.99.100同網段的虛擬IP,並且會是主IP:192.168.99.1,那麼就簡單了,在容器中訪問192.168.99.1這個地址就等於訪問宿主機。

注意,通過192.168.99.1訪問宿主機,等於換了一個ip,如果資料庫或中間件限制了本機訪問或者做了ip段限制,要記得添加192.168.99.1到白名單。

Docker容器運行的時候有 host 、 bridge 、 none 三種網路可供配置。默認是 bridge ,即橋接網路,以橋接模式連接到宿主機; host 是宿主網路,即與宿主機共用網路; none 則表示無網路,容器將無法聯網。

當容器使用 host 網路時,容器與宿主共用網路,這樣就能在容器中訪問宿主機網路,那麼容器的 localhost 就是宿主機的 localhost 。

(3)宿主機訪問容器的ip擴展閱讀

宿主機和容器通信原理的問題:

考慮重啟速度:在實際的運維過程中,部分場景下,會出現主機卡死,或者docker進程卡死, 這時,最快恢復業務的方法是重啟主機。

容器在主機重啟後,可以自動恢復,因此可以做到在1到2分鍾內快速恢復業務。這一點太重要了,物理機重啟由於需要做各種硬體檢測,重啟時間一般在5到10分鍾, 虛擬機重啟一般在1分鍾以內 , 物理機顯然無法滿足需求。

重建能力很重要:

容器平台經常需要更新操作系統,或者根據需要調整主機規格。

運行一段時間後,發現內存配置偏少了, 需要添加內存。這時候申請一台新的機器加入到集群中,將舊機器下線即可。

運行多年的 ubuntu 12.04 官方已經不再維護, 需要全量替換,工作量相當大。好的方法就是使用全新的伺服器替換舊伺服器。

當發生故障,主機無法恢復時, 直接申請新伺服器加入集群即可。

Ⅳ Docker容器網路-實現篇

前面介紹了: Docker容器網路-基礎篇

前文說到容器網路對Linux虛擬化技術的依賴,這一篇章我們將一探究竟,看看Docker究竟是怎麼做的。通常,Linux容器的網路是被隔離在它自己的Network Namespace中,其中就包括:網卡(Network Interface)、回環設備(Loopback Device)、路由表(Routing Table)和iptables規則。對於一個進程來說,這些要素,就構成了它發起和響應網路請求的基本環境。

我們在執行 docker run -d --name xxx 之後,進入容器內部:

並執行 ifconfig:

我們看到一張叫eth0的網卡,它正是一個Veth Pair設備在容器的這一端。

我們再通過 route 查看該容器的路由表:

我們可以看到這個eth0是這個容器的默認路由設備。我們也可以通過第二條路由規則,看到所有對 169.254.1.1/16 網段的請求都會交由eth0來處理。

而Veth Pair 設備的另一端,則在宿主機上,我們同樣也可以通過查看宿主機的網路設備來查看它:

在宿主機上,容器對應的Veth Pair設備是一張虛擬網卡,我們再用 brctl show 命令查看網橋:

可以清楚的看到Veth Pair的一端 vethd08be47 就插在 docker0 上。

我現在執行docker run 啟動兩個容器,就會發現docker0上插入兩個容器的 Veth Pair的一端。如果我們在一個容器內部互相ping另外一個容器的IP地址,是不是也能ping通?

容器1:

容器2:

從一個容器ping另外一個容器:

我們看到,在一個容器內部ping另外一個容器的ip,是可以ping通的。也就意味著,這兩個容器是可以互相通信的。

我們不妨結合前文時所說的,理解下為什麼一個容器能訪問另一個容器?先簡單看如一幅圖:

當在容器1里訪問容器2的地址,這個時候目的IP地址會匹配到容器1的第二條路由規則,這條路由規則的Gateway是0.0.0.0,意味著這是一條直連規則,也就是說凡是匹配到這個路由規則的請求,會直接通過eth0網卡,通過二層網路發往目的主機。而要通過二層網路到達容器2,就需要127.17.0.3對應的MAC地址。所以,容器1的網路協議棧就需要通過eth0網卡來發送一個ARP廣播,通過IP找到MAC地址。

所謂ARP(Address Resolution Protocol),就是通過三層IP地址找到二層的MAC地址的協議。這里說到的eth0,就是Veth Pair的一端,另一端則插在了宿主機的docker0網橋上。eth0這樣的虛擬網卡插在docker0上,也就意味著eth0變成docker0網橋的「從設備」。從設備會降級成docker0設備的埠,而調用網路協議棧處理數據包的資格全部交給docker0網橋。

所以,在收到ARP請求之後,docker0就會扮演二層交換機的角色,把ARP廣播發給其它插在docker0網橋的虛擬網卡上,這樣,127.17.0.3就會收到這個廣播,並把其MAC地址返回給容器1。有了這個MAC地址,容器1的eth0的網卡就可以把數據包發送出去。這個數據包會經過Veth Pair在宿主機的另一端veth26cf2cc,直接交給docker0。

docker0轉發的過程,就是繼續扮演二層交換機,docker0根據數據包的目標MAC地址,在CAM表查到對應的埠為veth8762ad2,然後把數據包發往這個埠。而這個埠,就是容器2的Veth Pair在宿主機的另一端,這樣,數據包就進入了容器2的Network Namespace,最終容器2將響應(Ping)返回給容器1。在真實的數據傳遞中,Linux內核Netfilter/Iptables也會參與其中,這里不再贅述。

CAM就是交換機通過MAC地址學習維護埠和MAC地址的對應表

這里介紹的容器間的通信方式就是docker中最常見的bridge模式,當然此外還有host模式、container模式、none模式等,對其它模式有興趣的可以去閱讀相關資料。

好了,這里不禁問個問題,到目前為止只是單主機內部的容器間通信,那跨主機網路呢?在Docker默認配置下,一台宿主機的docker0網橋是無法和其它宿主機連通的,它們之間沒有任何關聯,所以這些網橋上的容器,自然就沒辦法多主機之間互相通信。但是無論怎麼變化,道理都是一樣的,如果我們創建一個公共的網橋,是不是集群中所有容器都可以通過這個公共網橋去連接?

當然在正常的情況下,節點與節點的通信往往可以通過NAT的方式,但是,這個在互聯網發展的今天,在容器化環境下未必適用。例如在向注冊中心注冊實例的時候,肯定會攜帶IP,在正常物理機內的應用當然沒有問題,但是容器化環境卻未必,容器內的IP很可能就是上文所說的172.17.0.2,多個節點都會存在這個IP,大概率這個IP是沖突的。

如果我們想避免這個問題,就會攜帶宿主機的IP和映射的埠去注冊。但是這又帶來一個問題,即容器內的應用去意識到這是一個容器,而非物理機,當在容器內,應用需要去拿容器所在的物理機的IP,當在容器外,應用需要去拿當前物理機的IP。顯然,這並不是一個很好的設計,這需要應用去配合配置。所以,基於此,我們肯定要尋找其他的容器網路解決方案。

在上圖這種容器網路中,我們需要在我們已有的主機網路上,通過軟體構建一個覆蓋在多個主機之上,且能把所有容器連通的虛擬網路。這種就是Overlay Network(覆蓋網路)。

關於這些具體的網路解決方案,例如Flannel、Calico等,我會在後續篇幅繼續陳述。

Ⅳ k8s-pod-初探2

踩坑完畢,回到主線。

前面關於port的理解存在偏差,需要用實驗來確認port配置的含義。

k8s官方文檔對於對於這些配置項的解釋還是沒有很完善。下面是在其他博文中找到的解釋。

已知:

從k8s集群內部的宿主機(物理機、虛擬機)可以直接訪問pod的服務地址 ip:80

未知(需要測試):

1、同一區域網內,但沒有加入k8s集群的其他伺服器能否訪問pod的服務地址 ip:80---無法訪問

2、能否跳過pod直接訪問容器的服務地址 ip:80---沒查到ip

首先要知道容器的IP地址

可以看到上面的命令查出的結果是 - 無法看出ip,嘗試進入容器查看

然後我就沒轍了,不過根據linux系統的精神,所有內容都是文件,但是我google了好久也沒找到ip地址到底存在哪一個文件中。然後我就懷疑是不是一定要容器開放埠,ip地址才可以用docker inspect查詢,起了一個不開埠的容器,結果也是有ip的。後來問了一個底層開發的朋友,據說ip是不寫文件的。

那隻能先認為通過k8s啟動的容器其實是沒有容器ip的。

從側面看,也很有可能k8s啟動的容器確實沒有ip

3、訪問pod所在的主機的80埠能否返回相同的響應---無法訪問

從以上的信息來看,這個port配置應該和docker中暴露埠的意思是一樣的,例如下面的例子

來做一下實驗:

在我們之前的pod配置文件上增加配置,如下

結果和我們之前的猜測保持一致,增加ports的配置之後,訪問宿主機的ip:80也可以訪問到pod的內容了。

我這里pod ip 是 10.19.130.67,宿主機是 10.100.1.237。curl 10.19.130.67 和 curl 10.100.1.237 得到的結果是一樣的。正當我想再仔細看看的時候,伺服器又掛了,wc,只能明天找網管重啟了。

---第二天

昨天,我還想看看

1、關了這個pod之後是否就不能訪問了

啟動了2個pod如下,mynginx1沒有配置ports,mynginx2配置了ports。

當我關了pod-mynginx2之後訪問宿主機10.100.2.167應該就不能通了,結果居然是---能訪問到!

大吃一驚!結果ip弄錯了,宿主機不是10.100.2.167,而是10.100.1.237,犯了個低級錯誤。

結果如下:這回和預期的結果終於一樣了。

2、宿主機上是不是本身就開啟了nginx,所以恰巧就能訪問

確認宿主機上沒有開啟nginx

3、宿主機上的埠開放情況

使用netstat查看宿主機的埠開放,居然沒有發現80埠開著,好奇怪。

那如果在10.100.1.237宿主機上啟動一個nginx埠開在80,結果會是什麼樣子呢。

我居然啟動了,沒有埠已被佔用的報錯。現在把宿主機上的nginx的index頁面的內容改一下,看訪問10.100.1.237:80時,到底訪問的是哪一個nginx。

分別從集群內部3台伺服器和集群外部1台伺服器的機器取訪問10.100.1.237:80,訪問到的都是pod中的nginx。

會不會跟啟動順序有關,因為現在的情況是先啟動了pod-nignx,後啟動 宿主機-nginx,那現在將pod-nginx關閉,訪問10.100.1.237:80,看是啥。

集群內部3台伺服器和集群外部1台伺服器訪問10.100.1.237:80,結果一致,都是宿主機-nginx。

再啟動pod-nginx,查看結果。

訪問結果又變回pod-nginx了,4台伺服器結果一致。

再去看一下宿主機-nginx的日誌,有沒有報錯信息-----------沒有錯誤日誌

現在基本可以得出結論了:當pod和宿主機同時使用某一個埠時,不會因為沖突而報錯,但是pod會優先佔用埠,而與啟動順序無關。

至於為什麼會這樣,就不去深究了,畢竟精力有限,作為運維實施,了解到這樣子的程度應該夠用了。

Ⅵ 宿主機telnet不通docker容器內的ip地址怎麼解決

Docker搭建了lnmp環境後,如果需要訪問安裝在宿主機上的資料庫或中間件,是不能直接使用127.0.0.1這個ip的,這個ip在容器中指向容器自己,那麼應該怎麼去訪問宿主機呢:

例如你的docker環境的虛擬IP是192.168.99.100,那麼宿主機同樣會託管一個和192.168.99.100同網段的虛擬IP,並且會是主IP:192.168.99.1,那麼就簡單了,在容器中訪問192.168.99.1這個地址就等於訪問宿主機,問題解決注意,通過192.168.99.1訪問宿主機,等於換了一個ip,如果資料庫或中間件限制了本機訪問或者做了ip段限制,要記得添加192.168.99.1到白名單