Tổng quan
KVM được biết đến là một cơ sở hạ tầng ảo hóa cho nhân Linux. KVM cũng cung cấp các mô hình mạng trong việc ảo hóa network. Các mô hình bao gồm:
- NAT
- Host-only
- Linux-bridge
Ở bài viết này mình sẽ giới thiệu về mô hình NAT trên KVM.
Chuẩn bị
Một máy chạy hệ điều hành CentOS 7 hoặc Ubuntu cài đặt KVM có một card mạng kết nối với internet và cài đặt một VM bên trong máy đó. Chú ý máy vật lý ở đây là máy cài KVM. Máy này có thể là một máy ảo nhưng ở đây ta coi nó như một server vật lý.
Nếu như với mô hình linux bridge KVM tạo ra một virtual switch thì ta cũng có thể hình dung với mô hình mạng NAT này KVM sẽ tạo ra một thiết bị là virtual router. Khi ta tạo một dải mạng với mô hình NAT thì lúc này virtual router sẽ NAT từ dải mạng mà ta tạo ra ra địa chỉ của card mạng vật lý trên KVM host để đi ra ngoài internet. Khi một dải mạng tạo ra ta sẽ thấy trên KVM host xuất hiện một thêm một card mạng. Card mạng này đóng vai trò là gateway cho dải mạng mà ta tạo ra.
Tạo mô hình NAT trên KVM
Để list tất cả các network đang có trong server, sử dụng lệnh virsh net-list –all. Bạn sẽ thấy có 1 network default mặc định khi cài KVM sẽ tự tạo ra.
$ virsh net-list --all
Name State Autostart Persistent
-------------------------------------------------------
default inactive no yes
Mình sẽ không sử dụng network default nên mình sẽ xoá nó đi bằng lệnh dưới.
virsh net-destroy default
virsh net-undefine default
Để thêm network mới, bạn sử dụng file xml dưới, hãy để ý một số trường như sau:
- mode=nat: sử dụng mode nat.
- bridge name=’virbr192′: đặt tên card mạng nat, sau khi thêm network thành công bạn sẽ thấy nó xuất hiện trong server kvm.
- nat-network-sub192 chính là tên của network bạn sẽ tạo.
echo """<network>
<name>nat-network-sub192</name>
<forward mode='nat'/>
<bridge name='virbr192' stp='on' delay='0'/>
<ip address='192.168.1.254' netmask='255.255.255.0'>
<dhcp>
<range start='192.168.1.1' end='192.168.1.253'/>
</dhcp>
</ip>
</network>""" > ./nat-network-sub192.xml
Sử dụng lệnh virsh net-define <file_network_xml> để define network này.
$ virsh net-define ./nat-network-sub192.xml
Network nat-network-sub192 defined from ./nat-network-sub192.xml
Dùng lệnh virsh net-list –all để list network, bạn đã thấy network có tên nat-network-sub192 đã xuất hiện nhưng nó đang ở trạng thái inactive. Ở trạng thái này network chưa thể sử dụng được.
$ virsh net-list --all
Name State Autostart Persistent
---------------------------------------------------------
nat-network-sub192 inactive no yes
Để enable network này, sử dụng lệnh virsh net-start <file_network_xml> để start nó.
$ virsh net-start nat-network-sub192
Network nat-network-sub192 started
Sau khi start network xong, bạn thấy network đã chuyển qua trạng thái active, tức là lúc này network đã có thể sử dụng được nhưng mà tuỳ chọn Autostart đang ở trạng thái no, bạn hãy chuyển tuỳ chọn Autostart sang yes để khi máy chủ KVM khởi động lại, network sẽ tự start luôn.
$ virsh net-list --all
Name State Autostart Persistent
-------------------------------------------------------
nat-network-sub192 active no yes
Sử dụng lệnh virsh net-autostart <file_network_xml> để enable tính năng này.
$ virsh net-autostart nat-network-sub192
Network nat-network-sub192 marked as autostarted
Và đây là kết quả khi mình đã config xong một network.
$ virsh net-list --all
Name State Autostart Persistent
-------------------------------------------------------
nat-network-sub192 active yes yes
Để xem thông tin tóm tắt một network bạn có thể sử dụng lệnh virsh net-info <file_network_xml>.
$ virsh net-info nat-network-sub192
Name: nat-network-sub192
UUID: 721f7226-d500-4751-9ba9-260d8bb28836
Active: yes
Persistent: yes
Autostart: yes
Bridge: virbr192
Khi bạn show interface bạn cũng thấy xuất hiện 1 interface mới có tên virbr192 và được gán sẵn ip gateway 192 192.168.1.254 và interface này sẽ đóng vai trò là gateway của nat-network-sub192.
$ ifconfig virbr192
virbr192: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 192.168.1.254 netmask 255.255.255.0 broadcast 192.168.1.255
ether 52:54:00:2a:22:9a txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
Kiểm tra.
Mình sẽ tạo 1 máy ảo có tên test-nat-network-sub192 để kiểm tra network này như sau. Đầu tiên tạo file sshkey cho username ubuntu.
sudo mkdir -p /kvm-volumes-hdd/test-nat-network-sub192/ssh-keygen
sudo chmod +x /kvm-volumes-hdd/test-nat-network-sub192
sudo chmod 600 /kvm-volumes-hdd/test-nat-network-sub192/ssh-keygen
cd /kvm-volumes-hdd/test-nat-network-sub192/ssh-keygen
ssh-keygen -t rsa -b 4096 -f id_rsa -C hoanghd -N "" -q
Tạo 1 ổ đĩa chứ hệ điều hành, mình tạo 1 ổ đĩa có dung lượng 10G.
qemu-img create -b /kvm-volumes-hdd/images/bionic-server-ubuntu1804-cloudimg-amd64.img -f qcow2 /kvm-volumes-hdd/test-nat-network-sub192/os-test-nat-network-sub192.qcow2 10G
Xem lại thông tin ổ đĩa vừa tạo.
$ qemu-img info /kvm-volumes-hdd/test-nat-network-sub192/os-test-nat-network-sub192.qcow2
image: /kvm-volumes-hdd/test-nat-network-sub192/os-test-nat-network-sub192.qcow2
file format: qcow2
virtual size: 10 GiB (10737418240 bytes)
disk size: 196 KiB
cluster_size: 65536
backing file: /kvm-volumes-hdd/images/bionic-server-ubuntu1804-cloudimg-amd64.img
Format specific information:
compat: 1.1
lazy refcounts: false
refcount bits: 16
corrupt: false
Tiếp theo bạn tạo file cloud_init.cfg khai báo 1 số thông tin cơ bản cho máy ảo.
cat > /kvm-volumes-hdd/test-nat-network-sub192/cloud_init.cfg << OEF
#cloud-config
hostname: test-nat-network-sub192
fqdn: test-nat-network-sub192.hoanghd.com
manage_etc_hosts: true
users:
- name: ubuntu
sudo: ALL=(ALL) NOPASSWD:ALL
groups: users, admin
home: /home/ubuntu
shell: /bin/bash
lock_passwd: true
ssh-authorized-keys:
- $(cat /kvm-volumes-hdd/test-nat-network-sub192/ssh-keygen/id_rsa.pub)
- name: hoanghd
sudo: ALL=(ALL) NOPASSWD:ALL
groups: users, admin
home: /home/hoanghd
shell: /bin/bash
lock_passwd: false
package_update: true
packages_upgrade: true
packages:
- qemu-guest-agent
- traceroute
# only cert auth via ssh (console access can still login)
ssh_pwauth: false
disable_root: false
chpasswd:
list: |
hoanghd:Hoanghd164
expire: False
runcmd:
- sudo touch /etc/cloud/cloud-init.disabled
OEF
Tạo file cấu hình network.
cat > /kvm-volumes-hdd/test-nat-network-sub192/network_config_static.cfg << 'OEF'
version: 2
ethernets:
enp1s0:
dhcp4: false
addresses: [ 192.168.1.1/24 ]
gateway4: 192.168.1.254
nameservers:
addresses: [ 1.1.1.1, 8.8.8.8 ]
OEF
Giờ mình tạo 1 disk mới có tên test-nat-network-sub192-seed.qcow2 và mình mount 2 file config cloud_init.cfg và network_config_static.cfg vào disk này. Mục đích để lúc khởi động kvm sẽ đọc ổ đĩa này để load các file config.
cloud-localds -v --network-config=/kvm-volumes-hdd/test-nat-network-sub192/network_config_static.cfg /kvm-volumes-hdd/test-nat-network-sub192/test-nat-network-sub192-seed.qcow2 /kvm-volumes-hdd/test-nat-network-sub192/cloud_init.cfg
Bạn có thể xem lại thông tin disk này bằng lệnh dưới.
$ qemu-img info /kvm-volumes-hdd/test-nat-network-sub192/test-nat-network-sub192-seed.qcow2
image: /kvm-volumes-hdd/test-nat-network-sub192/test-nat-network-sub192-seed.qcow2
file format: raw
virtual size: 368 KiB (376832 bytes)
disk size: 368 KiB
Bây giờ hãy run máy ảo bằng lệnh dưới.
virt-install --name test-nat-network-sub192 \
--virt-type kvm --memory 4096 --vcpus 4 \
--boot hd,menu=on \
--disk path=/kvm-volumes-hdd/test-nat-network-sub192/test-nat-network-sub192-seed.qcow2,device=cdrom \
--disk path=/kvm-volumes-hdd/test-nat-network-sub192/os-test-nat-network-sub192.qcow2,device=disk \
--graphics vnc \
--os-type Linux --os-variant ubuntu18.04 \
--network network:nat-network-sub192 \
--console pty,target_type=serial \
--noautoconsole
Nếu không gặp lỗi, bạn sẽ thấy đầu ra xuất hiện như dưới.
Starting install...
Domain creation completed.
Giờ hãy list VM chúng ta thấy VM vừa tạo đã ở trạng thái running
$ virsh list --all
Id Name State
-----------------------------------------
6 test-nat-network-sub192 running
Và đây là kết quả.
$ virsh console test-nat-network-sub192
Connected to domain test-nat-network-sub192
Escape character is ^]
Ubuntu 18.04.6 LTS test-nat-network-sub192 ttyS0
test-nat-network-sub192 login: hoanghd
Password:
Welcome to Ubuntu 18.04.6 LTS (GNU/Linux 4.15.0-197-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Sat Dec 10 12:42:02 UTC 2022
System load: 0.35 Processes: 138
Usage of /: 13.6% of 9.51GB Users logged in: 0
Memory usage: 4% IP address for enp1s0: 192.168.1.1
Swap usage: 0%
34 updates can be applied immediately.
32 of these updates are standard security updates.
To see these additional updates run: apt list --upgradable
The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.
hoanghd@test-nat-network-sub192:~$ ip a
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: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 52:54:00:2d:e8:47 brd ff:ff:ff:ff:ff:ff
inet 192.168.1.1/24 brd 192.168.1.255 scope global enp1s0
valid_lft forever preferred_lft forever
inet6 fe80::5054:ff:fe2d:e847/64 scope link
valid_lft forever preferred_lft forever
hoanghd@test-nat-network-sub192:~$ ip route
default via 192.168.1.254 dev enp1s0 proto static
192.168.1.0/24 dev enp1s0 proto kernel scope link src 192.168.1.1
hoanghd@test-nat-network-sub192:~$ ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=56 time=30.9 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=56 time=30.6 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=56 time=31.7 ms
64 bytes from 8.8.8.8: icmp_seq=4 ttl=56 time=30.3 ms
--- 8.8.8.8 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3005ms
rtt min/avg/max/mdev = 30.399/30.938/31.745/0.509 ms
hoanghd@test-nat-network-sub192:~$ traceroute 8.8.8.8
traceroute to 8.8.8.8 (8.8.8.8), 30 hops max, 60 byte packets
1 _gateway (192.168.1.254) 0.346 ms 0.296 ms 0.274 ms
2 192.168.12.5 (192.168.12.5) 4.188 ms 5.626 ms 4.159 ms
3 * * localhost (27.71.251.149) 6.904 ms
4 10.255.39.245 (10.255.39.245) 6.893 ms 10.255.39.247 (10.255.39.247) 6.856 ms 10.255.39.241 (10.255.39.241) 6.812 ms
5 localhost (27.68.209.197) 27.372 ms 27.174 ms localhost (27.68.210.34) 30.175 ms
6 localhost (27.68.255.94) 32.710 ms * localhost (27.68.255.86) 25.026 ms
7 localhost (27.68.233.246) 25.019 ms 26.969 ms localhost (27.68.233.242) 26.952 ms
8 * * localhost (27.68.229.1) 26.910 ms
9 dns.google (8.8.8.8) 33.358 ms 34.225 ms localhost (27.68.255.98) 25.236 ms