Ansible operation and maintenance automation

Posted by kennethl on Sun, 26 Dec 2021 18:56:13 +0100

Ansible overview

Ansbile is an it automation tool. It can configure the system, deploy software and coordinate more advanced IT tasks, such as continuous deployment and rolling update.

Ansible is suitable for managing enterprise IT infrastructure, from a small scale with a few hosts to an enterprise environment with thousands of instances. Ansible is also a simple automation language that perfectly describes the IT application infrastructure.

It has the following three characteristics:

  • Simple: reduce learning costs
  • Powerful: aligning the application lifecycle
  • Agent free: predictable, reliable and secure

Working with documents: https://releases.ansible.com/...

Install Ansible:

[root@ops ~]#  yum install epel-release
[root@ops ~]#  yum install ansible -y

  • Inventory: host information managed by Ansible, including IP address, SSH port, account number, password, etc
  • Modules: all tasks are completed by modules. You can also customize modules, such as frequently used scripts.
  • Plugins: use plug-ins to add Ansible core functions. It provides many plug-ins, and you can also customize plug-ins. For example, the connection plug-in is used to connect to the target host.
  • Playbooks: "script", which defines a series of tasks in a modular way for external unified calls. Ansible core functions.

Host list

[root@ops ~]# cat /etc/ansible/hosts 
[webservers]
192.168.1.101
192.168.1.102
192.168.1.103

Command line usage

Connect remote host authentication

SSH password authentication:

[root@ops ~]# cat /etc/ansible/hosts 
[webservers]
192.168.1.101 ansible_ssh_user=root ansible_ssh_pass='Admin@1234'
192.168.1.102 ansible_ssh_user=root ansible_ssh_pass='Admin@1234'
192.168.1.103 ansible_ssh_user=root ansible_ssh_pass='Admin@1234'

SSH key pair authentication:

[root@ops ~]# cat /etc/ansible/hosts 
[webservers]
192.168.1.101 ansible_ssh_user=root ansible_ssh_key=/root/.ssh/id_rsa 
192.168.1.102 ansible_ssh_user=root '
192.168.1.103 ansible_ssh_user=root 

You can also specify in the configuration file:
[defaults]
private_key_file = /root/.ssh/id_rsa  # Default path

Common options

optiondescribe
-C, --checkRun the check and do nothing
-e EXTRA_VARS,--extra-vars=EXTRA_VARSSet additional variable key=value
-u REMOTE_USER, --user=REMOTE_USERSSH connection user, default None
-k, --ask-passSSH connection user password
-b, --becomeThe default value is root
-K, --ask-become-passRight raising password

Command line usage

[root@ops ~]# ansible all -m ping
192.168.1.102 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
192.168.1.103 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
192.168.1.101 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}


[root@ops ~]# ansible all -m shell -a "ls /root" -u root -k
SSH password: 
192.168.1.102 | CHANGED | rc=0 >>
etcd-v3.4.13-linux-amd64
etcd-v3.4.13-linux-amd64.tar.gz
192.168.1.101 | CHANGED | rc=0 >>
ca.cer
cfssl-certinfo_linux-amd64
cfssljson_linux-amd64
cfssl_linux-amd64
components.yaml
config.yaml
istio-1.11.4
istio-1.11.4-linux-amd64.tar.gz
transit.nolpay.ae.cer
192.168.1.103 | CHANGED | rc=0 >>

Common modules

Ansible doc – l view all modules

Ansible doc – s copy view module documentation

shell

Execute shell commands on the target host

