Salt Vagrant - automatically provision one master and two slaves
Configuration management let's you control hundreds of computers. You can even configure machines that don't exist yet!
In this article, you'll use ready-made network of three virtual computers to play with Salt, a popular configuration management system.
These notes have not been extensively tested yet.
Background & Prerequisites # ↑
I cleaned up this configuration from a setup I've used for a long time on Linux. You can probably adapt it to Windows, and I think some of my students have.
These notes are pretty dense. As prerequisite, you should know Linux command line and directory structure. Here, we prepare to administer a lot of computers. It would help if you could already administer one.
Install Virtualization Environment # ↑
$
$
$ ;
$
Copy-paste the ready-made Vagrantfile in place.
Ready made Vagrantfile for three computers # ↑
# -*- mode: ruby -*-
# vi: set ft=ruby :
# Copyright 2014-2023 Tero Karvinen http://TeroKarvinen.com
$minion = <<MINION
sudo apt-get update
sudo apt-get -qy install salt-minion
echo "master: 192.168.12.3">/etc/salt/minion
sudo service salt-minion restart
echo "See also: https://terokarvinen.com/2023/salt-vagrant/"
MINION
$master = <<MASTER
sudo apt-get update
sudo apt-get -qy install salt-master
echo "See also: https://terokarvinen.com/2023/salt-vagrant/"
MASTER
Vagrant.configure("2") do
config.vm.box = "debian/bullseye64"
config.vm.define "t001" do
t001.vm.provision :shell, inline: $minion
t001.vm.network "private_network", ip: "192.168.12.100"
t001.vm.hostname = "t001"
end
config.vm.define "t002" do
t002.vm.provision :shell, inline: $minion
t002.vm.network "private_network", ip: "192.168.12.102"
t002.vm.hostname = "t002"
end
config.vm.define "tmaster", primary: true do
tmaster.vm.provision :shell, inline: $master
tmaster.vm.network "private_network", ip: "192.168.12.3"
tmaster.vm.hostname = "tmaster"
end
end
Run Three Computers # ↑
$
It takes 3-5 minutes, and the three computers boot up. The slaves t001 and t002 will automatically contact master, because the slave daemon (salt-minion) was installed and configured with a three-line script in Vagrantfile.
Accept the Slaves # ↑
Log into your master computer.
$
The salt commands below are run inside the virtual machine tmaster. It's prompt is very long, so I've replaced it with "$". But it's a different computer from your host OS.
The slave computers have already sent their keys to master. Just approve them
$
The following keys are going to be accepted:
Unaccepted Keys:
t001
t002
Proceed? [n/Y] y
Key for minion t001 accepted.
Key for minion t002 accepted.
And test that the connection works. This command contacts slaves using the secured channel created by Salt.
$
t001:
True
t002:
True
Command Slaves # ↑
You can run regular shell commands
$
t001:
10.0.2.15 192.168.12.100
t002:
10.0.2.15 192.168.12.102
Collect Information # ↑
$
$
t002:
----------
ipv4:
- 10.0.2.15
- 127.0.0.1
- 192.168.12.102
osfinger:
Debian-11
t001:
----------
ipv4:
- 10.0.2.15
- 127.0.0.1
- 192.168.12.100
osfinger:
Debian-11
The Goal - Idempotent # ↑
Idempotent commands are much more powerful. They just describe the end state. Salt will only make changes if needed. These idempotent commands are the ones we'll mostly use later.
$
...
Succeeded: 1 (changed=1)
Failed: 0
If you run it many times, you'll see that it's really idempotent. In the following rounds, the "(changed=1)" will disappear.
To make success messages shorter, you can use --state-output=terse
$
Install some software
$
Make sure a daemon is running
$
Let's test that it's actually running
$
$ |
<title>Apache2 Debian Default Page: It works</title>
It works! So let's shut it down
$
$
curl: (7) Failed to connect to 192.168.12.102 port 80: Connection refused
We can control users
$
Modify users
$
And make sure they don't exist
$
If none of the others work, we can use cmd.run state. But we must make it idempotent ourselves.
$
You should prefer these to cmd.run: package, file, service, user.
Infra as Code - Your wishes as a text file # ↑
$
$
Write these contents to init.sls. Note that this syntax is YAML. Indentation matters, and its two spaces. No tabs.
$
/tmp/infra-as-code:
file.managed
$
top.sls - What Slave Runs What States # ↑
Top file defines what states are run for which slaves.
$
$
$
base:
'*':
- hello
Now you don't have to name any modules on state.apply:
$
Bye bye # ↑
We have cattle not pets. When it's time to say goodbye to this installation, you can destroy the machines and their contents. There is no undo.
$
$