Difference between revisions of "KVM"
From Blue-IT.org Wiki
(→Control NAT rules) |
(→Control NAT rules) |
||
Line 64: | Line 64: | ||
=== Control NAT rules === | === Control NAT rules === | ||
− | IpTables is what you want: | + | IpTables is what you want. But there are some pitfalls: |
− | + | # the prerouting rules, that enable a port forwarding into the nat'ed machine must be applied before (!) the virtual machine starts | |
− | + | # if you have a service installed like zentyal, or you are restarting your firewall, all rules are set back | |
+ | # libvirt nat-rules for the bridges are applied at service start time - this can interfere with other rules | ||
+ | # This is done by a quemu-hook script, called '''/etc/libvirt | ||
− | The POSTROUTING chains are set automatically by virt-manager and allow the virtual-machine accessing the internet from inside of the machine using NAT. | + | ==== An example ==== |
+ | The PREROUTING rules vor '''vm-1''' open up the ports 25, 587, 993 and 8080 for the NAT'ed virtual machine with the IP 192.168.122.2. So they are accessible from the outside world (webserver, e-mail-server, ...). This also means, that they can not be used any more in the host sytem (you should set the admin interface of e.g. zentyal to a different port). | ||
+ | |||
+ | he POSTROUTING chains are set automatically by virt-manager and allow the virtual-machine accessing the internet from inside of the machine using NAT. | ||
iptables -nvL -t nat | iptables -nvL -t nat | ||
Line 100: | Line 105: | ||
* ability to serve more than one guest | * ability to serve more than one guest | ||
* ... will be updated! | * ... will be updated! | ||
+ | |||
+ | Here it is: | ||
+ | > script="/etc/libvirt/hooks/qemu"; \ | ||
+ | touch $script; \ | ||
+ | chmod +x $script; \ | ||
+ | vim $script | ||
+ | |||
+ | #!/bin/bash | ||
+ | |||
+ | Guest_name="vm-webserver" | ||
+ | Guest_ipaddr=192.168.122.2 | ||
+ | Host_ports=" 80 443 8080 " | ||
+ | |||
+ | for Host_port in $Host_ports; | ||
+ | do | ||
+ | if [ $1 = $Guest_name ] | ||
+ | then | ||
+ | if [[ $2 = "stopped" || $2 = "reconnect" ]] | ||
+ | then | ||
+ | iptables -t nat -D PREROUTING -p tcp --dport $Host_port -j DNAT \ | ||
+ | --to $Guest_ipaddr:$Host_port | ||
+ | |||
+ | iptables -D FORWARD -d $Guest_ipaddr/32 -p tcp -m state --state NEW,RELATED,ESTABLISHED \ | ||
+ | -m tcp --dport $Host_port -j ACCEPT | ||
+ | |||
+ | #- allows port forwarding from localhost but | ||
+ | # only if you use the ip (e.g http://192.168.1.20:8888/) | ||
+ | iptables -t nat -D OUTPUT -p tcp -o lo --dport $Host_port -j DNAT \ | ||
+ | --to $Guest_ipaddr:$Host_port | ||
+ | |||
+ | fi | ||
+ | if [[ $2 = "start" || $2 = "reconnect" ]] | ||
+ | then | ||
+ | iptables -t nat -I PREROUTING -p tcp --dport $Host_port -j DNAT \ | ||
+ | --to $Guest_ipaddr:$Host_port | ||
+ | |||
+ | iptables -I FORWARD -d $Guest_ipaddr/32 -p tcp -m state --state NEW,RELATED,ESTABLISHED \ | ||
+ | -m tcp --dport $Host_port -j ACCEPT | ||
+ | |||
+ | #- allows port forwarding from localhost but | ||
+ | # only if you use the ip (e.g http://192.168.1.20:8888/) | ||
+ | iptables -t nat -I OUTPUT -p tcp -o lo --dport $Host_port -j DNAT \ | ||
+ | --to $Guest_ipaddr:$Host_port | ||
+ | |||
+ | fi | ||
+ | fi | ||
+ | done | ||
+ | |||
+ | Guest_name="vm-email" | ||
+ | Guest_ipaddr=192.168.123.2 | ||
+ | Host_ports=" 993 587 25 465 143 " | ||
+ | |||
+ | for Host_port in $Host_ports; | ||
+ | do | ||
+ | if [ $1 = $Guest_name ] | ||
+ | then | ||
+ | if [[ $2 = "stopped" || $2 = "reconnect" ]] | ||
+ | then | ||
+ | iptables -t nat -D PREROUTING -p tcp --dport $Host_port -j DNAT \ | ||
+ | --to $Guest_ipaddr:$Host_port | ||
+ | |||
+ | iptables -D FORWARD -d $Guest_ipaddr/32 -p tcp -m state --state NEW,RELATED,ESTABLISHED \ | ||
+ | -m tcp --dport $Host_port -j ACCEPT | ||
+ | |||
+ | #- allows port forwarding from localhost but | ||
+ | # only if you use the ip (e.g http://192.168.1.20:8888/) | ||
+ | iptables -t nat -D OUTPUT -p tcp -o lo --dport $Host_port -j DNAT \ | ||
+ | --to $Guest_ipaddr:$Host_port | ||
+ | |||
+ | fi | ||
+ | if [[ $2 = "start" || $2 = "reconnect" ]] | ||
+ | then | ||
+ | iptables -t nat -I PREROUTING -p tcp --dport $Host_port -j DNAT \ | ||
+ | --to $Guest_ipaddr:$Host_port | ||
+ | |||
+ | iptables -I FORWARD -d $Guest_ipaddr/32 -p tcp -m state --state NEW,RELATED,ESTABLISHED \ | ||
+ | -m tcp --dport $Host_port -j ACCEPT | ||
+ | |||
+ | #- allows port forwarding from localhost but | ||
+ | # only if you use the ip (e.g http://192.168.1.20:8888/) | ||
+ | iptables -t nat -I OUTPUT -p tcp -o lo --dport $Host_port -j DNAT \ | ||
+ | --to $Guest_ipaddr:$Host_port | ||
+ | |||
+ | fi | ||
+ | fi | ||
+ | done | ||
=== Delete NAT rules === | === Delete NAT rules === |
Revision as of 18:32, 31 October 2013
Contents
Using VirtualBox and KVM together
Using VirtualBox and KVM together at the same server at the same time is NOT possible!!!
Use VirtualBox
sudo service qemu-kvm stop sudo service vboxdrv start
OR use KVM
sudo service vboxdrv stop sudo service qemu-kvm start
Decide!
comand line foo
Show running machines
sudo apt-get install ubuntu-vm-builde virsh -c qemu:///system list
Show bridges
brctl show
Migration from VirtualBox to KVM
This boils down to
- having a lot of time
- having a lot of free harddisk space
- creating a clone of the vbox-machine with VBoxManage clonehd (this can take a looooong time!). Kloning is the easiest way of getting rid of snapshots of an existing virtual machine.
- converting the images from vdi to qcow-format with qemu-img convert
- creating and configuring a new kvm-guest
- adding some fou to NAT with a qemu-hook (see next section)
To clone an image - on the same machine - you have to STOP kvm and start vboxdr (see above). Also be aware, that the raw-images take up a lot of space!
# The conversion can take some time. Other virtual machines are not accessible in this time VBoxManage clonehd -format RAW myOldVM.vdi /home/vm-exports/myNewVM.raw 0%...
cd /home/vm-exports/ qemu-img convert -f raw myNewVM.raw -O qcow2 myNewVM.qcow
Cloning a Snapshot:
# for a snapshot do (not tested) cd /to/the/SnapShot/dir VBoxManage clonehd -format RAW "SNAPSHOT_UUID" /home/vm-exports/myNewVM.raw
Accessing services on KVM guests behind a NAT
This is done by editing a hook-script for quemu:
/etc/libvirt/hooks/qemu
I am referring to this article:
which ist mentioned in the libvirt wiki:
I installed the qemu-python script of the first article under ubuntu 12.04 LTS, which worked like expected.
So I can access a port in the virtualmachine-guest with the IP/Port of the host (!). From within the host, it is possible to reach the guest via it's real ip. I am using the virtio-Interface (performance).
Control NAT rules
IpTables is what you want. But there are some pitfalls:
- the prerouting rules, that enable a port forwarding into the nat'ed machine must be applied before (!) the virtual machine starts
- if you have a service installed like zentyal, or you are restarting your firewall, all rules are set back
- libvirt nat-rules for the bridges are applied at service start time - this can interfere with other rules
- This is done by a quemu-hook script, called /etc/libvirt
An example
The PREROUTING rules vor vm-1 open up the ports 25, 587, 993 and 8080 for the NAT'ed virtual machine with the IP 192.168.122.2. So they are accessible from the outside world (webserver, e-mail-server, ...). This also means, that they can not be used any more in the host sytem (you should set the admin interface of e.g. zentyal to a different port).
he POSTROUTING chains are set automatically by virt-manager and allow the virtual-machine accessing the internet from inside of the machine using NAT.
iptables -nvL -t nat
Then you should see something like the following.
root@myHost:# iptables -nvL -t nat Chain PREROUTING (policy ACCEPT 216 packets, 14658 bytes) pkts bytes target prot opt in out source destination 6 312 DNAT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:1222 to:192.168.122.2:80 2 120 DNAT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:1223 to:192.168.122.2:443 0 0 DNAT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:1444 to:192.168.122.2:8080 Chain INPUT (policy ACCEPT 14 packets, 2628 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 12 packets, 818 bytes) pkts bytes target prot opt in out source destination Chain POSTROUTING (policy ACCEPT 17 packets, 1048 bytes) pkts bytes target prot opt in out source destination 0 0 MASQUERADE tcp -- * * 192.168.122.0/24 !192.168.122.0/24 masq ports: 1024-65535 6 406 MASQUERADE udp -- * * 192.168.122.0/24 !192.168.122.0/24 masq ports: 1024-65535 0 0 MASQUERADE all -- * * 192.168.122.0/24 !192.168.122.0/24
A script from here is a little bit altered:
- Guest port same as host port
- ability to apply more than one port
- ability to serve more than one guest
- ... will be updated!
Here it is:
> script="/etc/libvirt/hooks/qemu"; \ touch $script; \ chmod +x $script; \ vim $script
#!/bin/bash Guest_name="vm-webserver" Guest_ipaddr=192.168.122.2 Host_ports=" 80 443 8080 " for Host_port in $Host_ports; do if [ $1 = $Guest_name ] then if | $2 = "reconnect" then iptables -t nat -D PREROUTING -p tcp --dport $Host_port -j DNAT \ --to $Guest_ipaddr:$Host_port iptables -D FORWARD -d $Guest_ipaddr/32 -p tcp -m state --state NEW,RELATED,ESTABLISHED \ -m tcp --dport $Host_port -j ACCEPT #- allows port forwarding from localhost but # only if you use the ip (e.g http://192.168.1.20:8888/) iptables -t nat -D OUTPUT -p tcp -o lo --dport $Host_port -j DNAT \ --to $Guest_ipaddr:$Host_port fi if | $2 = "reconnect" then iptables -t nat -I PREROUTING -p tcp --dport $Host_port -j DNAT \ --to $Guest_ipaddr:$Host_port iptables -I FORWARD -d $Guest_ipaddr/32 -p tcp -m state --state NEW,RELATED,ESTABLISHED \ -m tcp --dport $Host_port -j ACCEPT #- allows port forwarding from localhost but # only if you use the ip (e.g http://192.168.1.20:8888/) iptables -t nat -I OUTPUT -p tcp -o lo --dport $Host_port -j DNAT \ --to $Guest_ipaddr:$Host_port fi fi done Guest_name="vm-email" Guest_ipaddr=192.168.123.2 Host_ports=" 993 587 25 465 143 " for Host_port in $Host_ports; do if [ $1 = $Guest_name ] then if | $2 = "reconnect" then iptables -t nat -D PREROUTING -p tcp --dport $Host_port -j DNAT \ --to $Guest_ipaddr:$Host_port iptables -D FORWARD -d $Guest_ipaddr/32 -p tcp -m state --state NEW,RELATED,ESTABLISHED \ -m tcp --dport $Host_port -j ACCEPT #- allows port forwarding from localhost but # only if you use the ip (e.g http://192.168.1.20:8888/) iptables -t nat -D OUTPUT -p tcp -o lo --dport $Host_port -j DNAT \ --to $Guest_ipaddr:$Host_port fi if | $2 = "reconnect" then iptables -t nat -I PREROUTING -p tcp --dport $Host_port -j DNAT \ --to $Guest_ipaddr:$Host_port iptables -I FORWARD -d $Guest_ipaddr/32 -p tcp -m state --state NEW,RELATED,ESTABLISHED \ -m tcp --dport $Host_port -j ACCEPT #- allows port forwarding from localhost but # only if you use the ip (e.g http://192.168.1.20:8888/) iptables -t nat -I OUTPUT -p tcp -o lo --dport $Host_port -j DNAT \ --to $Guest_ipaddr:$Host_port fi fi done
Delete NAT rules
iptables -t nat -D PREROUTING 1
Where "1" is the first PREROUTING rule that appears with the above command.
In the above example the first line is the PREROUTING chain with the number "6" and the port 80. This is the FIRST rule.
Autostart at boot time
Set the 'autostart' flag so the domain is started upon boot time:
virsh autostart myMachine
Shutdown
On Ubuntu 12.04 LTS (Precise Pangolin) the shutdown scripts already take care of stopping the virtual machines (at least in the newest version of the libvirt-bin package). However, by default the script will only wait 30 seconds for the VMs to shutdown. Depending on the services running in the VM, this can be too short.
In this case, you have to create a file /etc/init/libvirt-bin.override with the following content:
> vim /etc/init/libvirt-bin.override # extend wait time for vms to shut down to 4 minutes env libvirtd_shutdown_timeout=240
Backup KVM
Via LVM
- http://pof.eslack.org/2010/12/23/best-solution-to-fully-backup-kvm-virtual-machines
- http://sandilands.info/sgordon/automatic-backup-of-running-kvm-virtual-machines
LiveBackup (under development - --Apos (talk) 18:07, 30 October 2013 (CET))