[root@ops ~]# ansible all -m shell -a "chdir='/var/log/' ls -l | grep log"      
192.168.1.102 | CHANGED | rc=0 >>
-rw-------. 1 root root       0 Nov  4 03:17 boot.log
-rw-------. 1 root root    9219 Nov  4 03:17 boot.log-20211104
-rw-r--r--. 1 root root  292000 Nov 24 10:59 lastlog
-rw-------. 1 root root       0 Nov 21 03:16 maillog
-rw-------. 1 root root     198 Mar 31  2021 maillog-20211107
-rw-------. 1 root root       0 Nov  7 03:43 maillog-20211114
-rw-------. 1 root root       0 Nov 14 03:32 maillog-20211121
-rw-------. 1 root root       0 Mar 31  2021 tallylog
-rw-------. 1 root root    4480 Nov  4 14:21 yum.log
192.168.1.103 | CHANGED | rc=0 >>
-rw-------. 1 root root       0 Nov  5 03:45 boot.log
-rw-------. 1 root root    9305 Nov  4 03:14 boot.log-20211104
-rw-------  1 root root    8383 Nov  5 03:45 boot.log-20211105
-rw-r--r--. 1 root root  292000 Nov 24 10:59 lastlog
-rw-------  1 root root       0 Nov 21 03:40 maillog
-rw-------. 1 root root     424 Nov  4 14:27 maillog-20211107
-rw-------  1 root root       0 Nov  7 03:21 maillog-20211114
-rw-------  1 root root       0 Nov 14 03:49 maillog-20211121
-rw-------. 1 root root       0 Mar 31  2021 tallylog
-rw-------. 1 root root    4480 Nov  4 14:21 yum.log
192.168.1.101 | CHANGED | rc=0 >>
-rw-------.  1 root root        0 Nov  5 03:12 boot.log
-rw-------.  1 root root     9241 Nov  4 03:08 boot.log-20211104
-rw-------   1 root root     8294 Nov  5 03:12 boot.log-20211105
-rw-r--r--.  1 root root   292000 Nov 24 10:59 lastlog
-rw-------   1 root root        0 Nov 21 03:43 maillog
-rw-------.  1 root root      424 Nov  4 15:41 maillog-20211107
-rw-------   1 root root        0 Nov  7 03:31 maillog-20211114
-rw-------   1 root root        0 Nov 14 03:25 maillog-20211121
-rw-------.  1 root root        0 Mar 31  2021 tallylog
-rw-------.  1 root root     7792 Nov  4 14:43 yum.log

Parameter Description:

  • Chdir parameter: this parameter is used to specify a directory. Before executing the corresponding command, it will enter the directory specified by the chdir parameter
  • executable parameter: by default, the shell module will call / bin/sh in the remote host to execute the corresponding command. Generally, the default shell in the remote host is bash. If you want to use other types of shells to execute commands, you can use this parameter to specify a certain type of shell to execute the corresponding commands. When specifying a shell file, you need to use an absolute path
  • Remove parameter: use this parameter to specify a file. When the specified file does not exist, the corresponding command will not be executed
  • Create parameter: use this parameter to specify a file. When the specified file exists, the corresponding command will not be executed
  • free_form parameter: a required parameter, specifying the command to be executed remotely, but there is no specific parameter named free_form,

copy

Copy files to remote host

[root@ops ~]# ansible all -m copy -a "src=ArmsAgent.tar.gz dest=/tmp/"
192.168.1.103 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "checksum": "0b0fed4f40a4bf83fe174309e17273cdeedb9c2e", 
    "dest": "/tmp/ArmsAgent.tar.gz", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "08dcb6dbe63eeeb42628dfe9cc14e4e9", 
    "mode": "0644", 
    "owner": "root", 
    "size": 46325347, 
    "src": "/root/.ansible/tmp/ansible-tmp-1637724228.32-26808-199044113552898/source", 
    "state": "file", 
    "uid": 0
}
192.168.1.102 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "checksum": "0b0fed4f40a4bf83fe174309e17273cdeedb9c2e", 
    "dest": "/tmp/ArmsAgent.tar.gz", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "08dcb6dbe63eeeb42628dfe9cc14e4e9", 
    "mode": "0644", 
    "owner": "root", 
    "secontext": "unconfined_u:object_r:admin_home_t:s0", 
    "size": 46325347, 
    "src": "/root/.ansible/tmp/ansible-tmp-1637724228.61-26806-205389838720285/source", 
    "state": "file", 
    "uid": 0
}
192.168.1.101 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "checksum": "0b0fed4f40a4bf83fe174309e17273cdeedb9c2e", 
    "dest": "/tmp/ArmsAgent.tar.gz", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "08dcb6dbe63eeeb42628dfe9cc14e4e9", 
    "mode": "0644", 
    "owner": "root", 
    "size": 46325347, 
    "src": "/root/.ansible/tmp/ansible-tmp-1637724228.5-26804-266077367101765/source", 
    "state": "file", 
    "uid": 0
}


