YAML language
YAML is an intuitive data serialization format that can be recognized by computer. It is a programming language with high readability, easy to be read by human beings, easy to interact with scripting language and used to express data sequences.
It is similar to the data description language of XML, a subset of the standard general markup language, and its syntax is much simpler than XML.
The format of YAML language is as follows:
house: family: name: Doe parents: - John - Jane children: - Paul - Mark - Simone address: number: 34 street: Main Street city: Nowheretown zipcode: 12345
Basic rules of YAML:
Indent is used to represent the hierarchical relationship. There are 2 spaces in each layer. The TAB key is prohibited
When the colon is not at the end, there must be a space after the colon
Use - to represent the list, and there must be a space after -
Use # to indicate comments
The YAML configuration file should be placed in the location of SaltStack. You can find the file in the Master configuration file of SaltStack_ You can see it from the roots.
[root@master salt]# pwd /etc/salt [root@master salt]# vim master 681 file_roots: 682 base: 683 - /srv/salt/base 684 test: 685 - /srv/salt/test 686 dev: 687 - /srv/salt/dev 688 prod: 689 - /srv/salt/prod [root@master ~]# mkdir -p /srv/salt/{base,test,dev,prod} [root@master base]# systemctl restart salt-master.service [root@master base]# systemctl restart salt-minion.service
Note:
Base is the default location, if file_ If there is only one root, base is required and must be called base, and cannot be renamed
Configuring an apache instance using SaltStack
Deploy the sls configuration file on the Master and execute
[root@master base]# pwd /srv/salt/base [root@master base]# mkdir -p web/apache [root@master apache]# pwd /srv/salt/base/web/apache [root@master apache]# touch apache.sls / / a status description file is generated [root@master apache]# vim apache.sls apache-install: pkg.installed: - name: httpd apache-service: service.running: - name: httpd - enable: True // The top grid in YAML configuration file is called ID, which must be globally unique and cannot be repeated // SaltStack reads YAML configuration files from top to bottom, so write the first execution in front Use before executing the status file test.ping Test whether the host that needs to execute the status file can communicate normally, and then execute the status file. [root@master salt]# salt 'minion01' test.ping minion01: True //Execution status description file [root@master ~]# salt 'minion01' state.sls web.apache.apache saltenv=base minion01: ---------- ID: apache-install Function: pkg.installed Name: httpd Result: True Comment: The following packages were installed/updated: httpd Started: 08:42:04.287654 Duration: 18111.181 ms Changes: ---------- apr: ---------- new: 1.6.3-9.el8 old: apr-util: ---------- new: 1.6.1-6.el8 old: apr-util-bdb: ---------- new: 1.6.1-6.el8 old: apr-util-openssl: ---------- new: 1.6.1-6.el8 old: httpd: ---------- new: 2.4.37-21.module+el8.2.0+5008+cca404a3 old: httpd-filesystem: ---------- new: 2.4.37-21.module+el8.2.0+5008+cca404a3 old: httpd-tools: ---------- new: 2.4.37-21.module+el8.2.0+5008+cca404a3 old: mailcap: ---------- new: 2.1.48-3.el8 old: mod_http2: ---------- new: 1.11.3-3.module+el8.2.0+4377+dc421495 old: redhat-logos-httpd: ---------- new: 81.1-1.el8 old: ---------- ID: apache-service Function: service.running Name: httpd Result: True Comment: Service httpd has been enabled, and is running Started: 08:42:22.458329 Duration: 758.569 ms Changes: ---------- httpd: True Summary for minion01 ------------ Succeeded: 2 (changed=2) Failed: 0 ------------ Total states run: 2 Total run time: 18.870 s stay minion Upper inspection apache State of [root@minion01 salt]# systemctl status httpd ● httpd.service - The Apache HTTP Server Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: d> Active: active (running) since Tue 2021-11-03 08:42:22 CST; 40min ago Docs: man:httpd.service(8) Main PID: 111233 (httpd)
Configuring nginx instances on minion02 using SaltStack
Deploy the sls configuration file on the Master and execute
[root@master web]# pwd /srv/salt/base/web [root@master web]# mkdir nginx [root@master nginx]# pwd /srv/salt/base/web/nginx [root@master nginx]# vim nginx.sls nginx-install: pkg.installed: - name: nginx nginx-service: service.running: - name: nginx - enable: true [root@master base]# salt 'minion02' state.sls web.nginx.nginx saltenv=base minion02: ---------- ID: nginx-install Function: pkg.installed Name: nginx Result: True Comment: The following packages were installed/updated: nginx Started: 09:36:09.485277 Duration: 11087.069 ms Changes: ---------- centos-indexhtml: ---------- new: 7-9.el7.centos old: gperftools-libs: ---------- new: 2.6.1-1.el7 old: nginx: ---------- new: 1:1.20.1-9.el7 old: nginx-filesystem: ---------- new: 1:1.20.1-9.el7 old: openssl11-libs: ---------- new: 1:1.1.1g-3.el7 old: ---------- ID: nginx-service Function: service.running Name: nginx Result: True Comment: Service nginx has been enabled, and is running Started: 09:36:20.603264 Duration: 192.469 ms Changes: ---------- nginx: True Summary for minion02 ------------ Succeeded: 2 (changed=2) Failed: 0 ------------ Total states run: 2 Total run time: 11.280 s //Check on minion02 [root@minion02 ~]# systemctl status nginx.service ● nginx.service - The nginx HTTP and reverse proxy server Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled) Active: active (running) since II. 2021-11-03 09:36:20 CST; 1min 19s ago Main PID: 20747 (nginx)
top file introduction
Is it automatic enough to execute sls files directly through commands? The answer is no, because we have to tell a host to perform a task. Automation should be that when we let it work, it knows which host to do. However, executing sls files directly through commands can not achieve this purpose. In order to solve this problem, top file came into being.
Top file is an entry. The file name of top file can be found by searching top.sls in the Master configuration file, and this file must be in the base environment. By default, this file must be called top.sls.
The function of top file is to tell the corresponding host what to do, such as enabling the web server to start web services, enabling the database server to install mysql, and so on.
case
[root@master base]# pwd /srv/salt/base [root@master base]# touch top.sls [root@master base]# vim top.sls base: //Environment to execute the status file 'minion01': //Target to execute status file - web.apache.apache //Status file to execute //Stop the httpd service on minion01 and test it [root@minion01 salt]# systemctl stop httpd.service [root@master base]# salt 'minion01' state.highstate / / execute using advanced state minion01: ---------- ID: apache-install Function: pkg.installed Name: httpd Result: True Comment: All specified packages are already installed Started: 10:31:02.863779 Duration: 713.364 ms Changes: ---------- ID: apache-service Function: service.running Name: httpd Result: True Comment: Service httpd is already enabled, and is running Started: 10:31:03.580843 Duration: 362.207 ms Changes: ---------- httpd: True Summary for minion01 ------------ Succeeded: 2 (changed=1) Failed: 0 ------------ Total states run: 2 Total run time: 1.076 s //Let's look at the httpd status of minion [root@minion01 ~]# systemctl status httpd ● httpd.service - The Apache HTTP Server Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor p> Active: active (running) since Tue 2021-11-03 10:31:03 CST; 1h 6min ago Docs: man:httpd.service(8) Main PID: 201195 (httpd)
Use top file to manage nginx on minion02
[root@master base]# pwd /srv/salt/base [root@master base]# vim top.sls base: 'minion02': - web.nginx.nginx [root@minion02 ~]# systemctl stop nginx.service [root@master base]# salt 'minion02' state.highstate minion02: ---------- ID: nginx-install Function: pkg.installed Name: nginx Result: True Comment: All specified packages are already installed Started: 10:46:06.330211 Duration: 631.054 ms Changes: ---------- ID: nginx-service Function: service.running Name: nginx Result: True [root@master base]# salt 'minion02' state.highstate minion02: ---------- ID: nginx-install Function: pkg.installed Name: nginx Result: True Comment: All specified packages are already installed Started: 18:46:38.797394 Duration: 626.71 ms Changes: ---------- ID: nginx-service Function: service.running Name: nginx Result: True Comment: Service nginx is already enabled, and is running Started: 10:46:39.426389 Duration: 115.327 ms Changes: ---------- nginx: True Summary for minion02 ------------ Succeeded: 2 (changed=1) Failed: 0 ------------ Total states run: 2 Total run time: 742.037 ms [root@minion02 ~]# systemctl status nginx.service ● nginx.service - The nginx HTTP and reverse proxy server Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled) Active: active (running) since II. 2021-11-03 10:46:39 CST; 22s ago
Manage minion01 and 02 at the same time
[root@minion01 ~]# systemctl status httpd [root@minion02 ~]# systemctl stop nginx.service [root@master base]# salt '*' state.highstate [root@master base]# salt '*' state.highstate minion02: ---------- ID: nginx-install Function: pkg.installed Name: nginx Result: True Comment: All specified packages are already installed Started: 10:49:51.691119 Duration: 828.843 ms Changes: ---------- ID: nginx-service Function: service.running Name: nginx Result: True Comment: Service nginx is already enabled, and is running Started: 10:49:52.523394 Duration: 179.223 ms Changes: ---------- nginx: True Summary for minion02 ------------ Succeeded: 2 (changed=1) Failed: 0 ------------ Total states run: 2 Total run time: 1.008 s minion01: ---------- ID: apache-install Function: pkg.installed Name: httpd Result: True Comment: All specified packages are already installed Started: 10:49:50.300689 Duration: 625.583 ms Changes: ---------- ID: apache-service Function: service.running Name: httpd Result: True Comment: Service httpd is already enabled, and is running Started: 10:49:50.928605 Duration: 315.648 ms Changes: ---------- httpd: True Summary for minion01 ------------ Succeeded: 2 (changed=1) Failed: 0 ------------ Total states run: 2 Total run time: 941.231 ms [root@minion01 ~]# systemctl status httpd ● httpd.service - The Apache HTTP Server Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: d> Active: active (running) since Tue 2021-11-03 10:49:51 CST; 33s ago [root@minion02 ~]# systemctl status nginx.service ● nginx.service - The nginx HTTP and reverse proxy server Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled) Active: active (running) since II. 2021-11-03 10:49:52 CST; 49s ago
Note: if the target in the top file is represented by, it should be noted that the target in the top file represents all the targets to be executed, while the target in salt '' state.highstate tells all machines to work, and whether to work is specified by the top file
Use of advanced state highstate
When managing SaltStack, the most common management operation is to perform advanced status.
[root@master salt]# salt '*' state.highstate / / do not use this operation in the production environment
Note: the above allows everyone to execute the advanced status, but it is generally not used in actual work. In work, it is generally to notify one or some target hosts to execute the advanced status. The specific execution is determined by the top file.
If you add the parameter test=True when executing the advanced state, it will tell us what it will do, but it will not really perform this operation.
Stop minion Upper httpd service [root@minion01 ~]# systemctl stop httpd stay master Perform advanced state tests on [root@master salt]# salt 'minion01' state.highstate test=true minion01: ---------- ID: apache-install Function: pkg.installed Name: httpd Result: True Comment: All specified packages are already installed Started: 09:54:34.099749 Duration: 540.741 ms Changes: ---------- ID: apache-service Function: service.running Name: httpd Result: None Comment: Service httpd is set to start Started: 09:54:34.642736 Duration: 60.081 ms Changes: Summary for minion01 ------------ Succeeded: 2 (unchanged=1) Failed: 0 ------------ Total states run: 2 Total run time: 600.822 ms [root@minion01 ~]# systemctl status httpd ● httpd.service - The Apache HTTP Server Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: dis> Active: inactive (dead) since Tue 2021-11-03 09:52:46 CST; 3min 15s ago Docs: man:httpd.service(8) //It can be seen that httpd did not, indicating that the high-level commands were not executed
SaltStack data system
SaltStack has two major data systems:
Grains
Pillar
Differences between Grains and Pillar
data system | Storage location | type | Acquisition mode | Application scenario |
---|---|---|---|---|
Grains | minion | static state | Collect when minion starts; You can avoid restarting the minion service by refreshing | For information query, target matching is performed on the command line, target matching is performed on the top file, and target matching is performed on the template |
Pillar | master | dynamic | Specify and take effect in real time | Target matching sensitive data configuration |
Grains of SaltStack component
Grains is a component of saltstack, which stores the information collected when minion starts.
Grains is one of the most important components of saltstack component, because we often use it in the process of configuration and deployment. Grains is a component of saltstack that records some static information of minion. It can be simply understood that grains records some common attributes of each minion, such as CPU, memory, disk, network information, etc. We can view all grains information of a minion through grains.items.
Functions of Grains:
Collect asset information
Grains application scenario:
Information Service
Target matching at the command line
Target matching in top file
Target matching in template
For target matching in the template, see
https://docs.saltproject.io/en/latest/topics/pillar/
Information query column:
list minion01 All grains of key and value value [root@master base]# salt 'minion01' grains.items minion01: ---------- biosreleasedate: //bios time 02/27/2020 biosversion: //Version of bios 6.00 cpu_flags: //cpu related properties - fpu - vme - de - pse - tsc - msr - pae - mce - cx8 - apic - sep - mtrr - pge - mca - cmov - pat - pse36 - clflush - mmx - fxsr - sse - sse2 - ht - syscall - nx - mmxext - fxsr_opt - pdpe1gb - rdtscp - lm - constant_tsc - rep_good - nopl - tsc_reliable - nonstop_tsc - cpuid - extd_apicid - pni - pclmulqdq - ssse3 - fma - cx16 - sse4_1 - sse4_2 - x2apic - movbe - popcnt - aes - xsave - avx - f16c - rdrand - hypervisor - lahf_lm - cmp_legacy - svm - extapic - cr8_legacy - abm - sse4a - misalignsse - 3dnowprefetch - osvw - perfctr_core - ssbd - ibpb - vmmcall - fsgsbase - bmi1 - avx2 - smep - bmi2 - rdseed - adx - smap - clflushopt - sha_ni - xsaveopt - xsavec - xsaves - clzero - arat - npt - svm_lock - nrip_save - vmcb_clean - flushbyasid - decodeassists - overflow_recov - succor cpu_model: //Specific model of cpu AMD Ryzen 5 3500U with Radeon Vega Mobile Gfx cpuarch: //cpu architecture x86_64 cwd: / disks: - sr0 dns: ---------- domain: ip4_nameservers: - 192.168.71.2 ip6_nameservers: nameservers: - 192.168.71.2 options: search: sortlist: domain: efi: False efi-secure-boot: False fqdn: minion01 fqdn_ip4: //ip address - 192.168.71.140 fqdn_ip6: - fe80::20c:29ff:fef4:b4a9 fqdns: - minion01 gid: 0 gpus: |_ ---------- model: SVGA II Adapter vendor: vmware groupname: root host: //host name minion01 hwaddr_interfaces: ---------- ens160: 00:0c:29:f4:b4:a9 lo: 00:00:00:00:00:00 id: //ID of minion minion01 init: systemd ip4_gw: 192.168.71.2 ip4_interfaces: ---------- ens160: - 192.168.71.140 lo: - 127.0.0.1 ip6_gw: False ip6_interfaces: ---------- ens160: - fe80::20c:29ff:fef4:b4a9 lo: - ::1 ip_gw: True ip_interfaces: ---------- ens160: - 192.168.71.140 - fe80::20c:29ff:fef4:b4a9 lo: - 127.0.0.1 - ::1 ipv4: - 127.0.0.1 - 192.168.71.140 ipv6: - ::1 - fe80::20c:29ff:fef4:b4a9 kernel: Linux kernelparams: |_ - BOOT_IMAGE - (hd0,msdos1)/vmlinuz-4.18.0-193.el8.x86_64 |_ - root - /dev/mapper/rhel-root |_ - ro - None |_ - crashkernel - auto |_ - resume - /dev/mapper/rhel-swap |_ - rd.lvm.lv - rhel/root |_ - rd.lvm.lv - rhel/swap |_ - rhgb - None |_ - quiet - None kernelrelease: 4.18.0-193.el8.x86_64 kernelversion: #1 SMP Fri Mar 27 21:35:58 UTC 2020 locale_info: ---------- defaultencoding: UTF-8 defaultlanguage: zh_CN detectedencoding: UTF-8 timezone: CST localhost: minion01 lsb_distrib_codename: Red Hat Enterprise Linux 8.2 (Ootpa) lsb_distrib_id: Red Hat Enterprise Linux lsb_distrib_release: 8.2 lvm: ---------- rhel: - home - root - swap machine_id: b8032364c46f4fadaefd58290347f0eb manufacturer: VMware, Inc. master: 192.168.71.134 mdadm: mem_total: 1800 nodename: minion01 num_cpus: 2 num_gpus: 1 os: RedHat os_family: RedHat osarch: x86_64 oscodename: Ootpa osfinger: Red Hat Enterprise Linux-8 osfullname: Red Hat Enterprise Linux osmajorrelease: 8 osrelease: 8.2 osrelease_info: - 8 - 2 path: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin pid: 49239 productname: VMware Virtual Platform ps: ps -efHww pythonexecutable: /usr/bin/python3.6 pythonpath: - /usr/bin - /usr/lib64/python36.zip - /usr/lib64/python3.6 - /usr/lib64/python3.6/lib-dynload - /usr/lib64/python3.6/site-packages - /usr/lib/python3.6/site-packages pythonversion: - 3 - 6 - 8 - final - 0 saltpath: /usr/lib/python3.6/site-packages/salt saltversion: 3004 saltversioninfo: - 3004 selinux: ---------- enabled: False enforced: Disabled serialnumber: VMware-56 4d af 2f 62 90 b5 d0-b0 1b e2 f8 e8 f4 b4 a9 server_id: 1293882994 shell: /bin/sh ssds: - nvme0n1 swap_total: 2091 systemd: ---------- features: +PAM +AUDIT +SELINUX +IMA -APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD +IDN2 -IDN +PCRE2 default-hierarchy=legacy version: 239 systempath: - /usr/local/sbin - /usr/local/bin - /usr/sbin - /usr/bin transactional: False uid: 0 username: root uuid: 2faf4d56-9062-d0b5-b01b-e2f8e8f4b4a9 virtual: VMware zfs_feature_flags: False zfs_support: False zmqversion: 4.3.4
Only query the key s of all grains
[root@master base]# salt 'minion01' grains.ls minion01: - biosreleasedate - biosversion - cpu_flags - cpu_model - cpuarch - cwd - disks - dns - domain - efi - efi-secure-boot - fqdn - fqdn_ip4 - fqdn_ip6 - fqdns - gid - gpus - groupname - host - hwaddr_interfaces - id - init - ip4_gw - ip4_interfaces - ip6_gw - ip6_interfaces - ip_gw - ip_interfaces - ipv4 - ipv6 - kernel - kernelparams - kernelrelease - kernelversion - locale_info - localhost - lsb_distrib_codename - lsb_distrib_id - lsb_distrib_release - lvm - machine_id - manufacturer - master - mdadm - mem_total - nodename - num_cpus - num_gpus - os - os_family - osarch - oscodename - osfinger - osfullname - osmajorrelease - osrelease - osrelease_info - path - pid - productname - ps - pythonexecutable - pythonpath - pythonversion - saltpath - saltversion - saltversioninfo - selinux - serialnumber - server_id - shell - ssds - swap_total - systemd - systempath - transactional - uid - username - uuid - virtual - zfs_feature_flags - zfs_support - zmqversion
Query the value of a key, such as the ip address
[root@master base]# salt 'minion01' grains.get fqdn_ip4 minion01: - 192.168.71.140 [root@master base]# salt 'minion02' grains.get fqdn_ip4 minion02: - 192.168.71.135 //Get a host mac address [root@master base]# salt 'minion01' grains.get hwaddr_interfaces minion01: ---------- ens160: 00:0c:29:f4:b4:a9 lo: 00:00:00:00:00:00 [root@master base]# salt '*' grains.get ip4_interfaces minion01: ---------- ens160: - 192.168.71.140 lo: - 127.0.0.1 minion02: ---------- ens33: - 192.168.71.135 lo: - 127.0.0.1 [root@master base]# salt 'minion01' grains.get hwaddr_interfaces:ens160 minion01: 00:0c:29:f4:b4:a9
Target matching instance:
Match minion with Grains:
At all centos Execute commands in the system [root@master base]# salt -G 'os:CentOS' test.ping minion02: True //Use Grains in the top file: [root@master base]# pwd /srv/salt/base [root@master base]# vim top.sls base: 'os:CentOS': //Indicates that all centos systems will execute the state to be reached - match: grain - web.nginx.nginx [root@master base]# salt -G 'os:CentOS' state.highstate [root@minion02 ~]# systemctl stop nginx.service [root@minion02 ~]# systemctl status nginx.service ● nginx.service - The nginx HTTP and reverse proxy server Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled) Active: active (running) since II. 2021-11-03 11:14:54 CST; 9s ago
There are two ways to customize Grains:
minion configuration file, search for grains in the configuration file
Generate a grains file under / etc/salt and define it in this file (recommended method)
Remember to restart the service because minion Only the contents before restart will be read, because we are minion It is written in the open state, so it needs to be restarted minion The service makes its reading effective [root@minion01 ~]# vim /etc/salt/grains system: linux version: redhat [root@minion01 ~]# systemctl restart salt-minion.service [root@master base]# salt 'minion01' grains.items swap_total: 2091 system: linux version: redhat virtual: If you do not want to restart, you can also use the following method [root@minion01 ~]# vim /etc/salt/grains age: 18 [root@master base]# salt 'minion01' saltutil.sync_grains minion01: [root@master base]# salt 'minion01' grains.get age minion01: 18
Pillar of SaltStack component
Pillar is also one of the most important components in the SaltStack component. It is the data management center. It is often used to configure states in large-scale configuration management. Pillar's main role in SaltStack is to store and define some data required in configuration management, such as software version number, user name, password and other information. Its definition storage format is similar to Grains, which is YAML Format.
There is a section of Pillar settings in the Master configuration file, which specifically defines some parameters related to Pillar:
#pillar_roots: # base: # - /srv/pillar
By default, the working directory of Pillar in the Base environment is under the / srv/pillar directory. If you want to define multiple Pillar working directories in different environments, you only need to modify the configuration file here.
Pillar features:
You can define the data required for the specified minion
Only the specified person can see the defined data
Set in master configuration file
//View pillar information [root@master base]# salt '*' pillar.items minion02: ---------- minion01: ----------
The default pillar does not have any information. If you want to view the information, you need to set the pillar in the master configuration file_ The annotation of opts is uncommented and its value is set to True
[root@master ~]# vim /etc/salt/master pillar_roots: base: - /srv/pillar/bash pillar_opts: True //Uncomment and change Fales to True. It is opened here to show the effect. It is recommended to keep it closed. [root@master ~]# systemctl restart salt-master.service [root@master ~]# salt 'minion01' pillar.items minion01: ---------- master: ---------- __cli: salt-master __role: master allow_minion_key_revoke: True
Specify the top file entry file
[root@master base]# pwd /srv/pillar/base [root@master base]# vim top.sls base: //Specify environment 'minion*': //Specify target - apache //Reference apache.sls [root@master base]# salt '*' pillar.items minion02: ---------- apache: test minion01: ---------- apache: httpd
Modify the apache status file under salt and reference the pilar data
[root@master base]# cat /srv/salt/base/web/apache/apache.sls apache-install: pkg.installed: - name: {{ pillar['apache'] }} apache-service: service.running: - name: {{ pillar['apache']}} - enable: True
Execute advanced status file
[root@master base]# salt '*' state.highstate minion02: ---------- ID: states Function: no.None Result: False Comment: No Top file or master_tops data matches found. Please see master log for details. Changes: Summary for minion02 ------------ Succeeded: 0 Failed: 1 ------------ Total states run: 1 Total run time: 0.000 ms minion01: ---------- ID: apache-install Function: pkg.installed Name: httpd Result: True Comment: All specified packages are already installed Started: 11:45:39.585376 Duration: 721.042 ms Changes: ---------- ID: apache-service Function: service.running Name: httpd Result: True Comment: The service httpd is already running Started: 11:45:40.310194 Duration: 115.002 ms Changes: Summary for minion01 ------------ Succeeded: 2 Failed: 0 ------------ Total states run: 2 Total run time: 836.044 ms ERROR: Minions returned with non-zero exit code