Главная

Monday, 25 April 2022

Vagrantfile features.


Всем привет.

Уверен что вы с 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

А что вы думаете по этому поводу?