[root@ops ~]# ansible all -m copy -a "src=ArmsAgent.tar.gz dest=/tmp/ owner=root group=root mode=777"
192.168.1.102 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "checksum": "0b0fed4f40a4bf83fe174309e17273cdeedb9c2e", 
    "dest": "/tmp/ArmsAgent.tar.gz", 
    "gid": 0, 
    "group": "root", 
    "mode": "0777", 
    "owner": "root", 
    "path": "/tmp/ArmsAgent.tar.gz", 
    "secontext": "unconfined_u:object_r:admin_home_t:s0", 
    "size": 46325347, 
    "state": "file", 
    "uid": 0
}
192.168.1.103 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "checksum": "0b0fed4f40a4bf83fe174309e17273cdeedb9c2e", 
    "dest": "/tmp/ArmsAgent.tar.gz", 
    "gid": 0, 
    "group": "root", 
    "mode": "0777", 
    "owner": "root", 
    "path": "/tmp/ArmsAgent.tar.gz", 
    "size": 46325347, 
    "state": "file", 
    "uid": 0
}
192.168.1.101 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "checksum": "0b0fed4f40a4bf83fe174309e17273cdeedb9c2e", 
    "dest": "/tmp/ArmsAgent.tar.gz", 
    "gid": 0, 
    "group": "root", 
    "mode": "0777", 
    "owner": "root", 
    "path": "/tmp/ArmsAgent.tar.gz", 
    "size": 46325347, 
    "state": "file", 
    "uid": 0
}

Parameter Description:

  • src parameter: used to specify the file or directory to copy
  • dest parameter: used to specify which directory the file will be copied to the remote host. dest is a required parameter
  • Content parameter: when you do not use src to specify the copied file, you can use content to directly specify the file content. There must be one of src and content parameters, otherwise an error will be reported
  • Force parameter: whether to force overwrite when a file with the same name already exists in the target path of the remote host and its content is different from that in the ansible host. The optional values are yes and No. the default value is yes, which means overwrite. If it is set to no, the overwrite copy operation will not be performed, and the files in the remote host remain unchanged
  • backup parameter: whether to back up the files of the remote host when a file with the same name already exists in the target path of the remote host and its contents are different from those in the ansible host. The optional values are yes and no. when it is set to yes, the files in the remote host will be backed up first, and then the files in the ansible host will be copied to the remote host
  • Owner parameter: Specifies the owner of the file after it is copied to the remote host, but there must be a corresponding user on the remote host, otherwise an error will be reported
  • Group parameter: Specifies the group to which the file belongs after being copied to the remote host, but there must be a corresponding group on the remote host, otherwise an error will be reported
  • Mode parameter: Specifies the permission after the file is copied to the remote host. If you want to set the permission to "rw-r--r --", you can use mode=0644. If you want to add execution permission to the corresponding permission bit of user, you can use mode=u+x

file

Manage files and file properties

# create a file
[root@ops ~]# ansible all -m file -a "path=/tmp/kubesre state=touch"
192.168.1.103 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dest": "/tmp/kubesre", 
    "gid": 0, 
    "group": "root", 
    "mode": "0644", 
    "owner": "root", 
    "size": 0, 
    "state": "file", 
    "uid": 0
}
192.168.1.102 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dest": "/tmp/kubesre", 
    "gid": 0, 
    "group": "root", 
    "mode": "0644", 
    "owner": "root", 
    "secontext": "unconfined_u:object_r:user_tmp_t:s0", 
    "size": 0, 
    "state": "file", 
    "uid": 0
}
192.168.1.101 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dest": "/tmp/kubesre", 
    "gid": 0, 
    "group": "root", 
    "mode": "0644", 
    "owner": "root", 
    "size": 0, 
    "state": "file", 
    "uid": 0
}
[root@ops ~]# ansible all -m shell -a "ls -l /tmp/kubesre"
192.168.1.102 | CHANGED | rc=0 >>
-rw-r--r--. 1 root root 0 Nov 24 11:37 /tmp/kubesre
192.168.1.103 | CHANGED | rc=0 >>
-rw-r--r-- 1 root root 0 Nov 24 11:37 /tmp/kubesre
192.168.1.101 | CHANGED | rc=0 >>
-rw-r--r-- 1 root root 0 Nov 24 11:37 /tmp/kubesre

