Introduction#
The reason that this came about is because I wanted to create VM templates that had the Salt Minion pre-installed. I know a number of customers that don’t allow VMs to have outbound internet access. Their template build processes are not always restricted in the same way though. Also, it’s one less task to be completed when deploying from a template.
The challenge with pre-installing the Salt Minion, however, is that when the service starts it will automatically create a Minion ID. By default the Minion ID is the same as the hostname.
Guest Customization#
Guest customization is a task (or series of tasks) that is performed after the first boot of a VM that is deployed from a template. Such customization can be performed by a number of methods. Two of the most common are:
- Cloud-Init - This utility started life as part of the Ubuntu Linux distribution but is now available for most major operating systems.
- VM Tools - Using a guest customization specification stored in VMware vSphere, a unique hostname may be set using the customization functionality present in both VM Tools and Open VM Tools.
Both of these methods make changes to the cloned operating system during its first boot. However, if the Salt Minion service is started before customization is complete then the Minion ID may well be based on the hostname set in the template. By default you’d end up with every Minion ID being the same.
Minion IDs are not fixed, they can be changed if required. The automatic generation of the Minion ID only occurs if the Minion does not already have an ID though. What would be better is to try and make sure that the Minion service is not started immediately thus allowing for customization to be completed.
Service Timer#
Many services in the Linux OS are executed or managed by the systemd process. Each service is defined by a unit file that tells systemd what to execute, and how. Timers are like services in that they have a unit file, but they are used to determine when something executes. There are two types of timers:
- realtime - Like a calendar event, or in much the same way as a cronjob is scheduled.
- monotonic - These activate after a specified period of time from an event.
It is the latter that is of most interest here.
Timer unit files are usually named after the service that they relate to. This creates a relationship between the two. Therefore, if we create a timer definition for our Salt Minion service to start the Salt Minion two minutes after the OS boots then we can be fairly sure that any customization of the OS should have completed.
Salt-Minion Install Script#
When we install the Salt Minion a service defintiion is created automatically. It is not enabled though. By default then the Salt Minion is present but will not start automatically at boot. This is good, this is what we want.
What we then must create though is a timer unit file called salt-minion.timer
and populate it with content like this:
[Unit]
Description=Timer for the salt-minion service
[Timer]
OnBootSec=2min
[Install]
WantedBy=timers.target
The final step is to enable the timer (not the service). We could do that with the following command:
systemctl enable salt-minion.timer
Two minutes after the OS boots, the timer will start the Salt Minion service. By which time the customization should be complete and the Salt Minion will get an ID that matches its hostname.
If we wanted to combine the Salt Minion installation and timer configuration into a single script, then it could look something like this:
Summary#
The process that I’ve outlined above is one way to pre-install the Salt Minion inside a VM template and have it activate a specific time after the OS next boots. This is particularly useful when using tools such as Packer to build templates. In fact, the script above comes from my own Packer repository. Feel free to check it out!
Packer build repository