專題四 - 虛擬機器的網路設計與大量佈建
上次更新日期 2019/07/08
如果使用 libvirtd 的網路管理機制,那麼為了維護系統的安全與虛擬機器的運作,libvirtd 主動加入了不少的防火牆機制。 不過,也因為這些機制的關係,我們實體機器防火牆規則會經常的變動,導致實體機器管理上面的問題發生。所以,這個章節裡面, 我們來修改虛擬機器的網路設計,讓管理上變得掌握度可以提高!
另外,為了方便我們登入虛擬機器,因此,虛擬機器最好也要做點修改,包括 ssh 以及金鑰系統等等,都需要進行一些設定才好。 而且,為了讓我們的網路可以順利的運作,當然 dhcp 伺服器的建置也需要來處理處理囉。
- 虛擬機器的網路與實體機器的網路及防火牆相關性
- 網路參數提供者: dhcp server 設定
- VM 系統 (Guest OS) 與磁碟的整理
- VM 的大量佈署 - 使用 backing file 機制
虛擬機器的網路與實體機器的網路及防火牆相關性
上一堂課如果你有自己觀察防火牆,會發現多了好幾條防火牆規則~如前所述,這是因為 libvirtd 怕使用者忘記加上,而主動加上的防火牆規則。 不過,我們可能不需要這些規則。如果是這樣的話,可能得要取消 libvirtd 的橋接器,改用 Linux 自己的橋接功能,或許會比較好一些。
- 利用 libvirtd 管理網路的問題:
- 一般來說,比較便宜行事的方式,可以透過 libvirtd 的網路管理,如同專題三提到的內容,
透過 libvirtd 的 net-list, net-define, net-start 的方式來處理你的虛擬機器需要的橋接功能,就能夠讓你的虛擬機器使用實體機器的網路連線出去!
基本的連線模式有 nat, birdge, private 等等。
# 請再次檢查你的 libvirtd 管理的網路橋接設定: # virsh net-list --all 名稱 狀態 自動啟動 Persistent ---------------------------------------------------------- qforward 啟用 no no qnet 啟用 no no # virsh net-dumpxml qforward <network> <name>qforward</name> <uuid>5d1316c2-1abc-4730-9afd-2d68142e883e</uuid> <forward dev='eth0' mode='bridge'> <interface dev='eth0'/> </forward> </network> # virsh net-dumpxml qnet <network connections='1'> <name>qnet</name> <uuid>d3e536a4-83bf-458f-9ab1-dda5ed121d76</uuid> <forward mode='nat'> <nat> <port start='1024' end='65535'/> </nat> </forward> <bridge name='virbr1' stp='on' delay='0'/> <mac address='52:54:00:66:ff:0c'/> <ip address='192.168.10.254' netmask='255.255.255.0'> <dhcp> <range start='192.168.10.1' end='192.168.10.100'/> </dhcp> </ip> </network> # 如上所示,我們的系統裡面,透過 libvirtd 管理的,目前就有兩個橋接界面
- 不過,使用 libvirtd 管理網路時,為了要進行 NAT,因此 libvirtd 會主動的啟動 dhcp, dnsmasq, iptables 等服務,
因此,你的實體機器上面就會多出很多的埠口!當你啟用了 libvirtd 的網路界面時,務必去瞧一瞧網路埠口,啟動 VM 時,去瞧一瞧 iptables 的服務,
你就可以發現相關的狀況為何了。
# 1. 先檢查一下你的網路界面有哪些喔: # ip link show 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000 link/ether 52:54:00:85:b1:54 brd ff:ff:ff:ff:ff:ff 3: virbr1: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default qlen 1000 link/ether 52:54:00:66:ff:0c brd ff:ff:ff:ff:ff:ff 4: virbr1-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr1 state DOWN mode DEFAULT group default qlen 1000 link/ether 52:54:00:66:ff:0c brd ff:ff:ff:ff:ff:ff # 基本上, virdbr1 是由 qnet 所產生的橋接界面。而 virdbr1-nic 則是放置在 VM 內的網卡 # 2. 檢查一下網路服務的監聽埠口有哪些? # netstat -tlunp | egrep '(Active|Proto|dns)' Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 192.168.10.254:53 0.0.0.0:* LISTEN 13305/dnsmasq udp 0 0 192.168.10.254:53 0.0.0.0:* 13305/dnsmasq udp 0 0 0.0.0.0:67 0.0.0.0:* 13305/dnsmasq # 你會發現有一些多的埠口會產生的!有時候還會多出 port 67 喔! # 3. 檢查一下 iptables 防火牆規則! # iptables-save # Generated by iptables-save v1.4.21 on Mon Apr 15 13:11:55 2019 *filter :INPUT DROP [119562:18055629] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [12650:586132] -A INPUT -i virbr1 -p udp -m udp --dport 53 -j ACCEPT -A INPUT -i virbr1 -p tcp -m tcp --dport 53 -j ACCEPT -A INPUT -i virbr1 -p udp -m udp --dport 67 -j ACCEPT -A INPUT -i virbr1 -p tcp -m tcp --dport 67 -j ACCEPT .... -A FORWARD -d 192.168.10.0/24 -o virbr1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A FORWARD -s 192.168.10.0/24 -i virbr1 -j ACCEPT -A FORWARD -i virbr1 -o virbr1 -j ACCEPT -A FORWARD -o virbr1 -j REJECT --reject-with icmp-port-unreachable -A FORWARD -i virbr1 -j REJECT --reject-with icmp-port-unreachable -A OUTPUT -o virbr1 -p udp -m udp --dport 68 -j ACCEPT COMMIT # Completed on Mon Apr 15 13:11:55 2019 # Generated by iptables-save v1.4.21 on Mon Apr 15 13:11:55 2019 *nat :PREROUTING ACCEPT [322151:40588412] :INPUT ACCEPT [3:144] :OUTPUT ACCEPT [63:3594] :POSTROUTING ACCEPT [63:3594] ... -A POSTROUTING -s 192.168.10.0/24 -d 224.0.0.0/24 -j RETURN -A POSTROUTING -s 192.168.10.0/24 -d 255.255.255.255/32 -j RETURN -A POSTROUTING -s 192.168.10.0/24 ! -d 192.168.10.0/24 -p tcp -j MASQUERADE --to-ports 1024-65535 -A POSTROUTING -s 192.168.10.0/24 ! -d 192.168.10.0/24 -p udp -j MASQUERADE --to-ports 1024-65535 -A POSTROUTING -s 192.168.10.0/24 ! -d 192.168.10.0/24 -j MASQUERADE COMMIT # Completed on Mon Apr 15 13:11:55 2019 # 如上所示,那個 virdbr1 的規則,通通是 libvirtd 幫你自己建立的!事實上,我們可能並不需要喔!
- 那 libvirtd 的 virsh 是怎麼設計這個網路的控制呢?其實 virsh 針對不同的網路環境,
不論是 nat, bridge 或是 private ,都有設計一些基礎的防火牆設定值,相關設定可以使用 virsh nwfilter-?? 來查詢:
# 1. 先檢查一下 virsh 提供了多少的網路防火牆機制 (network filter, nwfilter): # virsh nwfilter-list UUID 名稱 ------------------------------------------------------------------ a5623aff-8477-404d-9230-b95971ab0e14 allow-arp d7a109ff-c1c1-41c3-ae7d-2876f876bd52 allow-dhcp <==等等來看一下這個東西! df57d86f-93d8-44da-b8a3-826c2fe2c19e allow-dhcp-server b976041b-743d-4ffd-887d-2eb7277d73e8 allow-incoming-ipv4 a9bc573b-cb6c-4330-bd3a-ff17eeef4db7 allow-ipv4 40fa7d7d-e939-43fc-964c-03ce1e300781 clean-traffic a9940600-c70d-416e-bac8-8a35156a556f clean-traffic-gateway 49d3863a-be03-4b9c-b9c0-6183fd891afb no-arp-ip-spoofing fd629df7-cc3b-4586-a4cd-ab2e511d7866 no-arp-mac-spoofing 99af5654-741d-4ac3-94ae-d1c785bd2f39 no-arp-spoofing 8e50a914-0373-416e-9408-062228c8de2e no-ip-multicast c9d59368-cb15-4fdc-8857-e2eb47d3372b no-ip-spoofing c0823564-2876-4e28-b782-5f3c8fd48672 no-mac-broadcast 196ea180-afd4-4cb6-a6ff-56f29346989e no-mac-spoofing cbbdc197-ba7d-4f55-908d-3fde8fbda6dc no-other-l2-traffic 895c7d95-2657-49e7-8e8c-66d29ca7508b no-other-rarp-traffic 5bbc92e4-d3cf-44da-a2bc-0f67735a0fe5 qemu-announce-self 5c6b638f-4d7f-4d67-ad40-f3ce453e351a qemu-announce-self-rarp # 2. 承上,來看看 allow-dhcp 的規則為何? # virsh nwfilter-dumpxml allow-dhcp <filter name='allow-dhcp' chain='ipv4' priority='-700'> <uuid>d7a109ff-c1c1-41c3-ae7d-2876f876bd52</uuid> <rule action='accept' direction='out' priority='100'> <ip srcipaddr='0.0.0.0' dstipaddr='255.255.255.255' protocol='udp' srcportstart='68' dstportstart='67'/> </rule> <rule action='accept' direction='in' priority='100'> <ip protocol='udp' srcportstart='67' dstportstart='68'/> </rule> </filter> # 上面的規則中,意思是放行 udp 封包格式,包括 67 及 68 port number 的 input 設置! # 所以,這也是為何我們設定了界面有支援 dhcp 時,就會多了幾個防火牆的情況!
- 一般來說,比較便宜行事的方式,可以透過 libvirtd 的網路管理,如同專題三提到的內容,
透過 libvirtd 的 net-list, net-define, net-start 的方式來處理你的虛擬機器需要的橋接功能,就能夠讓你的虛擬機器使用實體機器的網路連線出去!
基本的連線模式有 nat, birdge, private 等等。
- 利用 Linux 核心的 bridge 功能:
- Linux 可以透過 ip 指令或者是 brctl 指令來產生一個內部的橋接界面,
該橋接界面也能夠實際綁定在某個實體網卡上面。不過,因為目前我們的系統裡面,只需要使用內部的橋接界面,
該界面可以讓虛擬機器來使用,同時可以讓實體機器透過 iptables 來進行封包轉遞即可。
# 1. 先使用 ip 指令來建立一個名為 mybr0 的橋接網路 # ip link add mybr0 type bridge # ip link show 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000 link/ether 52:54:00:85:b1:54 brd ff:ff:ff:ff:ff:ff 13: virbr1: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default qlen 1000 link/ether 52:54:00:66:ff:0c brd ff:ff:ff:ff:ff:ff 14: virbr1-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr1 state DOWN mode DEFAULT group default qlen 1000 link/ether 52:54:00:66:ff:0c brd ff:ff:ff:ff:ff:ff 15: mybr0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether 7e:a0:8c:69:6d:02 brd ff:ff:ff:ff:ff:ff # 2. 再用 brctl 建立一個名為 mybr1 的橋接界面: # brctl addbr mybr1 # brctl show bridge name bridge id STP enabled interfaces mybr0 8000.000000000000 no mybr1 8000.000000000000 no virbr1 8000.52540066ff0c yes virbr1-nic # 由上面的結果來看,我們可以看到目前有三個橋接器的界面,分別是 mybr0, mybr1, virdbr1 三個。
- 雖然使用 ip 或 brctl 可以很快速的建立好所需要的橋接界面,不過,在設定 IP 等行為上面,
沒有辦法做的比較完整。因此,建議可以直接修改 /etc/sysconfig/network-scripts/ifcfg-?? 的檔案,或者是直接使用 nmcli 來設定,
都可以處理妥當!
# 1. 先將剛剛建立的 mybr0 及 mybr1 刪除: # brctl delbr mybr0 # brctl delbr mybr1 # brctl show bridge name bridge id STP enabled interfaces virbr1 8000.52540066ff0c yes virbr1-nic # 最終只剩下一個而已,這樣就對了! # 2. 開始使用 nmcli 建立沒有綁定任何實體網卡的橋接器: # nmcli connection add type bridge con-name mybr0 ifname mybr0 ipv4.method manual ipv4.addresses 192.168.19.254/24 # nmcli connection show NAME UUID TYPE DEVICE eth0 0ae1fc2c-65cf-46b8-acc4-514a56f26e4c ethernet eth0 mybr0 91b3007e-cf11-437e-b5f2-52939272cc83 bridge mybr0 <==新的界面喔! virbr1 5d4a1a13-351b-4345-8441-9a3576db277a bridge virbr1 # ip addr show mybr0 17: mybr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000 link/ether 8a:8a:11:78:e6:12 brd ff:ff:ff:ff:ff:ff inet 192.168.19.254/24 brd 192.168.19.255 scope global noprefixroute mybr0 # brctl show bridge name bridge id STP enabled interfaces mybr0 8000.000000000000 yes <==注意看, mybr0 並沒有綁定任何實體網卡喔! virbr1 8000.52540066ff0c yes virbr1-nic
- Linux 可以透過 ip 指令或者是 brctl 指令來產生一個內部的橋接界面,
該橋接界面也能夠實際綁定在某個實體網卡上面。不過,因為目前我們的系統裡面,只需要使用內部的橋接界面,
該界面可以讓虛擬機器來使用,同時可以讓實體機器透過 iptables 來進行封包轉遞即可。
- 重新整理系統的網路參數與防火牆設置:
- 因為要使用我們手動建立的橋接界面,因此建議將 libvirtd 管理的網路界面通通關閉。而要處理網路界面前,
則必須要將所有的虛擬機器關閉才可以,否則可能會有衝突的情況發生。
# 1. 先關閉所有的虛擬機器才好: # virsh list Id 名稱 狀態 ---------------------------------------------------- # 如果有任何存在的 domain,都請關閉他!使用『 virsh shutdown domainname 』; # 這樣是正常關機!除非你的虛擬機器當機,否則不要使用 virsh destroy VMdomain,destroy 是強迫關機! # 2. 關閉並取消所有的網路界面 # virsh net-list --all 名稱 狀態 自動啟動 Persistent ---------------------------------------------------------- qforward 啟用 no no qnet 啟用 no no # virsh net-destroy qforward # virsh net-destroy qnet # virsh net-undefine qforward # virsh net-undefine qnet # 3. 再次檢查系統的網路服務埠口是否還有啟動呢? # netstat -tlnup Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN 1/systemd tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 4498/sshd tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 4658/master tcp6 0 0 :::111 :::* LISTEN 1/systemd tcp6 0 0 :::22 :::* LISTEN 4498/sshd tcp6 0 0 ::1:25 :::* LISTEN 4658/master udp 0 0 0.0.0.0:111 0.0.0.0:* 1/systemd udp 0 0 0.0.0.0:851 0.0.0.0:* 4070/rpcbind udp6 0 0 :::111 :::* 1/systemd udp6 0 0 :::851 :::* 4070/rpcbind # 你可以明顯的發現,那個 dnsmasq 已經不在存在了!恭賀恭賀! # 4. 最終,確認一下我們的網路界面囉: # ip addr show 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 52:54:00:85:b1:54 brd ff:ff:ff:ff:ff:ff inet 172.16.10.101/16 brd 172.16.255.255 scope global noprefixroute dynamic eth0 valid_lft 204931sec preferred_lft 204931sec inet6 fe80::483b:1735:c7da:f241/64 scope link noprefixroute valid_lft forever preferred_lft forever 17: mybr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000 link/ether 8a:8a:11:78:e6:12 brd ff:ff:ff:ff:ff:ff inet 192.168.19.254/24 brd 192.168.19.255 scope global noprefixroute mybr0 valid_lft forever preferred_lft forever # 我們有 eth0, mybr0 這兩個有可連線的 IP 界面喔!其中 mybr0 是作為我們虛擬機器內部連線的一個重要界面。
- 在關閉了相關的網路界面之後,你的防火牆應該就會恢復到你原本設定的模樣!
但是,因為我們未來的內部網路會使用到 192.168.19.0/24 這一段,而且來自於這個虛擬橋接器的網路都是內網,
所以可以直接給予放行!所以,打開你的防火牆腳本檔,增加及修改底下這幾段資料:
# 1. 增加防火牆的規則,對於內部連線放行 mybr0 這個裝置,對於對外連線,針對 192.168.19.0/24 放行 IP 偽裝: # vim firewall.sh iptables -A INPUT -i mybr0 -j ACCEPT iptables -t nat -A POSTROUTING -s 192.168.19.0/24 -o eno1 -j MASQUERADE # systemctl stop iptables # sh firewall.sh # systemctl restart iptables # 如此一來,你的防火牆規則就建置妥當了!棒棒Der!
- 因為要使用我們手動建立的橋接界面,因此建議將 libvirtd 管理的網路界面通通關閉。而要處理網路界面前,
則必須要將所有的虛擬機器關閉才可以,否則可能會有衝突的情況發生。
- 讓 VM 利用本機的橋接器:
- 修改 xml 檔案的內容,關於網路的地方修改:
# 1. 編輯 xml 設定檔 # vim centos7.ver01.xml # 原本長的像這樣: <interface type="network"> <source network="qnet"/> <mac address="52:54:00:db:5d:d8"/> <model type="virtio"/> </interface> # 將他改成變這樣: <interface type="bridge"> <source bridge="mybr0"/> <mac address="52:54:00:db:5d:d8"/> <model type="virtio"/> </interface>
- 開始啟動虛擬機器,並且觀察實體機器的各項網路參數囉:
# 1. 在實體機上面,啟動了 VM 吧! # virsh create centos7.ver01.xml # virsh list Id 名稱 狀態 ---------------------------------------------------- 1 centos7v01 執行中 # netstat -tlnp Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:2222 0.0.0.0:* LISTEN 1236/sshd tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN 1/systemd tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1236/sshd tcp 0 0 0.0.0.0:5911 0.0.0.0:* LISTEN 13912/qemu-kvm <==忘記 port 時,可以這樣查 tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN 1232/cupsd tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1490/master tcp6 0 0 :::2222 :::* LISTEN 1236/sshd tcp6 0 0 :::111 :::* LISTEN 1/systemd tcp6 0 0 :::22 :::* LISTEN 1236/sshd tcp6 0 0 ::1:631 :::* LISTEN 1232/cupsd tcp6 0 0 ::1:25 :::* LISTEN 1490/master # 2. 開始觀察本機的網路參數的變化: # ip link show 17: mybr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000 link/ether fe:54:00:db:5d:d8 brd ff:ff:ff:ff:ff:ff 19: vnet0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master mybr0 state UNKNOWN mode DEFAULT group default qlen 1000 link/ether fe:54:00:db:5d:d8 brd ff:ff:ff:ff:ff:ff # 這個 vnet0 就是 virsh 透過 libvirtd 自動產生的,提供給虛擬機器連接到外部的主要網路界面! # 你也可以看到,這個界面就是透過 mybr0 來連線的喔!
- 修改 xml 檔案的內容,關於網路的地方修改:
透過上述的功能,我們修改了實體機器的橋接器界面,讓我們自己手動管理橋接!不再透過 virsh 的網路設計,如此一來,未來我們的環境, 比較能夠自由的掌控!而且防火牆規則也比較清楚。另外,你要不要讓你的虛擬機器可以直接連網,或者是透過 NAT,也可以透過實體機器的設定來處理! 不再透過 virsh 的管理。而自己設定的橋接器 (mybr0) 也因為沒有綁定實體網卡,因此你的虛擬機器也不會被外部的其他相同 private network 所衝突! 在處理上也是一個可以考慮的角度。
實體機器管理虛擬機器的網路,主要是透過一個橋接界面 (本例中使用 mybr0) 來作為類似一個 switch 的角度!剛剛我們也發現到,啟動第一個 VM 時, 實體機器上面會有一個 vnet0 的界面,而虛擬機器裡面會有個 eth0 的界面,他們的關係有點像這樣:
而這個 mybr0 可以將 vnet0 vnet1... 串在一起,就真的很像 switch 啊!然後可以透過本機的 iptables 的 ip forward 功能,即可對外連線了! 相當的方便好用喔!
網路參數提供者: dhcp server 設定
一般來說,使用 libvirtd 內建的網路橋接界面,他可以自行設計好 dhcp 服務,所以我們可以不用架設 DHCP server。不過, 我們在後面還需要自己設定好需要的網路開機機制,因此得要額外加上許多 dhcp 的設定。因此,最好還是將 dhcp server 的管理權限拿回來, 這樣管理上也比較方便。
- 讓 VM 未來可以自動取得 IP 的 dhcp 伺服器設定:
- 自己建立一個可以自動分配 IP 網段的 dhcp 伺服器:
# 1. 安裝好 dhcp server # yum install dhcp # 2. 開始設定好 DHCP 伺服器的服務,注意,我們只要針對 192.168.19.0/24 這一個區段設計, # 另外,我們也只分配 1~150 號之間的設計而已! # vim /etc/dhcp/dhcpd.conf default-lease-time 600; max-lease-time 72000; ddns-update-style none; log-facility local7; subnet 192.168.19.0 netmask 255.255.255.0 { range 192.168.19.1 192.168.19.150; option routers 192.168.19.254; option domain-name "virtual.dic"; option domain-name-servers 120.114.100.1,120.114.150.1; } # systemctl start dhcpd # systemctl enable dhcpd # tail -n 100 /var/log/messages| grep dhcpd Apr 16 14:01:49 120-114-142-27 dhcpd: Listening on LPF/mybr0/fe:54:00:c4:cb:62/192.168.19.0/24 Apr 16 14:01:49 120-114-142-27 dhcpd: Sending on LPF/mybr0/fe:54:00:c4:cb:62/192.168.19.0/24 # 3. 觀察一下本機的 port 變化情況: # netstat -tlunp Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:5931 0.0.0.0:* LISTEN 9921/qemu-kvm tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN 1/systemd tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 4498/sshd tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 4658/master tcp6 0 0 :::111 :::* LISTEN 1/systemd tcp6 0 0 :::22 :::* LISTEN 4498/sshd tcp6 0 0 ::1:25 :::* LISTEN 4658/master udp 0 0 0.0.0.0:67 0.0.0.0:* 28423/dhcpd udp 0 0 0.0.0.0:111 0.0.0.0:* 1/systemd udp 0 0 0.0.0.0:851 0.0.0.0:* 4070/rpcbind udp6 0 0 :::111 :::* 1/systemd udp6 0 0 :::851 :::* 4070/rpcbind
- 為了方便未來的設計,最好加裝 bind 這個 name server 才好。 不過,未來實際練習再來玩吧!
- 自己建立一個可以自動分配 IP 網段的 dhcp 伺服器:
- 使用 spice 的方式連線到剛剛啟動的虛擬機上面,開始設定我們需要的網路參數:
# 1. 請使用 remote viewer 的軟體來連接上這個虛擬機器,底下為虛擬機器的設定: # nmcli connection show NAME UUID TYPE DEVICE eth0 380bcc96-fa09-41f9-ba1c-f1887466c65f ethernet eth0 # 2. 設定網路使用方式為 dhcp 喔! # nmcli connection modify eth0 ipv4.method auto ipv4.addresses '' ipv4.gateway '' ipv4.dns '' # nmcli connection up eth0 # 3. 嘗試連上 Internet 瞧瞧: # ping -c 3 168.95.1.1 # yum install bind-utils # dig www.google.com # 上面的指令都能成功的話,你的網路就已經暢行無阻了!恭喜恭喜!
- 在 Server 上面觀察 Client 取得的 IP 狀態:
事實上,在 Server 上面我們可以觀察用戶端取得的 dhcp 伺服器的網路參數喔!通常 dhcp 會將資料記載在 /var/log/messages 裡面, 也會將用戶端的詳細資訊載入到 /var/lib/dhcpd/dhcpd.leases 當中!通常我們可以這樣偵測:
# tail -f /var/log/messages
如果有最新的 dhcp 資訊,就會顯示到螢幕上!那你就知道用戶端取得的 IP 為何囉!
VM 系統 (Guest OS) 與磁碟的整理
想讓管理員可以更輕鬆的管理 VM,你最好針對 VM 的 Guest OS 進行一些基礎的設定~包括防火牆、SELinux 以及 sshd 的金鑰資料等等。 接下來,讓我們一項一項處理囉:
- 建立範本的 image 以及 XML 檔案內容:
基本上,想要大量佈建虛擬機器時,最主要就是複製兩個東西: (1)虛擬機器硬碟檔 (2)虛擬機器硬體設定檔 (就是 XML 檔案)。 XML 檔案的複製倒是沒啥大問題。但是,虛擬機器的硬碟檔要複製時,最好就是先處理好經常性的操作任務,包括升級啦、安裝基本的軟體啦、 取消不要的埠口啦、取消不要的軟體啦等等的,同時,最好也檢查一下,不要有太多的莫名帳號存在,避免你的個人資料洩漏。還有一些基礎的設定值, 通通要處理比較好:
- 設計基礎設定檔 demo.xml 以及基礎檔案 demo.img:
# 1. 先將所有的 VM 關閉,再來處理後續的相關事宜: # virsh list Id 名稱 狀態 ---------------------------------------------------- 1 centos7v01 執行中 # virsh shutdown centos7v01 # 2. 先來到 /vmdisk 目錄,然後進行複製與修改的行為: # cd /vmdisk # cp centos7.ver01.xml demo.xml # cp centos7.ver01.img demo.img # vim demo.xml # 要改的部份有 (1)name, (2)memory+currentMemory, (3)cputune, (4)cpu+topology # (5)<clock offset="utc"> (6)<source file="/vmdisk/demo.img"/> # (7)<interface type="bridge"> <source bridge="mybr0"/> # (8)<mac address="52:54:00:C4:CB:62"/> # (9)<graphics type="spice" port="xxxx" listen="0.0.0.0" passwd="xxxxxxx"> # 3. 啟動這個虛擬機器吧! # virsh create demo.xml 區域 demo 建立自 demo.xml
- 處理這個虛擬機器的相關任務:
# 1. 全系統升級、安裝所需要的軟體等等設定: # yum -y update # yum install net-tools bash-completion vim-enhanced tcpdump bind-utils bridge-utils # yum install iptables-services # 2. 處理防火牆的相關問題: # systemctl stop firewalld; systemctl disable firewalld # systemctl start iptables; systemctl enable iptables # vim firewall.sh #!/bin/bash iptables -F iptables -X iptables -Z iptables -P INPUT DROP iptables -P OUTPUT ACCEPT iptables -P FORWARD ACCEPT iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT iptables -A INPUT -p icmp -j ACCEPT iptables -A INPUT -i lo -j ACCEPT iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT iptables -A INPUT -s 192.168.19.0/24 -j ACCEPT iptables -A INPUT -j REJECT iptables-save > /etc/sysconfig/iptables # sh firewall.sh # 3. 暫時讓 SELinux 變成 permissive 的樣式: # vim /etc/selinux/config SELINUX=permissive # 4. 變更 sudo 的操作,讓你的用戶登入時,無須再輸入一次密碼。你的用戶不能加入 wheel 群組喔! # visudo your_account_name ALL=(ALL) NOPASSWD: ALL # 5. 重新開機後,處理核心檔案的動作: # reboot # uname -r 3.10.0-957.10.1.el7.x86_64 # ll /lib/modules drwxr-xr-x. 7 root root 4096 3月 19 19:16 3.10.0-957.10.1.el7.x86_64 drwxr-xr-x. 7 root root 4096 3月 12 19:52 3.10.0-957.el7.x86_64 # yum remove kernel-3.10.0-957.el7.x86_64 # 6. 整理 ssh 的可登入權限: # vim /etc/ssh/sshd_config PermitRootLogin yes <==因為未來可能會設定遠端處理方式! UseDNS no # systemctl restart sshd # 7. 讓系統效能使用的情況為 virtual-guest 狀態: # tuned-adm profile virtual-guest
- 設計好快速登入這個系統的 ssh 鑰匙:
# 1. 在實體機器的 root 以及自己的慣用帳號上面,建立 ssh 金鑰: # root # ssh-keygen # ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.19.10 # 一般用戶 $ ssh-keygen $ ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.19.10 # 這樣,即使未來忘記了這個 VM 的 root 密碼,只要有辦法知道 IP,依舊可以登入 VM 系統的!
- 登出虛擬機器,然後使用 spice 原生的終端機,來到 VM 裡面,並且進行如下的行為:
# 1. 讓網路變成使用 dhcp 的模樣,以保證 VM 的 IP 不會衝突 # nmcli connection modify eth0 ipv4.method auto ipv4.addresses '' ipv4.dns '' ipv4.gateway '' # nmcli connection up eth0 # nmcli connection show eth0 | grep IP4 IP4.ADDRESS[1]: 192.168.19.1/24 IP4.GATEWAY: 192.168.19.254 IP4.ROUTE[1]: dst = 0.0.0.0/0, nh = 192.168.19.254, mt = 100 IP4.ROUTE[2]: dst = 192.168.19.0/24, nh = 0.0.0.0, mt = 100 IP4.DNS[1]: 120.114.100.1 IP4.DNS[2]: 120.114.150.1 IP4.DOMAIN[1]: virtual.dic # 2. 來到實體機器 (HOST) ,觀察一下取得的 IP 是否為本機所提供的 # tail /var/log/messages Apr 16 14:15:25 120-114-142-27 dhcpd: DHCPDISCOVER from 52:54:00:c4:cb:62 via mybr0 Apr 16 14:15:26 120-114-142-27 dhcpd: DHCPOFFER on 192.168.19.1 to 52:54:00:c4:cb:62 via mybr0 Apr 16 14:15:27 120-114-142-27 dhcpd: DHCPREQUEST for 192.168.19.1 (192.168.19.254) from 52:54:00:c4:cb:62 via mybr0 Apr 16 14:15:27 120-114-142-27 dhcpd: DHCPACK on 192.168.19.1 to 52:54:00:c4:cb:62 via mybr0 # tail /var/lib/dhcpd/dhcpd.leases lease 192.168.19.1 { starts 2 2019/04/16 06:15:26; ends 2 2019/04/16 06:25:26; cltt 2 2019/04/16 06:15:26; binding state active; next binding state free; rewind binding state free; hardware ethernet 52:54:00:c4:cb:62; } # 2. 釋放之前安裝的軟體資料 (yum 的快取資料) # yum clean all # 3. 找出目前系統最大的容量目錄: # du -sm /* 100 /boot 35 /etc 1 /home 1 /root 1 /tmp 1068 /usr 562 /var
- 清理個人資料:如果這個 image 未來要開放給其他人使用,那麼你的個人帳號,
以及 root 的密碼,就得要重新處理!否則隨意釋出時,你的個人資料可能會有被竊取的問題喔!那麼我們就來將這個系統清理清理:
# 0. 先重新開機吧! # reboot # 1. 開始刪除系統上面的自己的帳號: # userdel -r your_account_name # 2. 開始修改 root 的密碼: # passwd # 3. 開始刪除登錄檔: # systemctl stop rsyslog # cd /var/log # rm -f audit/audit.log boot.log* btmp* cron* dmesg* firewalld lastlog maillog* messages* secure* spooler* tuned/tuned.log wtmp # systemctl start rsyslog # 4. 處理檔案系統的縮減,需要的步驟比較繁瑣,先是在 VM 的環境內: (如果你的 VM images 小於 2G,這個部份不用處理!) # fstrim -av # dd if=/dev/zero of=/tmp.img bs=1M # rm /tmp.img # dd if=/dev/zero of=/boot/tmp.img bs=1M # rm /boot/tmp.img # 5. 清除 root 自己的歷史命令 # history -c; history -w # 6. 關閉這個虛擬機器: # poweroff
- 設計基礎設定檔 demo.xml 以及基礎檔案 demo.img:
- 處理虛擬磁碟機的容量問題: (如果容量小於 2G,這個部份暫時不用處理!)
- 我們曾經處理過許多的資料,例如 yum 以及 docker 等等,因此這些資料會被紀錄在虛擬磁碟檔案中。
雖然我們在上面的步驟中,已經將這些東西通通刪除了!但是,檔案系統的抹除並沒有很詳細的將這些區塊設定為未被使用中,所以,
雖然檔案系統只用了 1.2G 左右,但是整個 VM 磁碟檔案卻大到 2.XG 了!而且並不會縮小。因為這樣,所以,上面我們進行的任務中,
就是將『所有空白的檔案系統位置,通通填上 0 』,這就是檔案系統歸零了。只是...如果磁碟檔案太大,那就很麻煩~
# 直接將原始的檔案重新轉化出令一個新檔案: # mv demo.img demo.img.raw # qemu-img convert -p -O qcow2 demo.img.raw demo.img (100.00/100%) # ll demo* -rw-r--r--. 1 root root 1404305408 4月 16 16:33 demo.img -rw-r--r--. 1 root root 40745238528 4月 16 16:30 demo.img.raw -rw-r--r--. 1 root root 2636 4月 16 09:06 demo.xml
- 現在,你可以將 demo.img.raw 刪除,只保留 demo.img 即可!未來就用這個 demo.img 來處理囉!
- 我們曾經處理過許多的資料,例如 yum 以及 docker 等等,因此這些資料會被紀錄在虛擬磁碟檔案中。
雖然我們在上面的步驟中,已經將這些東西通通刪除了!但是,檔案系統的抹除並沒有很詳細的將這些區塊設定為未被使用中,所以,
雖然檔案系統只用了 1.2G 左右,但是整個 VM 磁碟檔案卻大到 2.XG 了!而且並不會縮小。因為這樣,所以,上面我們進行的任務中,
就是將『所有空白的檔案系統位置,通通填上 0 』,這就是檔案系統歸零了。只是...如果磁碟檔案太大,那就很麻煩~
- 使用相同磁碟內容的新的 VM 生成方式:
- 如前所述,生成新的 VM 我們需要進行複製的兩個東西就是:
- 配置硬體的 XML 檔案
- 實際的虛擬機器磁碟映像檔。
- 磁碟映像檔剛剛已經處理妥當,目前你可以使用簡單複製的方式,直接建立這個虛擬磁碟即可:
# 建立一個名為 myok.img 的映像檔 # cd /vmdisk # cp demo.img myok.img # qemu-img info myok.img image: myok.img file format: qcow2 virtual size: 40G (42949672960 bytes) disk size: 1.3G cluster_size: 65536 Format specific information: compat: 1.1 lazy refcounts: false
- 至於新的 XML 檔案的建立,如果需要手動修改的話,一般你需要注意的項目有:
- name 名稱要修改
- memory 可能記憶體的容量你會做個變更
- cputune 可能 CPU 的配置個數會有不同
- image_name 一般來說,磁碟檔名當然不一樣
- NIC mac 網卡的卡號當然也要不一樣
- spice settings 使用 spice 連線的密碼與埠口也可能會需要做修改
- 如前所述,基本上,你可以直接使用複製的方法來處理 XML 檔案,然後再 vim *.xml 去修改需要處理的部份。
如果擔心某些地方忘記改了,那麼也能使用底下的方式來進行 xml 的複製:
# 透過 demo.xml 的協助,建立 myok.xml,需要使用到剛剛建立的 myok.img 檔案: # yum install libguestfs-tools-c # virt-clone --original-xml demo.xml --name myok --file /vmdisk/myok.img --preserve-data --print-xml > myok.xml
這個指令會幫你建置好所需要的 XML 檔案內容,唯一你需要額外手動修改的,大致上就是 spice 的埠口了。 如果想讓系統自動幫你隨機取用 spice port 的話,那就得要啟動虛擬機器之後,再以 netstat 去查看 qemu-kvm 啟用的 port number 即可。 當然,你也可以觀察實體機器的 /var/log/messages 裡面的 dhcp 紀錄,直接用 IP 連結上新的虛擬機器系統即可。 - 開始嘗試啟動這個 myok.xml ,並且使用 ssh 的方式連接到該系統上:
# 1. 先啟動這個 myok.xml 的虛擬機器: # virsh create myok.xml # netstat -tlunp | grep qemu tcp 0 0 0.0.0.0:5900 0.0.0.0:* LISTEN 17782/qemu-kvm # 2. 觀察實體機器的 messages 或 leasese 檔案,看看虛擬機器的 IP 為何? # tail -n 100 /var/log/messages | grep dhcpd Apr 17 14:07:48 120-114-142-27 dhcpd: DHCPDISCOVER from 52:54:00:fa:4b:3f via mybr0 Apr 17 14:07:49 120-114-142-27 dhcpd: DHCPOFFER on 192.168.19.1 to 52:54:00:fa:4b:3f via mybr0 Apr 17 14:07:49 120-114-142-27 dhcpd: DHCPREQUEST for 192.168.19.1 (192.168.19.254) from 52:54:00:fa:4b:3f via mybr0 Apr 17 14:07:49 120-114-142-27 dhcpd: DHCPACK on 192.168.19.1 to 52:54:00:fa:4b:3f via mybr0 # ip link show 33: mybr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000 link/ether fe:54:00:fa:4b:3f brd ff:ff:ff:ff:ff:ff 39: vnet0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master mybr0 state UNKNOWN mode DEFAULT group default qlen 1000 link/ether fe:54:00:fa:4b:3f brd ff:ff:ff:ff:ff:ff # 3. 就直接連線到 192.168.19.1 去瞧瞧: # ssh 192.168.19.1
- 如前所述,生成新的 VM 我們需要進行複製的兩個東西就是:
VM 的大量佈署 - 使用 backing file 機制
某些時候,例如我們上課用的 gocloud 系統,可能都需要用到大量的同性質虛擬機器, 這與一般企業用的角度不太一樣。同時,如果是同質性的測試系統時,大概也都是需要大量的相同虛擬機器。此時,似乎不必使用完整的複製, 因為測試完畢之後,通常虛擬機器就刪除了!那完整複製,似乎只是浪費磁碟容量而已。
解決方案也很單純,就是透過類似快照 (snapshot) 的功能來快速建立多個同質性的映像檔即可。
- 建立 backing file 的支援
其實,大量佈署重點就兩個,一個是 XML 的大量複製,再以所謂的 backing_file 大量的快速複製 image 而已!
- 大量複製原始磁碟的方法:
- 查詢 qemu-img 的功能,找到 create 裡面的 backing_file 參數
- 建立另外一個相同的 image,檔名則請隨意指定
# qemu-img create -f qcow2 -o backing_file=/vmdisk/demo.img check1.img # ll # qemu-img info check1.img
- 建立 XML 檔案的方式:
- 複製 xml 檔案,成為與目前 image 相同檔名的 xml 檔案
- 修改 xml 檔案內容,需要注意記憶體、name、MAC 等特徵參數,需要特別修改才行。建議還是可以使用 demo.xml 來產生即可。
- 若需要手動修改設定,可以使用底下的方式來隨機產生網卡卡號 (MAC)
# printf '52:54:00:%02X:%02X:%02X\n' $((RANDOM%256)) $((RANDOM%256)) $((RANDOM%256))
- 如果想要大量自動產生 image 以及 xml 檔案的話,也能參考一下底下的腳本來自動建立:
# vim create_vm_settings.sh #!/bin/bash vmnames="raw1 raw2" origdir="/vmdisk" snapdir="/vmdisk" xmldir="/vmdisk" oridisk="demo.img" orixml="demo.xml" oridisk="${origdir}/${oridisk}" orixml="${xmldir}/${orixml}" # 檢查容量 for filename in ${oridisk} ${orixml} do if [ ! -f ${filename} ]; then echo "Can not find the disk/xml filename: '${filename}'" exit 1 fi done for vm in ${vmnames} do echo "Try to create VM name '${vm}'" vmdisk=${snapdir}/${vm}.img vmxml=${xmldir}/${vm}.xml qemu-img create -f qcow2 -o backing_file=${oridisk} ${vmdisk} virt-clone --original-xml ${orixml} --name ${vm} --file ${vmdisk} --preserve-data --print-xml > ${vmxml} done
- 將上述的腳本建立起來,並根據你的系統配置,建立好 raw1 與 raw2 這兩個 VM !
- 完成 raw1 與 raw2 的建立後,請啟動這兩個 VM,並且嘗試連線進入這兩個 VM。連線成功後,並請將 VM 關閉。
- 大量複製原始磁碟的方法:
- 基本目標,將一個 snapshot 類型的映像檔啟用後,經過一些處理後, 將處理的資料回溯給 backing_file 本身。亦即修改了原始磁碟的意思。
- 因為會更動到原始磁碟,因此建議你的 snapshot 類型的映像檔,要重新變更一個 backing_file,
避免更動到其他人的 backing_file (例如你用 raw1 去復原了 demo.img,結果卻導致 raw2 無法繼續參考 demo.img 了!
這時其他呼叫到 demo.img 的快照磁碟,會失效的)。
# 1. 先複製 demo.img 成為 demo2.img # cp demo.img demo2.img # 2. 將 raw1.img 的 backing_file 重新指定到 demo2.img # qemu-img rebase -b demo2.img raw1.img # qemu-img info raw1.img qemu-img info raw1.img image: raw1.img file format: qcow2 virtual size: 40G (42949672960 bytes) disk size: 15M cluster_size: 65536 backing file: demo2.img <==仔細看這裡!變更了! Format specific information: compat: 1.1 lazy refcounts: false
- 現在開始啟動 raw1 系統,然後觀察登錄檔 (tail -f /var/log/messages) ,確認取得 IP 之後,
從遠端登入這個系統,開始進行一些特別的動作:
- 嘗試安裝圖形界面群組
- 嘗試安裝開發工具群組
- 嘗試將預設登入界面處理成為圖形界面登入
- 進行 yum clean all 釋放未使用的容量
- 關機。
- 現在開始進行磁碟 commit 的動作!去影響到原始磁碟!
# 1. 嘗試觀察原始磁碟與快照磁碟之間的容量與關係 # ll demo2.img raw1.img -rw-r--r--. 1 qemu qemu 1404305408 4月 17 16:36 demo2.img -rw-r--r--. 1 root root 4228513792 4月 17 21:24 raw1.img <==容量明顯大起來 # qemu-img info demo2.img image: demo2.img file format: qcow2 virtual size: 40G (42949672960 bytes) disk size: 1.3G <==容量沒有變化啊! cluster_size: 65536 Format specific information: compat: 1.1 lazy refcounts: false # qemu-img info raw1.img image: raw1.img file format: qcow2 virtual size: 40G (42949672960 bytes) disk size: 3.9G <==就是這裡!容量變好大! cluster_size: 65536 backing file: demo2.img Format specific information: compat: 1.1 lazy refcounts: false # 2. 開始以 raw1.img 的內容去更新 demo2.img 的內容: # qemu-img commit raw1.img Image committed. # ll demo2.img raw1.img -rw-r--r--. 1 qemu qemu 5398855680 4月 17 21:27 demo2.img <==換他容量變大了! -rw-r--r--. 1 root root 4228513792 4月 17 21:24 raw1.img # rm raw1.img # qemu-img create -f qcow2 -o backing_file=demo2.img raw1.img # qemu-img info raw1.img image: raw1.img file format: qcow2 virtual size: 40G (42949672960 bytes) disk size: 196K cluster_size: 65536 backing file: demo2.img Format specific information: compat: 1.1 lazy refcounts: false # virsh create raw1.xml # tail -f /var/log/messages Apr 17 21:33:42 120-114-142-27 dhcpd: DHCPDISCOVER from 52:54:00:ca:8c:9e via mybr0 Apr 17 21:33:43 120-114-142-27 dhcpd: DHCPOFFER on 192.168.19.1 to 52:54:00:ca:8c:9e via mybr0 Apr 17 21:33:43 120-114-142-27 dhcpd: DHCPREQUEST for 192.168.19.1 (192.168.19.254) from 52:54:00:ca:8c:9e via mybr0 Apr 17 21:33:43 120-114-142-27 dhcpd: DHCPACK on 192.168.19.1 to 52:54:00:ca:8c:9e via mybr0 # ssh 192.168.19.1 # systemctl get-default # history
最終你就可以發現到快照碟可以移除,並且產生新的快照碟~原始碟就可以提供給所有人使用了!相當快速方便!