# Create directory
[root@ops ~]# ansible all -m file -a "path=/tmp/test state=directory"
192.168.1.103 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "gid": 0, 
    "group": "root", 
    "mode": "0755", 
    "owner": "root", 
    "path": "/tmp/test", 
    "size": 6, 
    "state": "directory", 
    "uid": 0
}
192.168.1.102 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "gid": 0, 
    "group": "root", 
    "mode": "0755", 
    "owner": "root", 
    "path": "/tmp/test", 
    "secontext": "unconfined_u:object_r:user_tmp_t:s0", 
    "size": 6, 
    "state": "directory", 
    "uid": 0
}
192.168.1.101 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "gid": 0, 
    "group": "root", 
    "mode": "0755", 
    "owner": "root", 
    "path": "/tmp/test", 
    "size": 6, 
    "state": "directory", 
    "uid": 0
}

[root@ops ~]# ansible all -m shell -a "ls -l /tmp"      
192.168.1.102 | CHANGED | rc=0 >>
total 45240
drwx------. 2 root root       41 Nov 24 11:48 ansible_command_payload_ceyqUR
-rwxrwxrwx. 1 root root 46325347 Nov 24 11:23 ArmsAgent.tar.gz
-rw-r--r--. 1 root root        0 Nov 24 11:37 kubesre
drwxr-xr-x. 2 root root        6 Nov 24 11:48 test
192.168.1.103 | CHANGED | rc=0 >>
total 45240
drwx------ 2 root root       41 Nov 24 11:48 ansible_command_payload_IyoZG8
-rwxrwxrwx 1 root root 46325347 Nov 24 11:23 ArmsAgent.tar.gz
-rw-r--r-- 1 root root        0 Nov 24 11:37 kubesre
drwxr-xr-x 2 root root        6 Nov 24 11:48 test
192.168.1.101 | CHANGED | rc=0 >>
total 45240
drwx------ 2 root root       41 Nov 24 11:48 ansible_command_payload_guMhZe
-rwxrwxrwx 1 root root 46325347 Nov 24 11:23 ArmsAgent.tar.gz
-rw-r--r-- 1 root root        0 Nov 24 11:37 kubesre
drwxr-xr-x 2 root root        6 Nov 24 11:48 test

# Delete directory
[root@ops ~]# ansible all -m file -a "path=/tmp/test state=absent"
192.168.1.103 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "path": "/tmp/test", 
    "state": "absent"
}
192.168.1.102 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "path": "/tmp/test", 
    "state": "absent"
}
192.168.1.101 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "path": "/tmp/test", 
    "state": "absent"
}

# modify attribute
[root@ops ~]# ansible all -m file -a "path=/tmp/kubesre mode=777"
192.168.1.103 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "gid": 0, 
    "group": "root", 
    "mode": "0777", 
    "owner": "root", 
    "path": "/tmp/kubesre", 
    "size": 0, 
    "state": "file", 
    "uid": 0
}
192.168.1.102 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "gid": 0, 
    "group": "root", 
    "mode": "0777", 
    "owner": "root", 
    "path": "/tmp/kubesre", 
    "secontext": "unconfined_u:object_r:user_tmp_t:s0", 
    "size": 0, 
    "state": "file", 
    "uid": 0
}
192.168.1.101 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "gid": 0, 
    "group": "root", 
    "mode": "0777", 
    "owner": "root", 
    "path": "/tmp/kubesre", 
    "size": 0, 
    "state": "file", 
    "uid": 0
}

