Всем привет.
Уверен что вы с VirtualBox командную строку используете намного реже чем GUI. Но есть одна причина не пользоваться ни тем ни другим - это Vagrant. Vagrant этакая надстройка для виртуальных провайдеров 2-го уровня, которая позволяет автоматизировать многие повторяющиеся процессы по развертыванию виртуалок. Все описание процесса создания ВМ определенной конфигурации попадает в единый файл Vagrantfile. Полное его описание не последует в рамках данного поста, а последуют его фишки которые мне понравились от одного умного автора.
Например, чтобы сказать что:
- мы хотим развернуть виртуальную машину из образа, имя которого задается переменной окружения 'box_name',
- при этом следует проигнорировать Vagrantfile, включенный в состав этого образа как файл по умолчанию,
- машина в этом образе относится к классу Linux,
- по завершении запуска машины нужно вывести в консоль сообщение "Machine started".
Тогда следует в Vagrantfile написать так:
Vagrant.configure("2") do |config|
config.vm.box = ENV['box_name']
config.vm.ignore_box_vagrantfile = true
config.vm.guest = :linux
config.vm.post_up_message = "Machine started"
end
Можно создать отдельный раздел, определяющий какие ресурсы хостовой машины мы выделяем для гостевой машины. Делается это через доступ к свойствам отдельных провайдеров (гипервизоров), т.е обращаемся к свойствам VirtualBox:
config.vm.provider :virtualbox do |v, override|
v.gui = true # Display the VirtualBox GUI when booting the machine
v.customize ["modifyvm", :id, "--memory", ENV['ram_memory_size_mb']]
v.customize ["modifyvm", :id, "--cpus", ENV['cpu_count']]
v.customize ["modifyvm", :id, "--vram", 64] # Video memory 64 MB
end
где ram_memory_size_mb и cpu_count переменные окружения.
Однако кроме провайдеров существуют еще и провизионеры (поставщики). Поставщики добавляются вызовом метода config.vm.provision. В них мы определяем какие-то действия с уже запущенной виртуальной машиной и то, какой механизм и при каких условиях эти действия будет выполнять.
Пусть нам необходимы только два типа поставщиков, определяемых параметром type:
"file" - копирование файла с хостовой машины в виртуальную
"shell" - исполнение команды оболочки sh/bash.
Мы помним что Vagrantfile ипользуется при каждом запуске ВМ. Очевидно, что далеко не все команды, заданные в этом файле, имеет смысл выполнять при каждом запуске. Часть команд будет выполнять первоначальное конфигурирование при развертывании машины. Другая часть должна выполняться при каждом запуске. И управлять этим поведением позволяет параметр run. Можно задать его равным "once" и команды будут выполнены только при первом развертывании машины, а при последующих запусках будут проигнорированы. Например копировать файл настройки сети из хостовой машины в виртуальную достаточно только один раз в процессе ее развертывания:
config.vm.provision "Copying netplan configuration file to VM", type: "file", run: "once" do |f|
f.source = Dir.pwd + "/netplan_config.yaml"
f.destination = "~/netplan_config.yaml"
end
Можно задать параметр run равным "always" и тогда команда будет выполняться при каждом запуске виртуальной машины через команду vagrant up. Например при каждом запуске можно устанавливать одинаковое разрешение экрана:
config.vm.provision "Setting screen resilution via xrandr", type: "shell", run: "always" do |s|
s.inline = "xrandr -display :0.0 -s 1600x1200" # sleep 10 - waiting boot process to end and GUI to appear
s.privileged = false
end
Можно указать run "never" и тогда команды никогда не будут выполняться при запуске виртуальной машины через команду vagrant up. Тем не менее их можно будет явно вызвать командой vagrant provision --provision-with имя_блока_provision. Это очень удобная возможность для вывода диагностических сообщений. Например чтобы выполнить команду ps aux | grep "agent.jar" внутри виртуальной машины, но отобразить её вывод в консоли хостовой машины, из консоли хостовой машины достаточно будет выполнить команду vagrant provision --provision-with CheckJenkinsNode.
config.vm.provision "CheckJenkinsNode", type: "shell", run: "never" do |s|
$checkJenkinsAgentScript =<<-SCRIPT
sleep 30
echo "Output of ps aux | grep agent.jar must contain information about running jenkins agent."
echo "If there is no such information maybe Jenkins server is stopped. The output is below:"
ps aux | grep agent.jar
SCRIPT
s.inline = $checkJenkinsAgentScript
end
В Vagrantfile можно объявлять переменные. Например в целях отладки тип запуска большинства провизионеров можно задать в переменной $initRunType, а затем вместо констант "once", "never" или "always" использовать эту переменную. Таким образом можно быстро переключаться между выполнением команд только при первом запуске и выполнением команд при каждом запуске машины. Такой подход позволит упростить отладку Vagrantfile и выполняемых с помощью него действий:
$initRunType = "once"
#........
config.vm.provision "Copying netplan configuration file to VM", type: "file", run: $initRunType do |f|
f.source = Dir.pwd + "/netplan_config.yaml"
f.destination = "~/netplan_config.yaml"
end
Под финиш пример Vagrantfile-a который создает три однотипных ВМ VirtualBox и подбрасывает необходимые ssh-ключи. Он не очень оригинален, просто всплыл в моей памяти из одного полигона:
VAGRANT_DOTFILE_PATH = 'D:\VM';
Vagrant.configure("2") do |config|
(1..3).each do |i|
config.vm.define "server#{i}" do |web|
web.vm.box = "ubuntu/trusty64"
web.vm.network "public_network"
web.vm.network "forwarded_port", guest: 22, host: 2222+i, auto_correct: true
web.vm.hostname = "Server#{i}"
ssh_pub_key = File.readlines("#{Dir.home}/.ssh/id_rsa.pub").first.strip
$script = <<-'SCRIPT'
echo #{ssh_pub_key} >» /home/vagrant/.ssh/authorized_keys
echo #{ssh_pub_key} >» /root/.ssh/authorized_keys
SCRIPT
web.vm.provision "shell", inline: $script
web.vm.provider "virtualbox" do |v|
v.name = "server#{i}"
v.memory = 1024
v.cpus = 1
v.gui = false
end
end
end
end
Удачи.
Слава Украине!
No comments:
Post a Comment
А что вы думаете по этому поводу?