Runners and orchestration#
Salt runners#
Salt runners are convenience applications executed with the salt-run
command.
Salt runners work similarly to Salt execution modules however they execute on the Salt master instead of the Salt minions.
A Salt runner can be a simple client call or a complex application. Figure 11.1 shows how a runner can be used to communicate with third-party applications and allow for passing data received from minions
Runners for reporting#
Runners are particularly good for returning reports about infrastructure. They can be used to execute a number of commands on minions, gather specific data and then output that data in a predictable way.
Runner examples#
Check the status of all known minion:
salt-run manage.status
down:
- town
- market
up:
- master01
- parascope
- awesomeweb1
- awesomeweb2
Runners are available to create clean lists of minions:
salt-run manage.down removekeys=True
The previous command will print a list of all unresponsive minions and remove their keys. This will work for targeting ‘*’ without worrying about minion timeouts due to down minions.
Bootstrap minions with salt-bootstrap script
# Use salt-bootstrap.sh
salt-run manage.bootstrap hosts='host1,host2'
# Use PsExec to bootstrap Windows minions
salt-run manage.bootstrap_psexec hosts='host1,host2'
installer_url='https://example.com/salt-installer.exe'
Jobs runner#
Since Salt executes jobs running on many systems, Salt needs to be able to manage jobs running on many systems.
The job management system is used to interact with active jobs, query active jobs, lookup executed jobs and kill running jobs.
Print a specific job’s detail given by its jid, including the return data.
salt-run jobs.print_job 20190502190314793312
Salt orchestration#
Salt provides the ability to orchestrate system administrative tasks throughout the enterprise.
Orchestration can be configured across physical and cloud environments.
Salt fulfills these tasks through orchestration states defined in SLS files that have a different structure than Salt state files.
The scope of defining the relationship of administrative tasks to orchestrate expansion from a single host to multiple systems.
The orchestration state runner#
The orchestration runner offers the following advantages:
Orchestration states can use the full suite of requisites.
Call execution modules and pass arguments as necessary.
Run states and highstates as well as using Salt Environments.
Execute other Salt runner modules.
Execute Salt states/functions using salt-ssh.
Executing Salt orchestration states#
Orchestration states execute on the Salt master using the state runner module.
Assuming a default Salt master configuration, the following commands are equivalent:
salt-run state.orchestrate orch.deploy-webapps
- or use the alias to orchestrate -
salt-run state.orch orch.deploy-webapps
The previous example assumes there is a subdirectory in the file_roots named orch
and contains an orchestration state file: deploy-webapps.sls
Orchestration state syntax#
Orchestration SLS files have a slightly different structure compared to state SLS files:
Orchestration states use mapped command interfaces:
salt.function: Calls remote execution modules on minions.
salt.state: Call states/highstates directly.
salt.runner: Call Salt runner modules on the Salt master.
salt.wheel: Call the Salt wheel interface for Salt minion key administration.
Orchestration states can call any combination of the above command interfaces. This means that an execution can be called, followed by a runner, and then apply highstate.
Orchestration states that use the salt.function
or salt.state
interface include an extra set of parameters to define targeting:
tgt: Targeting parameter for the function or state/highstate. This item can be any of the currently supported targeting types
tgt_type: If minion ID globbing is NOT used in the tgt parameter, then this option must define the supported targeting type used
Orchestration state structure#
An orchestration state will have the following structure:
# skeleton structure for "salt.function"
id_declaration_function:
salt.function:
- name: exec_module.function
- tgt: 'your-targets'
- tgt_type: 'type-of-targeting'
# skeleton structure for "salt.state"
id_declaration_states:
salt.state:
- tgt: 'your-targets'
- tgt_type: 'type-of-targeting'
- sls:
- path1.state1
- path1.state2
- path2.state1
id_declaration_highstate:
salt.state:
- tgt: 'your-targets'
- tgt_type: 'type-of-targeting'
- highstate: True
# skeleton structure for "salt.state"
id_declaration_runner:
salt.runner:
- name: runner_module.function
Orchestration examples#
Calling states and functions:
reconfig_load_balancers:
salt.state:
- tgt: 'proxy*'
- sls:
- haproxy-pool
extract_war:
salt.function:
- name: cmd.run
- tgt: 'javasrv01'
- arg:
- jar xf /opt/biz/myproject.war -C /opt/tomcat/webapps
- require:
- salt: reconfig_load_balancers
A more complex example. Consider the following individual cli commands:
salt \* state.apply core
salt -E '^(web|app).*' state.highstate
salt -G 'role:firewall' junos.ping
salt -G 'role:firewall' state.apply firewall.web_rules pillar='{"rule_group":"web_app"}'
salt-run http.query 'https://example.com/update/web_app' method=POST data='<xml>somedata</xml>'
A Salt orchestration state file could be defined to run these commands:
apply_core:
salt.state:
- tgt: '*'
- sls:
- core
web_highstate:
salt.state:
- tgt: '^(web|app).*'
- tgt_type: pcre
- highstate: True
- require:
- salt: apply_core
test_fw:
salt.function:
- name: junos.ping
- tgt: 'role:firewall'
- tgt_type: grain
deploy_web_rules:
salt.state:
- tgt: 'role:firewall'
- tgt_type: grain
- sls:
- firewall.web_rules
- pillar:
- rule_group: {{ pillar.get['rule_group'] }}
- require:
- salt: test_fw
- onchanges:
- salt: web_highstate
update_devops:
salt.runner:
- name: http.query
- arg:
- 'https://example.comf/update/web_app'
- kwarg:
method: POST
data: '<xml>somedata</xml>'
- require:
- salt: deploy_web_rules
To execute the orchestration state:
salt-run state.orch orch.deploy_web pillar='{"rule_group":"web_app"}'
Note
Notice we can also pass in Pillar data via the command line in order to pass along to executions as well as utilize the full set of requisites.
Another example to allow new minions to join to the Salt master and initiate a highstate:
{% set minion_id = salt['pillar.get']('minion_id', None) %}
{% if minion_id %}
minion_add:
salt.wheel:
- name: key.accept
- match: {{ minion_id }}
pause_flow:
salt.runner:
- name: test.sleep
- s_time: 5
- require:
- salt: minion_add
deploy_highstate:
salt.state:
- tgt: {{ minion_id }}
- highstate: True
- require:
- salt: minion_add
{% else %}
need_minion:
test.fail_without_changes:
- name: The required 'minion_id' value was not passed via Pillar
{% endif %}