Parameter Description:

  • path: the file or directory to operate on
  • State: this parameter is very flexible. The corresponding value of this parameter needs to be set according to the situation. For example, when we need to create a directory in the remote host, we need to use the path parameter to specify the corresponding directory path. Assuming that I want to create the / testdir/a/b directory on the remote host, I need to set path=/testdir/a/b, We can't tell whether B is a file or a directory from the path "/ testdir/a/b". Similarly, ansible can't know whether you want to create a file or directory from a string alone. Therefore, we need to explain it through the state parameter. When the / testdir/a/b we want to create is a directory, we need to set the value of state to directory, "directory" means directory, When it is combined with path, ansible can know that the target we want to operate is a directory. Similarly, when the / testdir/a/b we want to operate is a file, we need to set the value of state to touch. When we want to create a soft link file, we need to set state to link. When we want to create a hard link file, we need to set state to hard, When we want to delete a file (regardless of whether the target is a file, directory or link), we need to set the value of state to absent, "absent" means absence. When we want the target of the operation to be "absent", it means that we want to delete the target
  • src: when the state is set to link or hard, it means that we want to create a soft chain or hard chain. Therefore, we must specify which file is linked by the soft chain or hard chain. The link source can be specified through the src parameter.
  • Force: when state=link, you can use this parameter to force the creation of a link file. When force=yes, it means that you force the creation of a link file. However, there are two cases of forced creation of a link file. Case 1: when the source file pointed to by the link file you want to create does not exist, you can use this parameter to force the creation of a link file first. Case 2: when a file with the same name as the linked file already exists in the directory where you want to create the linked file, set force to yes and overwrite the file with the same name as the linked file, which is equivalent to deleting the file with the same name and creating the linked file. Case 3: when a file with the same name as the linked file already exists in the directory where you want to create the linked file, and the source file pointed to by the linked file does not exist, the file with the same name will be forcibly replaced with the linked file.
  • Owner: used to specify the owner of the operated file. The user corresponding to the owner must exist in the remote host, otherwise an error will be reported.
  • Group: used to specify the group of the operated file. The group corresponding to the group must exist in the remote host, otherwise an error will be reported.
  • Mode: used to specify the permission of the operated file. For example, if you want to set the file permission to "rw-r-x" -, you can use mode=650 or mode=0650. The effect is the same. If you want to set special permissions, such as suid for binary files, you can use mode=4700, which is very convenient.
  • Recurse: when the file to be operated is a directory, set recurse to yes to recursively modify the attributes of the files in the directory.
  • absent: indicates uninstall

yum

Software package management

# Installing Nginx
[root@ops ~]# ansible all -m yum -a "name=http://nginx.org/packages/rhel/7/x86_64/RPMS/nginx-1.16.1-1.el7.ngx.x86_64.rpm state=present"

# Uninstall Nginx
[root@ops ~]# ansible all -m yum -a "name=nginx state=absent"

# Update all packages
[root@ops ~]# ansible all -m yum -a "name='*' state=latest" 

service/systemd

management service

[root@ops ~]# ansible all -m systemd -a "name=nginx state=restarted enabled=yes"

unarchive

Extract to the specified directory of the remote machine

[root@ops ~]# ansible all -m unarchive -a "src=ArmsAgent.tar.gz dest=/tmp"
192.168.1.103 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dest": "/tmp", 
    "extract_results": {
        "cmd": [
            "/usr/bin/gtar", 
            "--extract", 
            "-C", 
            "/tmp", 
            "-z", 
            "-f", 
            "/root/.ansible/tmp/ansible-tmp-1637734297.88-28601-94567791333261/source"
        ], 
        "err": "", 
        "out": "", 
        "rc": 0
    }, 
    "gid": 0, 
    "group": "root", 
    "handler": "TgzArchive", 
    "mode": "01777", 
    "owner": "root", 
    "size": 240, 
    "src": "/root/.ansible/tmp/ansible-tmp-1637734297.88-28601-94567791333261/source", 
    "state": "directory", 
    "uid": 0
}
192.168.1.102 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dest": "/tmp", 
    "extract_results": {
        "cmd": [
            "/usr/bin/gtar", 
            "--extract", 
            "-C", 
            "/tmp", 
            "-z", 
            "-f", 
            "/root/.ansible/tmp/ansible-tmp-1637734298.15-28599-160150628668658/source"
        ], 
        "err": "", 
        "out": "", 
        "rc": 0
    }, 
    "gid": 0, 
    "group": "root", 
    "handler": "TgzArchive", 
    "mode": "01777", 
    "owner": "root", 
    "secontext": "system_u:object_r:tmp_t:s0", 
    "size": 240, 
    "src": "/root/.ansible/tmp/ansible-tmp-1637734298.15-28599-160150628668658/source", 
    "state": "directory", 
    "uid": 0
}
192.168.1.101 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dest": "/tmp", 
    "extract_results": {
        "cmd": [
            "/usr/bin/gtar", 
            "--extract", 
            "-C", 
            "/tmp", 
            "-z", 
            "-f", 
            "/root/.ansible/tmp/ansible-tmp-1637734298.01-28597-226262773743899/source"
        ], 
        "err": "", 
        "out": "", 
        "rc": 0
    }, 
    "gid": 0, 
    "group": "root", 
    "handler": "TgzArchive", 
    "mode": "01777", 
    "owner": "root", 
    "size": 240, 
    "src": "/root/.ansible/tmp/ansible-tmp-1637734298.01-28597-226262773743899/source", 
    "state": "directory", 
    "uid": 0
}

debug

Print statements during execution

- debug:
    msg: System {{ inventory_hostname }} has uuid {{ ansible_product_uuid }}

- name: Displays all variables known to the host
  debug:
    var: hostvars[inventory_hostname]
    verbosity: 4

variable

Variables are a convenient way to apply to multiple hosts. Before the host executes, variables are added to each host and then referenced during execution.

Host and group variables

[webservers]  # Host variable
192.168.1.101 hostname=web1
192.168.1.102 hostname=web2
192.168.1.103 hostname=web3

[webservers:vars]   # Group variable
group=webservers

Register variable

- shell: /usr/bin/uptime
  register: result
- debug:
    var: result
    verbosity: 2

Playbook

Playbooks is Ansible's configuration, deployment and orchestration language. They can describe what you want to do on a remote machine or describe a series of steps in an IT process. Organize Playbook files in a readable YAML format.

If the Ansible module is a tool in your work, the Playbook is your user manual, and your host asset file is your raw material.

Compared with ad hoc task execution mode, Playbooks uses ansible in a completely different way and is particularly powerful.

https://docs.ansible.com/ansi...

---
- hosts: webservers
  vars:
    http_port: 80
    server_name: www.kubesre.com
  remote_user: root
  gather_facts: false
  tasks:
  - name: install nginx the latest version
    yum: pkg=nginx state=latest
  - name: write in nginx configuration file
    template: src=/srv/httpd.j2 dest=/etc/nginx/nginx.conf
    notify:
    - restart nginx
  - name: ensure nginx Running
    service: name=httpd state=started
  handlers:
    - name: restart nginx
      service: name=nginx state=reloaded

Hosts and users

- hosts: webservers
  remote_user: root
  become: yes
  become_user: nginx

Explanation:

  • become: whether to carry out the right raising operation. Set to yes if necessary
  • become_user: set as the user with the required privileges - the user you want to be, not the user you log in with
  • become_method: permission tools, such as sudo, su, pfexec, doas, pbrun, dzdo, ksu, runas, machinectl
  • become_flags: at the play or task level, specific flags are allowed for tasks or roles. A common usage is to change the user to nobody when the shell is set to no login. This instruction was added in Ansible 2.2.

Define variables

The preferred practice in Ansible is not to store variables in Inventory.

In addition to storing variables directly in the Inventory file, host and group variables can also be stored in a single file relative to the Inventory file.

- hosts: webservers
  vars:
    http_port: 80
    server_name: www.kubesre.com

task list

Each play contains a series of tasks. These tasks are executed in order. In play, all hosts will execute the same task instructions. The purpose of play is to map the selected host to the task.

tasks:
  - name: install nginx the latest version
    yum: pkg=nginx state=latest

Syntax checking and debugging

Syntax check: ansible playbook -- check / path / to / playbook yaml

Test run, not actual operation: ansible playbook - C / path / to / playbook yaml

The debug module prints statements during execution without stopping play for debugging variables or expressions. It is better to debug with the 'when:' instruction.

- hosts: webserver
tasks:
- debug:
msg: {{group_names}}
- debug:
msg: {{inventory_hostname}}
- debug:
msg: {{ansible_hostname}}

Task control

If you have a large script, it may be useful to be able to run specific parts without running the whole script.

tasks:
  - name: install nginx the latest version
    yum: pkg=nginx state=latest
    tags: install
  - name: write in nginx configuration file
    template: src=/srv/httpd.j2 dest=/etc/nginx/nginx.conf
    tags: config

use:

ansible-playbook example.yml --tags "install"
ansible-playbook example.yml --tags "install,config"
ansible-playbook example.yml --skip-tags "install"

Process control

Conditions:

tasks:
- name: Only in 192.168.1.100 Run task
  debug: msg="{{ansible_default_ipv4.address}}"
  when: ansible_default_ipv4.address == '192.168.1.100'

Cycle:

tasks:
- name:  Batch create user
  user: name={{ item }} state=present groups=wheel
  with_items:
     - testuser1
     - testuser2
- name: decompression
  copy: src={{ item }} dest=/tmp
  with_fileglob:
    - "*.txt"

Common loop statements:

sentencedescribe
with_itemsStandard cycle
with_fileglobTraverse directory files
with_dictTraversal dictionary

Template

tasks:
  - name: write in nginx configuration file
    template: src=/srv/httpd.j2 dest=/etc/nginx/nginx.conf

Define variables

{% set local_ip = inventory_hostname %}

Conditions and cycles:

{% set list=['one', 'two', 'three'] %}
{% for i in list %}
    {% if i == 'two' %}
        -> two
    {% elif loop.index == 3 %}
        -> 3
    {% else %}
        {{i}}
    {% endif %}
{% endfor %}

For example: generate connection etcd string

{% for host in groups['etcd'] %}
    https://{{ hostvars[host].inventory_hostname }}:2379
    {% if not loop.last %},{% endif %}
{% endfor %} 

You can also use ansible variables.

Roles

Roles is a method of automatically loading certain variable files, tasks and handlers based on known file structures. Grouping content by role is suitable for building complex deployment environments.

Define Roles

Roles directory structure:

site.yml
webservers.yml
fooservers.yml
roles/
   common/
     tasks/
     handlers/
     files/
     templates/
     vars/
     defaults/
     meta/
   webservers/
     tasks/
     defaults/
     meta/
  • Tasks - contains the main list of tasks to be performed by the role.
  • Handlers - contains handlers that can be used by this role even anywhere outside this role.
  • defaults - the default variable for the role
  • vars - other variables of the role
  • Files - contains files that can be deployed through this role.
  • Templates - contains templates that can be deployed through this role.
  • meta - defines some metadata for this role. See more details below.

The usual approach is to start from tasks / main The YML file contains platform specific tasks:

# roles/webservers/tasks/main.yml
- name: added in 2.4, previously you used 'include'
  import_tasks: redhat.yml
  when: ansible_facts['os_family']|lower == 'redhat'
- import_tasks: debian.yml
  when: ansible_facts['os_family']|lower == 'debian'

# roles/webservers/tasks/redhat.yml
- yum:
    name: "httpd"
    state: present

# roles/webservers/tasks/debian.yml
- apt:
    name: "apache2"
    state: present

Use role

# site.yml
- hosts: webservers
  roles:
    - common
    - webservers


Define multiple:
- name: 0
  gather_facts: false
  hosts: all 
  roles:
    - common

- name: 1
  gather_facts: false
  hosts: all 
  roles:
    - webservers

Role control

- name: 0.System initialization
  gather_facts: false
  hosts: all 
  roles:
    - common
  tags: common 

Define variables

Group variables:
group_vars It stores a group of variables
group_vars/all.yml  Indicates that all hosts are valid, equivalent to[all:vars]
grous_vars/etcd.yml express etcd Group host valid, equivalent to[etcd:vars]

Click“ Read the original text "Get a better reading experience!

Topics: Linux Operation & Maintenance